private static TevStage ReadTevCombinerStage(EndianBinaryReader stream) { var retVal = new TevStage(); retVal.Unknown0 = stream.ReadByte(); for (int i = 0; i < 4; i++) { retVal.ColorIn[i] = (GXCombineColorInput)stream.ReadByte(); } retVal.ColorOp = (GXTevOp)stream.ReadByte(); retVal.ColorBias = (GXTevBias)stream.ReadByte(); retVal.ColorScale = (GXTevScale)stream.ReadByte(); retVal.ColorClamp = stream.ReadBoolean(); retVal.ColorRegId = stream.ReadByte(); for (int i = 0; i < 4; i++) { retVal.AlphaIn[i] = (GXCombineAlphaInput)stream.ReadByte(); } retVal.AlphaOp = (GXTevOp)stream.ReadByte(); retVal.AlphaBias = (GXTevBias)stream.ReadByte(); retVal.AlphaScale = (GXTevScale)stream.ReadByte(); retVal.AlphaClamp = stream.ReadBoolean(); retVal.AlphaRegId = stream.ReadByte(); retVal.Unknown1 = stream.ReadByte(); Trace.Assert(retVal.Unknown0 == 0xFF); Trace.Assert(retVal.Unknown1 == 0xFF); return(retVal); }
public MaterialEntry(EndianBinaryReader er) { Name = er.ReadString(Encoding.ASCII, 20).Replace("\0", ""); BufferColor = er.ReadColor8(); ConstColors = new Color[6]; ConstColors[0] = er.ReadColor8(); ConstColors[1] = er.ReadColor8(); ConstColors[2] = er.ReadColor8(); ConstColors[3] = er.ReadColor8(); ConstColors[4] = er.ReadColor8(); ConstColors[5] = er.ReadColor8(); Flags = er.ReadUInt32(); //Material Flag: // 0-1: Nr texMap // 2-3: Nr texMatrix // 4-5: Nr texCoordGen // 6-8: Nr tevStage // 9: Has alphaCompare // 10: Has blendMode // 11: Use Texture Only // 12: Separate Blend Mode // 14: Has Indirect Parameter //15-16: Nr projectionTexGenParameter // 17: Has Font Shadow Parameter TexMaps = new TexMap[Flags & 3]; for (int i = 0; i < (Flags & 3); i++) { TexMaps[i] = new TexMap(er); } TexMatrices = new TexMatrix[(Flags >> 2) & 3]; for (int i = 0; i < ((Flags >> 2) & 3); i++) { TexMatrices[i] = new TexMatrix(er); } TexCoordGens = new TexCoordGen[(Flags >> 4) & 3]; for (int i = 0; i < ((Flags >> 4) & 3); i++) { TexCoordGens[i] = new TexCoordGen(er); } TevStages = new TevStage[(Flags >> 6) & 7]; for (int i = 0; i < ((Flags >> 6) & 7); i++) { TevStages[i] = new TevStage(er); } if (((Flags >> 9) & 1) == 1) { AlphaTest = new AlphaCompare(er); } if (((Flags >> 10) & 1) == 1) { ColorBlendMode = new BlendMode(er); } if (((Flags >> 12) & 1) == 1) { AlphaBlendMode = new BlendMode(er); } //Some more things }
private void GenerateTevColorAndAlphaCommands(Material mat) { for (int i = 0; i < 16; i++) { if (mat.TevStages[i] == null) { continue; } TevStage stage = mat.TevStages[i].Value; if (mat.SwapModes[i] == null) { continue; } TevSwapMode swapMode = mat.SwapModes[i].Value; BPCommand tev_color_env = new BPCommand() { Register = BPRegister.TEV_COLOR_ENV_0 + i * 2 }; BPCommand tev_alpha_env = new BPCommand() { Register = BPRegister.TEV_ALPHA_ENV_0 + i * 2 }; BPCommand ind_cmd = new BPCommand() { Register = BPRegister.IND_CMD0 + i }; tev_color_env.SetBits((int)stage.ColorInD, 0, 4); tev_color_env.SetBits((int)stage.ColorInC, 4, 4); tev_color_env.SetBits((int)stage.ColorInB, 8, 4); tev_color_env.SetBits((int)stage.ColorInA, 12, 4); tev_color_env.SetBits((int)stage.ColorBias, 16, 2); tev_color_env.SetBits((int)stage.ColorOp, 18, 1); tev_color_env.SetFlag(stage.ColorClamp, 19); tev_color_env.SetBits((int)stage.ColorScale, 20, 2); tev_color_env.SetBits((int)stage.ColorRegId, 22, 2); tev_alpha_env.SetBits((int)stage.AlphaInA, 13, 3); tev_alpha_env.SetBits((int)stage.AlphaInB, 10, 3); tev_alpha_env.SetBits((int)stage.AlphaInC, 7, 3); tev_alpha_env.SetBits((int)stage.AlphaInD, 4, 3); tev_alpha_env.SetBits((int)stage.AlphaBias, 16, 2); tev_alpha_env.SetBits((int)stage.AlphaOp, 18, 1); tev_alpha_env.SetFlag(stage.AlphaClamp, 19); tev_alpha_env.SetBits((int)stage.AlphaScale, 20, 2); tev_alpha_env.SetBits((int)stage.AlphaRegId, 22, 2); tev_alpha_env.SetBits(swapMode.RasSel, 0, 2); tev_alpha_env.SetBits(swapMode.TexSel, 2, 2); BPCommands.Add(tev_color_env); BPCommands.Add(tev_alpha_env); BPCommands.Add(ind_cmd); } }
public MaterialEntry(EndianBinaryReader er) { Name = er.ReadString(Encoding.ASCII, 20).Replace("\0", ""); BufferColor = er.ReadColor8(); ConstColors = new Color[6]; ConstColors[0] = er.ReadColor8(); ConstColors[1] = er.ReadColor8(); ConstColors[2] = er.ReadColor8(); ConstColors[3] = er.ReadColor8(); ConstColors[4] = er.ReadColor8(); ConstColors[5] = er.ReadColor8(); Flags = er.ReadUInt32(); //Material Flag: // 0-1: Nr texMap // 2-3: Nr texMatrix // 4-5: Nr texCoordGen // 6-8: Nr tevStage // 9: Has alphaCompare // 10: Has blendMode // 11: Use Texture Only // 12: Separate Blend Mode // 14: Has Indirect Parameter //15-16: Nr projectionTexGenParameter // 17: Has Font Shadow Parameter TexMaps = new TexMap[Flags & 3]; for (int i = 0; i < (Flags & 3); i++) { TexMaps[i] = new TexMap(er); } TexMatrices = new TexMatrix[(Flags >> 2) & 3]; for (int i = 0; i < ((Flags >> 2) & 3); i++) { TexMatrices[i] = new TexMatrix(er); } TexCoordGens = new TexCoordGen[(Flags >> 4) & 3]; for (int i = 0; i < ((Flags >> 4) & 3); i++) { TexCoordGens[i] = new TexCoordGen(er); } TevStages = new TevStage[(Flags >> 6) & 7]; for (int i = 0; i < ((Flags >> 6) & 7); i++) { TevStages[i] = new TevStage(er); } if (((Flags >> 9) & 1) == 1) AlphaTest = new AlphaCompare(er); if (((Flags >> 10) & 1) == 1) ColorBlendMode = new BlendMode(er); if (((Flags >> 12) & 1) == 1) AlphaBlendMode = new BlendMode(er); //Some more things }
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)); }
private static void WriteStage(StringBuilder stream, int stageIndex, Material mat, MAT3 data) { // Basic TEV Operation: // Inputs: [0 <= A, B, C <= 255] [-1024 <= D <= 1023] // Lerp between A and B using C as the interpolation factor. Optionally negate the result // using op. Input D and a bias (0, +0.5, -0.5) are added to the result. Then a constant // scale (1, 2, 4, 0.5) is applied. Result is optionally clamped before being written to // an output buffer. TevStage tevStage = mat.TevStages[stageIndex]; TevOrder tevOrder = mat.TevOrders[stageIndex]; stream.AppendFormat("\t// TEV Stage {0}\n", stageIndex); stream.AppendFormat("\t// Unknown0: {0} ColorInA: {1} ColorInB: {2} ColorInC: {3} ColorInD: {4} ColorOp: {5} ColorBias: {6} ColorScale: {7} ColorClamp: {8} ColorRegId: {9}\n", tevStage.Unknown0, tevStage.ColorIn[0], tevStage.ColorIn[1], tevStage.ColorIn[2], tevStage.ColorIn[3], tevStage.ColorOp, tevStage.ColorBias, tevStage.ColorScale, tevStage.ColorClamp, tevStage.ColorRegister); stream.AppendFormat("\t// AlphaInA: {0} AlphaInB: {1} AlphaInC: {2} AlphaInD: {3} AlphaOp: {4} AlphaBias: {5} AlphaScale: {6} AlphaClamp: {7} AlphaRegId: {8} Unknown1: {9}\n", tevStage.AlphaIn[0], tevStage.AlphaIn[1], tevStage.AlphaIn[2], tevStage.AlphaIn[3], tevStage.AlphaOp, tevStage.AlphaBias, tevStage.AlphaScale, tevStage.AlphaClamp, tevStage.AlphaRegister, tevStage.Unknown1); stream.AppendFormat("\t// Tev Order TexCoordId: {0} TexMap: {1} ChannelId: {2}\n", tevOrder.TexCoordId, tevOrder.TexMap, tevOrder.ChannelId); TevSwapMode swapMode = mat.TevSwapModes[stageIndex]; TevSwapModeTable rasSwapTable = mat.TevSwapModeTables[swapMode.RasSel]; TevSwapModeTable texSwapTable = mat.TevSwapModeTables[swapMode.TexSel]; stream.AppendFormat("\t// TEV Swap Mode: RasSel: {0} TexSel: {1}\n", swapMode.RasSel, swapMode.TexSel); stream.AppendFormat("\t// Ras Swap Table: R: {0} G: {1} B: {2} A: {3}\n", rasSwapTable.R, rasSwapTable.G, rasSwapTable.B, rasSwapTable.A); stream.AppendFormat("\t// Tex Swap Table: R: {0} G: {1} B: {2} A: {3}\n", texSwapTable.R, texSwapTable.G, texSwapTable.B, texSwapTable.A); int texcoord = (int)tevOrder.TexCoordId; bool bHasTexCoord = (int)tevOrder.TexCoordId < mat.NumTexGens; // Build a Swap Mode for swapping texture color input/rasterized color input to the TEV Stage. string[] rasSwapModeTable = new string[4]; string swapColors = "rgba"; for (int i = 0; i < 4; i++) { char[] swapTable = new char[4]; swapTable[0] = swapColors[rasSwapTable.R]; swapTable[1] = swapColors[rasSwapTable.G]; swapTable[2] = swapColors[rasSwapTable.B]; swapTable[3] = swapColors[rasSwapTable.A]; rasSwapModeTable[i] = new string(swapTable); } string[] texSwapModeTable = new string[4]; for (int i = 0; i < 4; i++) { char[] swapTable = new char[4]; swapTable[0] = swapColors[texSwapTable.R]; swapTable[1] = swapColors[texSwapTable.G]; swapTable[2] = swapColors[texSwapTable.B]; swapTable[3] = swapColors[texSwapTable.A]; texSwapModeTable[i] = new string(swapTable); } // ToDo: Implement Indirect Stages // If our TEV Stage uses rasterized alpha or color inputs if (tevStage.ColorIn[0] == GXCombineColorInput.RasAlpha || tevStage.ColorIn[0] == GXCombineColorInput.RasColor || tevStage.ColorIn[1] == GXCombineColorInput.RasAlpha || tevStage.ColorIn[1] == GXCombineColorInput.RasColor || tevStage.ColorIn[2] == GXCombineColorInput.RasAlpha || tevStage.ColorIn[2] == GXCombineColorInput.RasColor || tevStage.ColorIn[3] == GXCombineColorInput.RasAlpha || tevStage.ColorIn[3] == GXCombineColorInput.RasColor || tevStage.AlphaIn[0] == GXCombineAlphaInput.RasAlpha || tevStage.AlphaIn[1] == GXCombineAlphaInput.RasAlpha || tevStage.AlphaIn[2] == GXCombineAlphaInput.RasAlpha || tevStage.AlphaIn[3] == GXCombineAlphaInput.RasAlpha) { stream.AppendFormat("\t// TEV Swap Mode\n"); stream.AppendFormat("\trastemp = {0}.{1};\n", m_tevRasTable[(int)tevOrder.ChannelId], rasSwapModeTable[rasSwapTable.A]); // ToDo: No idea if this works. } if (tevOrder.TexCoordId != GXTexCoordSlot.Null) { int texmap = tevOrder.TexMap; if (true /* !bHasIndStage*/) { if (bHasTexCoord) { stream.AppendFormat("\ttevcoord.xy = TexGen{0}.xy;\n", texcoord); } else { stream.AppendFormat("\ttevcoord.xy = vec2(0, 0);\n"); } } string texswap = texSwapModeTable[texSwapTable.A]; // Again, no idea if this works. stream.Append("\ttextemp = "); SampleTexture(stream, "vec2(tevcoord.xy)", texswap, texmap); } else { stream.AppendFormat("\ttextemp = vec4(1,1,1,1); // tevOrder specified no texture!\n"); } if (tevStage.ColorIn[0] == GXCombineColorInput.Konst || tevStage.ColorIn[1] == GXCombineColorInput.Konst || tevStage.ColorIn[2] == GXCombineColorInput.Konst || tevStage.ColorIn[3] == GXCombineColorInput.Konst || tevStage.AlphaIn[0] == GXCombineAlphaInput.Konst || tevStage.AlphaIn[1] == GXCombineAlphaInput.Konst || tevStage.AlphaIn[2] == GXCombineAlphaInput.Konst || tevStage.AlphaIn[3] == GXCombineAlphaInput.Konst) { GXKonstColorSel kc = mat.KonstColorSelectors[stageIndex]; GXKonstAlphaSel ka = mat.KonstAlphaSelectors[stageIndex]; stream.AppendFormat("\t// KonstColorSel: {0} KonstAlphaSel: {1}\n", kc, ka); stream.AppendFormat("\tkonsttemp = vec4({0}, {1});\n", m_tevKSelTableC[(int)kc], m_tevKSelTableA[(int)ka]); } stream.AppendFormat("\ttevin_a = vec4({0}, {1});\n", m_tevCInputTable[(int)tevStage.ColorIn[0]], m_tevAInputTable[(int)tevStage.AlphaIn[0]]); stream.AppendFormat("\ttevin_b = vec4({0}, {1});\n", m_tevCInputTable[(int)tevStage.ColorIn[1]], m_tevAInputTable[(int)tevStage.AlphaIn[1]]); stream.AppendFormat("\ttevin_c = vec4({0}, {1});\n", m_tevCInputTable[(int)tevStage.ColorIn[2]], m_tevAInputTable[(int)tevStage.AlphaIn[2]]); stream.AppendFormat("\ttevin_d = vec4({0}, {1});\n", m_tevCInputTable[(int)tevStage.ColorIn[3]], m_tevAInputTable[(int)tevStage.AlphaIn[3]]); // COLOR COMBINER stream.AppendFormat("\t// Color Combine\n"); stream.AppendFormat("\t{0} = clamp(", m_tevCOutputTable[(byte)tevStage.ColorRegister]); if (tevStage.ColorOp == GXTevOp.Add || tevStage.ColorOp == GXTevOp.Sub) { WriteTevRegular(stream, "rgb", tevStage.ColorBias, tevStage.ColorOp, tevStage.ColorScale, tevStage.ColorClamp); } else { string[] opTable = new string[] { "((tevin_a.r > tevin_b.r) ? tevin_c.rgb : vec3(0,0,0))", // GXTevOp::Comp_R8_GT "((tevin_a.r == tevin_b.r) ? tevin_c.rgb : vec3(0,0,0))", // GXTevOp::Comp_R8_EQ "((dot(tevin_a.rgb, comp16) > dot(tevin_b.rgb, comp16)) ? tevin_c.rgb : vec3(0,0,0))", // GXTevOp::Comp_GR16_GT "((dot(tevin_a.rgb, comp16) == dot(tevin_b.rgb, comp16)) ? tevin_c.rgb : vec3(0,0,0))", // GXTevOp::Comp_GR16_EQ "((dot(tevin_a.rgb, comp24) > dot(tevin_b.rgb, comp24)) ? tevin_c.rgb : vec3(0,0,0))", // GXTevOp::Comp_GR24_GT "((dot(tevin_a.rgb, comp24) == dot(tevin_b.rgb, comp24)) ? tevin_c.rgb : vec3(0,0,0))", // GXTevOp::Comp_GR24_EQ "(max(sign(tevin_a.rgb - tevin_b.rgb), vec3(0,0,0)) * tevin_c.rgb)", // GXTevOp::Comp_RGB8_GT "((vec3(1,1,1) - sign(abs(tevin_a.rgb - tevin_b.rgb))) * tevin_c.rgb)", // GXTevOp::Comp_RGB8_EQ }; int index = (int)tevStage.ColorOp - 8; stream.AppendFormat("tevin_d.rgb + {0}", opTable[index]); } if (tevStage.ColorClamp) { stream.AppendFormat(", vec3(0,0,0), vec3(1,1,1))"); } else { stream.AppendFormat(", vec3(-1024, -1024, -1024), vec3(1023, 1023, 1023))"); } stream.AppendFormat(";\n"); // ALPHA COMBINER stream.AppendFormat("\t// Alpha Combine\n"); stream.AppendFormat("\t{0} = clamp(", m_tevAOutputTable[(byte)tevStage.AlphaRegister]); if (tevStage.AlphaOp == GXTevOp.Add || tevStage.AlphaOp == GXTevOp.Sub) { WriteTevRegular(stream, "a", tevStage.AlphaBias, tevStage.AlphaOp, tevStage.AlphaScale, tevStage.AlphaClamp); } else { string[] opTable = new string[] { "((tevin_a.r > tevin_b.r) ? tevin_c.a : 0)", // GXTevOp::Comp_R8_GT "((tevin_a.r == tevin_b.r) ? tevin_c.a : 0)", // GXTevOp::Comp_R8_EQ "((dot(tevin_a.rgb, comp16) > dot(tevin_b.rgb, comp16)) ? tevin_c.a : 0)", // GXTevOp::Comp_GR16_GT "((dot(tevin_a.rgb, comp16) == dot(tevin_b.rgb, comp16)) ? tevin_c.a : 0)", // GXTevOp::Comp_GR16_EQ "((dot(tevin_a.rgb, comp24) > dot(tevin_b.rgb, comp24)) ? tevin_c.a : 0)", // GXTevOp::Comp_GR24_GT "((dot(tevin_a.rgb, comp24) == dot(tevin_b.rgb, comp24)) ? tevin_c.a : 0)", // GXTevOp::Comp_GR24_EQ "((tevin_a.a > tevin_b.a) ? tevin_c.a : 0)", // GXTevOp::Comp_RGB8_GT "((tevin_a.a == tevin_b.a) ? tevin_c.a : 0)", // GXTevOp::Comp_RGB8_EQ }; int index = (int)tevStage.AlphaOp - 8; stream.AppendFormat("tevin_d.a + {0}", opTable[index]); } if (tevStage.AlphaClamp) { stream.AppendFormat(", 0, 1)"); } else { stream.AppendFormat(", -1024, 1023)"); } stream.AppendFormat(";\n"); stream.AppendLine(); }
void ReadMaterial() { if (clyt.Materials.Count > 0) { throw new FormatException("Expecting just one mat1 section"); } long baseOffset = reader.Stream.Position - 8; int numMaterials = reader.ReadInt32(); while (numMaterials > 0) { // Read from table and jump to material long offset = baseOffset + reader.ReadUInt32(); reader.Stream.PushToPosition(offset); var material = new Material(); material.Name = reader.ReadString(0x14).Replace("\0", string.Empty); for (int i = 0; i < material.TevConstantColors.Length; i++) { // TODO: Convert to RGBA material.TevConstantColors[i] = reader.ReadUInt32(); } uint flags = reader.ReadUInt32(); uint numTexMap = flags & 0x3; uint numTexMatrix = (flags >> 2) & 0x3; uint numTexCoordGen = (flags >> 4) & 0x3; uint numTevStage = (flags >> 6) & 0x7; bool hasAlphaCompare = ((flags >> 9) & 0x01) == 1; bool hasBlendMode = ((flags >> 10) & 0x01) == 1; material.UseTextureOnly = ((flags >> 11) & 0x01) == 1; bool separateBlendMode = ((flags >> 12) & 0x01) == 1; bool hasIndirectParam = ((flags >> 13) & 0x01) == 1; uint numProjTexGenParam = (flags >> 14) & 0x03; bool hasFontShadowParam = ((flags >> 16) & 0x01) == 1; for (int i = 0; i < numTexMap; i++) { var entry = new TextureMapEntry(); entry.Index = reader.ReadUInt16(); byte flag1 = reader.ReadByte(); byte flag2 = reader.ReadByte(); entry.WrapS = (WrapMode)(flag1 & 0x3); entry.WrapT = (WrapMode)(flag2 & 0x3); entry.MinFilter = (TextureFilter)((flag1 >> 2) & 0x3); entry.MagFilter = (TextureFilter)((flag2 >> 2) & 0x3); material.TexMapEntries.Add(entry); } for (int i = 0; i < numTexMatrix; i++) { var entry = new TextureMatrixEntry(); entry.Translation = new Vector2(reader.ReadSingle(), reader.ReadSingle()); entry.Rotation = reader.ReadSingle(); entry.Scale = new Vector2(reader.ReadSingle(), reader.ReadSingle()); material.TexMatrixEntries.Add(entry); } for (int i = 0; i < numTexCoordGen; i++) { material.TextureCoordGen.Add(reader.ReadSingle()); } for (int i = 0; i < numTevStage; i++) { var stage = new TevStage(); stage.Param1 = reader.ReadUInt32(); stage.Param2 = reader.ReadUInt32(); stage.Param3 = reader.ReadUInt32(); material.TevStages.Add(stage); } if (hasAlphaCompare) { material.AlphaCompare = new AlphaCompare { Function = reader.ReadUInt32(), Reference = reader.ReadSingle(), }; } if (hasBlendMode) { material.ColorBlendMode = new BlendMode { BlendOperator = reader.ReadByte(), SourceFactor = reader.ReadByte(), DestinationFactor = reader.ReadByte(), LogicOperator = reader.ReadByte(), }; } if (separateBlendMode) { material.AlphaBlendMode = new BlendMode { BlendOperator = reader.ReadByte(), SourceFactor = reader.ReadByte(), DestinationFactor = reader.ReadByte(), LogicOperator = reader.ReadByte(), }; } if (hasIndirectParam || numProjTexGenParam > 0 || hasFontShadowParam) { Console.WriteLine($"WARN: Material ({material.Name}) with unknown sections."); } clyt.Materials.Add(material); reader.Stream.PopPosition(); numMaterials--; } }
public Material(ref BinaryStream s) { name = Encoding.ASCII.GetString(s.ReadBytes(28)).Replace("\0", ""); flag = s.ReadUInt32(); unknown = s.ReadUInt32(); byte[] black = s.ReadBytes(4), white = s.ReadBytes(4); blackColor = Color.FromArgb(black[3], black[0], black[1], black[2]); whiteColor = Color.FromArgb(white[3], white[0], black[1], black[2]); texMapCount = (uint)(flag & 0x03); texSRTCount = (uint)((flag >> 2) & 0x03); texCoordGenCount = (uint)((flag >> 4) & 0x03); tevStageCount = (uint)((flag >> 6) & 0x07); hasAlphaCompare = ((flag >> 9) & 0x01) == 1; hasBlendMode = ((flag >> 10) & 0x01) == 1; useTextureOnly = ((flag >> 11) & 0x01) == 1; seperateBlendMode = ((flag >> 12) & 0x01) == 1; hasIndirectParameter = ((flag >> 14) & 0x01) == 1; projectionTexGenParameterCount = (uint)((flag >> 15) & 0x03); hasFontShadowParameter = ((flag >> 17) & 0x01) == 1; thresholingAlphaInterpolation = ((flag >> 18) & 0x01) == 1; texMaps = new TexMap[texMapCount]; for (int i = 0; i < texMapCount; i++) { texMaps[i] = new TexMap(ref s); } texSRTs = new TexSRT[texSRTCount]; for (int i = 0; i < texSRTCount; i++) { texSRTs[i] = new TexSRT(ref s); } texCoords = new TexCoordGen[texCoordGenCount]; for (int i = 0; i < texCoordGenCount; i++) { texCoords[i] = new TexCoordGen(ref s); } tevStages = new TevStage[tevStageCount]; for (int i = 0; i < tevStageCount; i++) { tevStages[i] = new TevStage(ref s); } if (hasAlphaCompare) { alphaCompare = new AlphaCompare(ref s); } if (hasBlendMode) { blendMode = new BlendMode(ref s); } if (seperateBlendMode) { blendAlpha = new BlendMode(ref s); } if (hasIndirectParameter) { indirectParameter = new IndirectParameter(ref s); } projectionTexGenParameters = new ProjectionTexGenParameters[projectionTexGenParameterCount]; for (int i = 0; i < projectionTexGenParameterCount; i++) { projectionTexGenParameters[i] = new ProjectionTexGenParameters(ref s); } if (hasFontShadowParameter) { fontShadowParameter = new FontShadowParameter(ref s); } //System.Windows.Forms.MessageBox.Show($"[{s.BaseStream.Position}] mat end"); }