Esempio n. 1
0
        private static ChanCtrl ReadChannelControl(EndianBinaryReader stream)
        {
            var retVal = new ChanCtrl
            {
                Enable              = stream.ReadBoolean(),
                MaterialSrc         = (GXColorSrc)stream.ReadByte(),
                LitMask             = (GXLightId)stream.ReadByte(),
                DiffuseFunction     = (GXDiffuseFn)stream.ReadByte(),
                AttenuationFunction = (GXAttenuationFn)stream.ReadByte(),
                AmbientSrc          = (GXColorSrc)stream.ReadByte()
            };

            Trace.Assert(stream.ReadUInt16() == 0xFFFF); // Padding
            return(retVal);
        }
Esempio n. 2
0
        public Material(ref EndianBinaryReader reader)
        {
            base.setType(Type.Wii);

            mMaterialName = reader.ReadString(0x14).Replace("\0", "");

            mForeColor = reader.ReadRGBAColor16();
            mBackColor = reader.ReadRGBAColor16();
            mColorReg3 = reader.ReadRGBAColor16();
            mTevColor1 = reader.ReadRGBAColor8();
            mTevColor2 = reader.ReadRGBAColor8();
            mTevColor3 = reader.ReadRGBAColor8();
            mTevColor4 = reader.ReadRGBAColor8();
            mFlags     = reader.ReadUInt32();

            mHasMaterialColor  = Convert.ToBoolean(ExtractBits(mFlags, 1, 4));
            mHasChannelControl = Convert.ToBoolean(ExtractBits(mFlags, 1, 6));
            mHasBlendMode      = Convert.ToBoolean(ExtractBits(mFlags, 1, 7));
            mHasAlphaCompare   = Convert.ToBoolean(ExtractBits(mFlags, 1, 8));
            mTevStageCount     = ExtractBits(mFlags, 5, 9);
            mIndTexStageCount  = ExtractBits(mFlags, 3, 14);
            mIndTexSRTCount    = ExtractBits(mFlags, 2, 17);
            mHasTevSwapTable   = Convert.ToBoolean(ExtractBits(mFlags, 1, 19));
            mTexCoordGenCount  = ExtractBits(mFlags, 4, 20);
            mTexSRTCount       = ExtractBits(mFlags, 4, 24);
            mTexMapCount       = ExtractBits(mFlags, 4, 28);

            mTexMaps = new List <TexMap>();

            for (int i = 0; i < mTexMapCount; i++)
            {
                mTexMaps.Add(new TexMap(ref reader));
            }

            mTexSRTs = new List <TexSRT>();

            for (int i = 0; i < mTexSRTCount; i++)
            {
                mTexSRTs.Add(new TexSRT(ref reader));
            }

            mTexCoordGens = new List <TexCoordGen>();

            for (int i = 0; i < mTexCoordGenCount; i++)
            {
                mTexCoordGens.Add(new TexCoordGen(ref reader));
            }

            if (mHasChannelControl)
            {
                mChanCtrl = new ChanCtrl(ref reader);
            }

            if (mHasMaterialColor)
            {
                mMaterialColor = reader.ReadRGBAColor8();
            }

            if (mHasTevSwapTable)
            {
                mTevSwapTable = new TevSwapTable(ref reader);
            }

            mIndTexSRT = new List <IndTexSRT>();

            for (int i = 0; i < mIndTexSRTCount; i++)
            {
                mIndTexSRT.Add(new IndTexSRT(ref reader));
            }

            mIndTexStages = new List <IndTexStage>();

            for (int i = 0; i < mIndTexStageCount; i++)
            {
                mIndTexStages.Add(new IndTexStage(ref reader));
            }

            mTevStages = new List <TevStage>();

            for (int i = 0; i < mTevStageCount; i++)
            {
                mTevStages.Add(new TevStage(ref reader));
            }

            if (mHasAlphaCompare)
            {
                mAlphaCompare = new AlphaCompare(ref reader);
            }

            if (mHasBlendMode)
            {
                mBlendMode = new BlendMode(ref reader);
            }
        }
Esempio n. 3
0
        private static string GetLightCalcString(ChanCtrl chanInfo, bool alpha)
        {
            // If the lighting channel is disabled, the material color for that channel will be passed through unmodified.
            if (!chanInfo.Enable)
            {
                return("0.5f");
            }

            //string matColorSrc = (chanInfo.MaterialSrc == GXColorSrc.Vertex) ? "RawColor" : "matColor";

            // Up to 8 possible lights.
            for (int i = 0; i < 8; i++)
            {
                if (((int)chanInfo.LitMask & (int)(GXLightId)i) != 0)
                {
                    // I don't think this is right
                }
            }

            if (chanInfo.LitMask == 0)
            {
                return("0.0f");
            }
            else
            {
                return("0.5f");
            }

            // Pre-lighting - hardware-computed local diffuse lighting with baked vertex lighting.
            // lit_color = pre_lit_color * (ambient_scale + diffuse_scale * other_attenuation * diffuse_lit_color)
            // ambient_scale + diffuse_scale = 1.0;
            // When no diffuse light is present, the color is equal to the ambient pre-lit color (pre_lit_color * ambient_scale).
            // When a light is shining on an object, the percentage of pre_lit_color is increased until, at brightest, the full value of pre_lit_color is used.
            // This requires some calculation based on the locaton in the level to nearby point lights.

            // Specular lighting - if if chanInfo.AttenuationFunction is set to GXAttenuationFn.Spec.
            // See GX.pdf - pg 62

            /*switch (chanInfo.DiffuseFunction)
             * {
             *  case GXDiffuseFn.None:
             *      break;
             *  case GXDiffuseFn.Signed:
             *      break;
             *  case GXDiffuseFn.Clamp:
             *      break;
             *  default:
             *      break;
             * }
             *
             * switch (chanInfo.AttenuationFunction)
             * {
             *  case GXAttenuationFn.None:
             *      break;
             *  case GXAttenuationFn.Spec:
             *      break;
             *  case GXAttenuationFn.Spot:
             *      break;
             *  default:
             *      break;
             * }*/
        }
Esempio n. 4
0
        public static bool GenerateVertexShader(Shader shader, Material mat)
        {
            StringBuilder stream = new StringBuilder();

            // Shader Header
            stream.AppendLine("#version 330 core");
            stream.AppendLine();

            // Input Format
            stream.AppendLine("// Input");
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Position))
            {
                stream.AppendLine("in vec3 RawPosition;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Normal))
            {
                stream.AppendLine("in vec3 RawNormal;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Color0))
            {
                stream.AppendLine("in vec4 RawColor0;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Color1))
            {
                stream.AppendLine("in vec4 RawColor1;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Tex0))
            {
                stream.AppendLine("in vec2 RawTex0;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Tex1))
            {
                stream.AppendLine("in vec2 RawTex1;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Tex2))
            {
                stream.AppendLine("in vec2 RawTex2;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Tex3))
            {
                stream.AppendLine("in vec2 RawTex3;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Tex4))
            {
                stream.AppendLine("in vec2 RawTex4;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Tex5))
            {
                stream.AppendLine("in vec2 RawTex5;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Tex6))
            {
                stream.AppendLine("in vec2 RawTex6;");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Tex7))
            {
                stream.AppendLine("in vec2 RawTex7;");
            }

            stream.AppendLine();

            // Output Format
            stream.AppendLine("// Output");
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Normal))
            {
                stream.AppendLine("out vec3 Normal;");
            }

            for (int i = 0; i < mat.NumChannelControls; i++)
            {
                stream.AppendLine(string.Format("out vec4 Color{0};", i));
            }

            for (int texGen = 0; texGen < mat.NumTexGens; texGen++)
            {
                if (mat.TexGenInfos[texGen] != null)
                {
                    stream.AppendLine(string.Format("out vec3 Tex{0};", texGen));
                }
            }

            // Uniforms
            stream.AppendLine();
            stream.AppendLine("// Uniforms");
            stream.AppendLine(
                "   uniform mat4 ModelMtx;\n" +
                "   uniform mat4 ViewMtx;\n" +
                "   uniform mat4 ProjMtx;\n" +
                "\n" +

                "   uniform mat4 TexMtx[10];\n" +
                "   uniform mat4 PostMtx[20];\n" +
                "   uniform vec4 COLOR0_Amb;\n" +
                "   uniform vec4 COLOR0_Mat;\n" +
                "   uniform vec4 COLOR1_Amb;\n" +
                "   uniform vec4 COLOR1_Mat;\n" +
                "\n" +
                "struct GXLight\n" +
                "{\n" +
                "   vec4 Position;\n" +
                "   vec4 Direction;\n" +
                "   vec4 Color;\n" +
                "   vec4 DistAtten;\n" +
                "   vec4 AngleAtten;\n" +
                "};\n" +
                "\n" +

                "   GXLight Lights[8];\n" +
                "\n" +
                "uniform int NumLights;\n" +
                "uniform vec4 ambLightColor;\n");

            // Main Shader Code
            stream.AppendLine("// Main");
            stream.AppendLine("void main()");
            stream.AppendLine("{");
            stream.AppendLine("    mat4 MVP = ProjMtx * ViewMtx * ModelMtx;");
            stream.AppendLine("    mat4 MV = ViewMtx * ModelMtx;");

            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Position))
            {
                stream.AppendLine("    gl_Position = MVP * vec4(RawPosition, 1);");
            }
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Normal))
            {
                stream.AppendLine("    Normal = normalize(RawNormal.xyz * inverse(transpose(mat3(MV))));");
            }
            //if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Color0))
            //  stream.AppendLine("    Color0 = RawColor0;");
            //if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Color1))
            //stream.AppendLine("    Color1 = RawColor1;");

            stream.AppendLine();
            stream.AppendLine("    // Ambient Colors & Material Colors");
            // Add the Ambient Colors for the Material
            for (int a = 0; a < mat.AmbientColors.Length; a++)
            {
                stream.AppendLine(string.Format("    vec4 ambColor{0} = vec4({1}, {2}, {3}, {4});", a, mat.AmbientColors[a].R, mat.AmbientColors[a].G, mat.AmbientColors[a].B, mat.AmbientColors[a].A));
            }

            // Add in the Material Colors
            for (int m = 0; m < mat.MaterialColors.Length; m++)
            {
                stream.AppendLine(string.Format("    vec4 matColor{0} = vec4({1}, {2}, {3}, {4});", m, mat.MaterialColors[m].R, mat.MaterialColors[m].G, mat.MaterialColors[m].B, mat.MaterialColors[m].A));
            }

            stream.AppendLine();
            stream.AppendLine(string.Format("    // ChanCtrl's - {0} count", mat.NumChannelControls));

            // Channel Controllers
            // A vertex can have up to two color channels (RGBA each) which gives us four possible channels:
            // color0, color1, alpha0, alpha1
            // Each channel has an associated ambient color/alpha and a material color/alpha. These can come
            // from vertex colors or existing amb/mat registers.
            for (int chanSel = 0; chanSel < mat.NumChannelControls; chanSel++)
            {
                ChanCtrl chanInfo = mat.ChannelControls[chanSel];
                string   chanTarget, ambColor, matColor, ambLight, diffLight;
                string   swizzle, chan;
                bool     alpha;

                // Todo: Is this really a fixed order?
                switch (chanSel)
                {
                case /* Color0 */ 0: chan = "0"; swizzle = ".rgb"; alpha = false; break;

                case /* Alpha0 */ 1: chan = "0"; swizzle = ".a"; alpha = true; break;

                case /* Color1 */ 2: chan = "1"; swizzle = ".rgb"; alpha = false; break;

                case /* Alpha1 */ 3: chan = "1"; swizzle = ".a"; alpha = true; break;

                default:
                    WLog.Warning(LogCategory.TEVShaderGenerator, shader, "Unknown vertex output color channel {0}, skipping.", chanSel);
                    continue;
                }

                chanTarget = string.Format("Color{0}{1}", chan, swizzle);
                ambColor   = (chanInfo.AmbientSrc == GXColorSrc.Vertex ? "RawColor" : "ambColor") + chan + swizzle;
                matColor   = (chanInfo.MaterialSrc == GXColorSrc.Vertex ? "RawColor" : "matColor") + chan + swizzle;
                ambLight   = "ambLightColor" + swizzle;
                diffLight  = GetLightCalcString(chanInfo, alpha);

                //Color{0}.rgb = ambient * ambLightColor * light
                stream.AppendLine(string.Format("    Color{0} = vec4(1, 1, 1, 1);", chan));
                if (chanInfo.Enable)
                {
                    stream.AppendLine(string.Format("    {0} = {1} * {2} + {3} * {4};", chanTarget, ambColor, ambLight, matColor, diffLight));
                }
                else
                {
                    stream.AppendLine(string.Format("    {0} = {1};", chanTarget, matColor));
                }

                stream.AppendLine();
                stream.AppendLine();
            }


            // Texture Coordinate Generation
            stream.AppendLine(string.Format("    // TexGen - {0} count", mat.NumTexGens));
            for (int i = 0; i < mat.NumTexGens; i++)
            {
                if (mat.TexGenInfos[i] == null)
                {
                    continue;
                }

                TexCoordGen texGen = mat.TexGenInfos[i];
                string      texGenSrc;

                switch (texGen.Source)
                {
                case GXTexGenSrc.Position: texGenSrc = "RawPosition"; break;

                case GXTexGenSrc.Normal: texGenSrc = "RawNormal"; break;

                case GXTexGenSrc.Color0: texGenSrc = "Color0"; break;

                case GXTexGenSrc.Color1: texGenSrc = "Color1"; break;

                case GXTexGenSrc.Tex0: texGenSrc = "RawTex0"; break;     // Should Tex0 be TEXTURE 0? Or is it TEX0 = Input TEX0, while TEXCOORD0 = Output TEX0?

                case GXTexGenSrc.Tex1: texGenSrc = "RawTex1"; break;

                case GXTexGenSrc.Tex2: texGenSrc = "RawTex2"; break;

                case GXTexGenSrc.Tex3: texGenSrc = "RawTex3"; break;

                case GXTexGenSrc.Tex4: texGenSrc = "RawTex4"; break;

                case GXTexGenSrc.Tex5: texGenSrc = "RawTex5"; break;

                case GXTexGenSrc.Tex6: texGenSrc = "RawTex6"; break;

                case GXTexGenSrc.Tex7: texGenSrc = "RawTex7"; break;

                case GXTexGenSrc.TexCoord0: texGenSrc = "Tex0"; break;

                case GXTexGenSrc.TexCoord1: texGenSrc = "Tex1"; break;

                case GXTexGenSrc.TexCoord2: texGenSrc = "Tex2"; break;

                case GXTexGenSrc.TexCoord3: texGenSrc = "Tex3"; break;

                case GXTexGenSrc.TexCoord4: texGenSrc = "Tex4"; break;

                case GXTexGenSrc.TexCoord5: texGenSrc = "Tex5"; break;

                case GXTexGenSrc.TexCoord6: texGenSrc = "Tex6"; break;

                case GXTexGenSrc.Tangent:
                case GXTexGenSrc.Binormal:
                default:
                    WLog.Warning(LogCategory.TEVShaderGenerator, shader, "Unsupported TexGenSrc: {0}, defaulting to TEXCOORD0.", texGen.Source);
                    texGenSrc = "Tex0";
                    break;
                }

                if (texGen.TexMatrixSource == GXTexMatrix.Identity)
                {
                    switch (texGen.Type)
                    {
                    case GXTexGenType.Matrix2x4:
                        stream.AppendLine(string.Format("    Tex{0} = vec3({1}.xy, 0);", i, texGenSrc));
                        break;

                    case GXTexGenType.Matrix3x4:
                        stream.AppendLine(string.Format("    float3 uvw = {0}.xyz;", texGenSrc));
                        stream.AppendLine(string.Format("    Tex{0} = vec3((uvw / uvw.z).xy,0);", i));
                        break;

                    case GXTexGenType.SRTG:
                        stream.AppendLine(string.Format("    Tex{0} = vec3({1}.rg, 0);", i, texGenSrc));
                        break;

                    case GXTexGenType.Bump0:
                    case GXTexGenType.Bump1:
                    case GXTexGenType.Bump2:
                    case GXTexGenType.Bump3:
                    case GXTexGenType.Bump4:
                    case GXTexGenType.Bump5:
                    case GXTexGenType.Bump6:
                    case GXTexGenType.Bump7:
                    default:
                        WLog.Warning(LogCategory.TEVShaderGenerator, shader, "Unsupported TexMatrixSource: {0}, Defaulting to Matrix2x4", texGen.TexMatrixSource);
                        stream.AppendLine(string.Format("    Tex{0} = vec3({1}.xy, 0);", i, texGenSrc));
                        break;
                    }
                }
                else
                {
                    // Convert to TexMtx0 to TexMtx9
                    int matIndex = ((int)texGen.TexMatrixSource - 30) / 3;
                    switch (texGen.Type)
                    {
                    default:
                        WLog.Warning(LogCategory.TEVShaderGenerator, shader, "Unsupported TexMatrixSource");
                        break;
                    }
                }
            }

            stream.AppendLine("}");
            stream.AppendLine();

            // Compile the Vertex Shader and return whether it compiled sucesfully or not.
            Directory.CreateDirectory("ShaderDump");
            System.IO.File.WriteAllText("ShaderDump/" + mat.Name + "_vert_output", stream.ToString());
            return(shader.CompileSource(stream.ToString(), OpenTK.Graphics.OpenGL.ShaderType.VertexShader));
        }