private static bool GenerateFragmentShader(Shader shader, Material mat)
        {
            StringBuilder stream = new StringBuilder();

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

            // Configure inputs to match our outputs from VS
            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Position))
            {
                stream.AppendLine("in vec3 Position;");
            }

            if (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Normal))
            {
                stream.AppendLine("in vec3 Normal;");
            }

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

            for (int texGen = 0; texGen < mat.NumTexGens; texGen++)
            {
                stream.AppendLine(string.Format("in vec3 Tex{0};", texGen));
            }

            stream.AppendLine();

            // Final Output
            stream.AppendLine("// Final Output");
            stream.AppendLine("out vec4 PixelColor;");

            // Texture Inputs
            for (int i = 0; i < 8; i++)
            {
                if (mat.Textures[i] == null)
                {
                    continue;
                }

                stream.AppendLine(string.Format("uniform sampler2D Texture{0};", i));
            }

            // Main Function
            stream.AppendLine("void main()");
            stream.AppendLine("{");

            // Default initial values of the TEV registers.
            // ToDo: Does this need swizzling? themikelester has it marked as mat.registerColor[i==0?3:i-1]]
            stream.AppendLine("    // Initial TEV Register Values");
            for (int i = 0; i < 4; i++)
            {
                stream.AppendLine(string.Format("    vec4 {0} = vec4({1}, {2}, {3}, {4});", m_tevOutputRegs[i], mat.TevColor[i].R, mat.TevColor[i].G, mat.TevColor[i].B, mat.TevColor[i].A));
            }
            stream.AppendLine();

            // Constant Color Registers
            stream.AppendLine("    // Konst TEV Colors");
            for (int i = 0; i < 4; i++)
            {
                stream.AppendLine(string.Format("    vec4 konst{0} = vec4({1}, {2}, {3}, {4});", i, mat.TevKonstColors[i].R, mat.TevKonstColors[i].G, mat.TevKonstColors[i].B, mat.TevKonstColors[i].A));
            }
            stream.AppendLine();

            // Texture Samples
            bool[] oldCombos = new bool[256];
            for (int i = 0; i < mat.NumTevStages; i++)
            {
                TevOrder       order = mat.TevOrderInfos[i];
                int            tex   = order.TexMap;
                GXTexCoordSlot coord = order.TexCoordId;

                // This TEV probably doesn't use textures.
                if (tex == 0xFF || coord == GXTexCoordSlot.Null)
                {
                    continue;
                }

                if (IsNewTexCombo(tex, (int)coord, oldCombos))
                {
                    string swizzle = ""; // Uhh I don't know if we need to swizzle since everyone's been converted into ARGB
                    stream.AppendLine(string.Format("    vec4 texCol{0} = texture(Texture{0}, Tex{1}.xy){2};", tex, (int)coord, swizzle));
                }
            }
            stream.AppendLine();

            // ToDo: Implement indirect texturing.
            stream.AppendLine("    // TEV Stages");
            stream.AppendLine();
            stream.AppendLine();

            for (int i = 0; i < mat.NumTevStages; i++)
            {
                stream.AppendLine(string.Format("    // TEV Stage {0}", i));
                TevOrder order = mat.TevOrderInfos[i];
                TevStage stage = mat.TevStageInfos[i];

                TevSwapMode      swap     = mat.TevSwapModes[i];
                TevSwapModeTable rasTable = mat.TevSwapModeTables[swap.RasSel];
                TevSwapModeTable texTable = mat.TevSwapModeTables[swap.TexSel];

                // There's swapping involved in the ras table.
                stream.AppendLine(string.Format("    // Rasterization Swap Table: {0}", rasTable));
                if (!(rasTable.R == 0 && rasTable.G == 1 && rasTable.B == 2 && rasTable.A == 3))
                {
                    stream.AppendLine(string.Format("    {0} = {1}{2};", GetVertColorString(order), GetVertColorString(order), GetSwapModeSwizzleString(rasTable)));
                }
                stream.AppendLine();


                // There's swapping involved in the texture table.
                stream.AppendLine(string.Format("    // Texture Swap Table: {0}", texTable));
                if (!(texTable.R == 0 && texTable.G == 1 && texTable.B == 2 && texTable.A == 3))
                {
                    stream.AppendLine(string.Format("    {0} = {1}{2};", GetTexTapString(order), GetTexTapString(order), GetSwapModeSwizzleString(rasTable)));
                }
                stream.AppendLine();

                string[] colorInputs = new string[4];
                colorInputs[0] = GetColorInString(stage.ColorIn[0], mat.KonstColorSels[i], order);
                colorInputs[1] = GetColorInString(stage.ColorIn[1], mat.KonstColorSels[i], order);
                colorInputs[2] = GetColorInString(stage.ColorIn[2], mat.KonstColorSels[i], order);
                colorInputs[3] = GetColorInString(stage.ColorIn[3], mat.KonstColorSels[i], order);

                stream.AppendLine("    // Color and Alpha Operations");
                stream.AppendLine(string.Format("    {0}", GetColorOpString(stage.ColorOp, stage.ColorBias, stage.ColorScale, stage.ColorClamp, stage.ColorRegId, colorInputs)));

                string[] alphaInputs = new string[4];
                alphaInputs[0] = GetAlphaInString(stage.AlphaIn[0], mat.KonstAlphaSels[i], order);
                alphaInputs[1] = GetAlphaInString(stage.AlphaIn[1], mat.KonstAlphaSels[i], order);
                alphaInputs[2] = GetAlphaInString(stage.AlphaIn[2], mat.KonstAlphaSels[i], order);
                alphaInputs[3] = GetAlphaInString(stage.AlphaIn[3], mat.KonstAlphaSels[i], order);

                stream.AppendLine(string.Format("    {0}", GetAlphaOpString(stage.AlphaOp, stage.AlphaBias, stage.AlphaScale, stage.AlphaClamp, stage.AlphaRegId, alphaInputs)));
                stream.AppendLine();
            }
            stream.AppendLine();

            // Alpha Compare
            stream.AppendLine("    // Alpha Compare Test");
            AlphaCompare alphaCompare = mat.AlphaCompare;
            string       alphaOp;

            switch (alphaCompare.Operation)
            {
            case GXAlphaOp.And: alphaOp = "&&"; break;

            case GXAlphaOp.Or: alphaOp = "||"; break;

            case GXAlphaOp.XOR: alphaOp = "^"; break;     // Not really tested, unsupported in some examples but I don't see why.

            case GXAlphaOp.XNOR: alphaOp = "=="; break;   // Not really tested. ^

            default:
                WLog.Warning(LogCategory.TEVShaderGenerator, null, "Unsupported alpha compare operation: {0}", alphaCompare.Operation);
                alphaOp = "||";
                break;
            }

            // clip(result.a < 0.5 && result a > 0.2 ? -1 : 1)
            string ifContents = string.Format("(!({0} {1} {2}))",
                                              GetCompareString(alphaCompare.Comp0, m_tevOutputRegs[0] + ".a", alphaCompare.Reference0),
                                              alphaOp,
                                              GetCompareString(alphaCompare.Comp1, m_tevOutputRegs[0] + ".a", alphaCompare.Reference1));

            // clip equivelent
            stream.AppendLine("    // Alpha Compare (Clip)");
            stream.AppendLine(string.Format("    if{0}\n\t\tdiscard;", ifContents));

            //string output = "PixelColor = texCol0" + (mat.VtxDesc.AttributeIsEnabled(ShaderAttributeIds.Color0) ? " * Color0;" : ";");
            //stream.AppendLine(output);
            stream.AppendLine(string.Format("    PixelColor = {0};", m_tevOutputRegs[0]));

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

            // Compile the Fragment Shader and return whether it compiled sucesfully or not.
            Directory.CreateDirectory("ShaderDump");
            System.IO.File.WriteAllText("ShaderDump/" + mat.Name + "_frag_output", stream.ToString());
            return(shader.CompileSource(stream.ToString(), OpenTK.Graphics.OpenGL.ShaderType.FragmentShader));
        }
Beispiel #2
0
 public TevOrder(GXTexCoordSlot slot, byte texMap, GXColorChannelId chanID)
 {
     TexCoordId = slot;
     TexMap     = texMap;
     ChannelId  = chanID;
 }