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); }
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); } }
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; * }*/ }
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)); }