// vertex shader // lights/colors // materials name is I_MATERIALS in vs and I_PMATERIALS in ps // inColorName is color in vs and colors_ in ps // dest is o.colors_ in vs and colors_ in ps public string GenerateLightingShader(string materialsName, string lightsName, string inColorName, string dest) { string s = Tabs + "{\n"; w(ref s, "//Lighting Section\n"); for (uint j = 0; j < UsableMaterialNode.LightChannels; j++) { LightChannelControl color = j == 0 ? UsableMaterialNode._chan1._color : UsableMaterialNode._chan2._color; LightChannelControl alpha = j == 0 ? UsableMaterialNode._chan1._alpha : UsableMaterialNode._chan2._alpha; if (color.MaterialSource == GXColorSrc.Vertex) { if (_colorSet[j] != null) { w(ref s, "mat = {0}{1};\n", inColorName, j); } else if (_colorSet[0] != null) { w(ref s, "mat = {0}0;\n", inColorName); } else { w(ref s, "mat = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"); } } else { w(ref s, "mat = {0}[{1}];\n", materialsName, j + 2); } if (color.Enabled) { if (color.AmbientSource == GXColorSrc.Vertex) { if (_colorSet[j] != null) { w(ref s, "lacc = {0}{1};\n", inColorName, j); } else if (_colorSet[0] != null) { w(ref s, "lacc = {0}0;\n", inColorName); } else { w(ref s, "lacc = vec4(0.0f, 0.0f, 0.0f, 0.0f);\n"); } } else { w(ref s, "lacc = {0}[{1}];\n", materialsName, j); } } else { w(ref s, "lacc = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n"); } // check if alpha is different if (alpha.MaterialSource != color.MaterialSource) { if (alpha.MaterialSource == GXColorSrc.Vertex) { if (_colorSet[j] != null) { w(ref s, "mat.w = {0}{1}.w;\n", inColorName, j); } else if (_colorSet[0] != null) { w(ref s, "mat.w = {0}0.w;\n", inColorName); } else { w(ref s, "mat.w = 1.0f;\n"); } } else { w(ref s, "mat.w = {0}[{1}].w;\n", materialsName, j + 2); } } if (alpha.Enabled) { if (alpha.AmbientSource == GXColorSrc.Vertex) { if (_colorSet[j] != null) { w(ref s, "lacc.w = {0}{1}.w;\n", inColorName, j); } else if (_colorSet[0] != null) { w(ref s, "lacc.w = {0}0.w;\n", inColorName); } else { w(ref s, "lacc.w = 0.0f;\n"); } } else { w(ref s, "lacc.w = {0}[{1}].w;\n", materialsName, j); } } else { w(ref s, "lacc.w = 1.0f;\n"); } if (color.Enabled && alpha.Enabled) { //Both have lighting, test if they use the same lights int mask = 0; if (color.Lights == alpha.Lights) { mask = (int)color.Lights & (int)alpha.Lights; if (mask != 0) { for (int i = 0; i < 8; i++) { if ((mask & (1 << i)) != 0) { w(ref s, GenerateLightShader(i, color, lightsName, 3)); } } } } //No shared lights for (int i = 0; i < 8; i++) { if (((mask & (1 << i)) == 0) && ((int)color.Lights & (1 << i)) != 0) { w(ref s, GenerateLightShader(i, color, lightsName, 1)); } if (((mask & (1 << i)) == 0) && ((int)alpha.Lights & (1 << i)) != 0) { w(ref s, GenerateLightShader(i, alpha, lightsName, 2)); } } } else if (color.Enabled || alpha.Enabled) { //Lights are disabled on one channel so process only the active ones LightChannelControl workingchannel = color.Enabled ? color : alpha; int coloralpha = color.Enabled ? 1 : 2; for (int i = 0; i < 8; i++) { if (((int)workingchannel.Lights & (1 << i)) != 0) { w(ref s, GenerateLightShader(i, workingchannel, lightsName, coloralpha)); } } } w(ref s, "{0}{1} = mat * saturate(lacc);\n", dest, j); } w(ref s, "}\n"); return(s); }
// coloralpha - 1 if color, 2 if alpha public string GenerateLightShader(int index, LightChannelControl chan, string lightsName, int coloralpha) { string s = ""; string swizzle = "xyzw"; if (coloralpha == 1) { swizzle = "xyz"; } else if (coloralpha == 2) { swizzle = "w"; } if (chan.Attenuation == GXAttnFn.None) { // atten disabled switch (chan.DiffuseFunction) { case GXDiffuseFn.Disabled: w(ref s, "lacc.{0} += {1}[{2}].{3};\n", swizzle, lightsName, index * 5, swizzle); break; case GXDiffuseFn.Enabled: case GXDiffuseFn.Clamped: w(ref s, "ldir = normalize({0}[{1} + 3].xyz - pos.xyz);\n", lightsName, index * 5); w(ref s, "lacc.{0} += {1}dot(ldir, _norm0)) * {2}[{3}].{4};\n", swizzle, chan.DiffuseFunction != GXDiffuseFn.Enabled ? "max(0.0f," : "(", lightsName, index * 5, swizzle); break; } } else { // spec and spot if (chan.Attenuation == GXAttnFn.Spotlight) { // spot w(ref s, "ldir = {0}[{1} + 3].xyz - pos.xyz;\n", lightsName, index * 5); w(ref s, "dist2 = dot(ldir, ldir);\n" + "dist = sqrt(dist2);\n" + "ldir = ldir / dist;\n" + "attn = max(0.0f, dot(ldir, {0}[{1} + 4].xyz));\n", lightsName, index * 5); w(ref s, "attn = max(0.0f, dot({0}[{1} + 1].xyz, float3(1.0f, attn, attn*attn))) / dot({2}[{3} + 2].xyz, float3(1.0f,dist,dist2));\n", lightsName, index * 5, lightsName, index * 5); } if (chan.Attenuation == GXAttnFn.Specular) { // specular w(ref s, "ldir = normalize({0}[{1} + 3].xyz);\n", lightsName, index * 5); w(ref s, "attn = (dot(_norm0, ldir) >= 0.0f) ? max(0.0f, dot(_norm0, {0}[{1} + 4].xyz)) : 0.0f;\n", lightsName, index * 5); w(ref s, "attn = max(0.0f, dot({0}[{1} + 1].xyz, float3(1,attn,attn*attn))) / dot({2}[{3} + 2].xyz, float3(1,attn,attn*attn));\n", lightsName, index * 5, lightsName, index * 5); } switch (chan.DiffuseFunction) { case GXDiffuseFn.Disabled: w(ref s, "lacc.{0} += attn * {1}[{2}].{3};\n", swizzle, lightsName, index * 5, swizzle); break; case GXDiffuseFn.Enabled: case GXDiffuseFn.Clamped: w(ref s, "lacc.{0} += attn * {1}dot(ldir, _norm0)) * {2}[{3}].{4};\n", swizzle, chan.DiffuseFunction != GXDiffuseFn.Enabled ? "max(0.0f," : "(", lightsName, index * 5, swizzle); break; } } w(ref s, "\n"); return(s); }