public void WriteAlphaTest(PSGRENDER_MODE mode) { // using discard then return works the same in cg and dx9 but not in dx11 w("if(!("); int comp0index = (int)_alphaFunc.Comp0 % 8; int comp1index = (int)_alphaFunc.Comp1 % 8; w(tevAlphaFuncsTable[comp0index] + "{1}" + tevAlphaFuncsTable[comp1index].Replace("{0}", "{2}"), alphaRef[0], tevAlphaFunclogicTable[(int)_alphaFunc.Logic % 4], alphaRef[1]);//lookup the first component from the alpha function table w("))\n{\n"); w("ocol0 = vec4(0.0, 0.0, 0.0, 0.0);\n"); if (mode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND) { w("ocol1 = vec4(0.0, 0.0, 0.0, 0.0);\n"); } if (DepthTextureEnable) { w("depth = 1.f;\n"); } // HAXX: zcomploc is a way to control whether depth test is done before // or after texturing and alpha test. PC GPU does depth test before texturing ONLY if depth value is // not updated during shader execution. // We implement "depth test before texturing" by discarding the fragment // when the alpha test fail. This is not a correct implementation because // even if the depth test fails the fragment could be alpha blended. // this implemnetation is a trick to keep speed. // the correct, but slow, way to implement a correct zComploc is : // 1 - if zcomplock is enebled make a first pass, with color channel write disabled updating only // depth channel. // 2 - in the next pass disable depth chanel update, but proccess the color data normally // this way is the only CORRECT way to emulate perfectly the zcomplock behaviour if (!(ZCompareLoc && EnableDepthUpdate)) { w("discard;\n"); w("return;\n"); } w("}\n"); }
public void WriteAlphaTest(PSGRENDER_MODE mode) { // using discard then return works the same in cg and dx9 but not in dx11 w("if(!("); int comp0index = (int)_alphaFunc.Comp0 % 8; int comp1index = (int)_alphaFunc.Comp1 % 8; w(tevAlphaFuncsTable[comp0index] + "{1}" + tevAlphaFuncsTable[comp1index].Replace("{0}", "{2}"), alphaRef[0], tevAlphaFunclogicTable[(int)_alphaFunc.Logic % 4], alphaRef[1]);//lookup the first component from the alpha function table w("))\n{\n"); w("ocol0 = vec4(0.0, 0.0, 0.0, 0.0);\n"); if (mode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND) w("ocol1 = vec4(0.0, 0.0, 0.0, 0.0);\n"); if (DepthTextureEnable) w("depth = 1.f;\n"); // HAXX: zcomploc is a way to control whether depth test is done before // or after texturing and alpha test. PC GPU does depth test before texturing ONLY if depth value is // not updated during shader execution. // We implement "depth test before texturing" by discarding the fragment // when the alpha test fail. This is not a correct implementation because // even if the depth test fails the fragment could be alpha blended. // this implemnetation is a trick to keep speed. // the correct, but slow, way to implement a correct zComploc is : // 1 - if zcomplock is enebled make a first pass, with color channel write disabled updating only // depth channel. // 2 - in the next pass disable depth chanel update, but proccess the color data normally // this way is the only CORRECT way to emulate perfectly the zcomplock behaviour if (!(ZCompareLoc && EnableDepthUpdate)) { w("discard;\n"); w("return;\n"); } w("}\n"); }
public string GeneratePixelShaderCode(MDL0ObjectNode Object, PSGRENDER_MODE PSGRenderMode, TKContext ctx) { tempShader = ""; int numStages = ShaderNode.Children.Count; int numTexgen = Children.Count; w("//Pixel Shader for TEV stages\n"); w("//{0} TEV stages, {1} texgens, {2} IND stages\n", numStages, numTexgen, IndirectShaderStages); int nIndirectStagesUsed = 0; if (IndirectShaderStages > 0) for (int i = 0; i < numStages; ++i) { TEVStage stage = ShaderNode.Children[i] as TEVStage; if (stage.IndirectActive && stage.bt < IndirectShaderStages) nIndirectStagesUsed |= 1 << stage.bt; } DepthTextureEnable = (/*bpmem.ztex2.op != ZTEXTURE_DISABLE && */!ZCompareLoc && EnableDepthTest && EnableDepthUpdate)/* || g_ActiveConfig.bEnablePerPixelDepth*/; //A few required defines and ones that will make our lives a lot easier if (ctx.bSupportsGLSLBinding || ctx.bSupportsGLSLUBO) { w("#version 330 compatibility\n"); if (ctx.bSupportsGLSLBinding) w("#extension GL_ARB_shading_language_420pack : enable\n"); //if (ctx.bSupportsGLSLUBO) // w("#extension GL_ARB_uniform_buffer_object : enable\n"); } else w("#version 120\n"); if (ctx.bSupportsGLSLATTRBind) w("#extension GL_ARB_explicit_attrib_location : enable\n"); w("#define saturate(x) clamp(x, 0.0f, 1.0f)\n"); w("#define lerp(x, y, z) mix(x, y, z)\n"); w("float fmod(float x, float y)\n"); w("{\n"); w("float z = fract(abs(x / y)) * abs(y);\n"); w("return (x < 0) ? -z : z;\n"); w("}\n"); for (uint i = 0; i < 8; i++) w("{0}uniform sampler2D samp{1};\n", WriteBinding(i, ctx), i); w("\n"); w("uniform vec4 " + I_COLORS + "[4];\n"); w("uniform vec4 " + I_KCOLORS + "[4];\n"); w("uniform vec4 " + I_ALPHA + ";\n"); w("uniform vec4 " + I_TEXDIMS + "[8];\n"); w("uniform vec4 " + I_ZBIAS + "[2];\n"); w("uniform vec4 " + I_INDTEXSCALE + "[2];\n"); w("uniform vec4 " + I_INDTEXMTX + "[6];\n"); w("uniform vec4 " + I_FOG + "[3];\n"); // Compiler will optimize these out by itself. w("uniform vec4 " + I_PLIGHTS + "[40];\n"); w("uniform vec4 " + I_PMATERIALS + "[4];\n"); w("vec4 ocol0;\n"); if (DepthTextureEnable) w("float depth;\n"); w("vec4 rawpos = gl_FragCoord;\n"); w("vec4 colors_0 = gl_Color;\n"); w("vec4 colors_1 = gl_SecondaryColor;\n"); if (numTexgen < 7) { for (int i = 0; i < numTexgen; i++) w("vec3 uv{0} = gl_TexCoord[{0}].xyz;\n", i); w("vec4 clipPos = gl_TexCoord[{0}];\n", numTexgen); w("vec4 Normal = gl_TexCoord[{0}];\n", numTexgen + 1); } else for (int i = 0; i < 8; ++i) w("vec4 uv{0} = gl_TexCoord[{0}];\n", i); w("void main()\n{\n"); AlphaPretest Pretest = PretestAlpha(); //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_ALPHA_PASS && !DepthTextureEnable && Pretest >= 0) //{ // if (Pretest == AlphaPretest.AlwaysFail) // { // w("ocol0 = vec4(0);\n"); // w("discard;\n"); // if(PSGRenderMode != PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND) // w("gl_FragColor = ocol0;\n"); // w("return;\n"); // } // else // w("ocol0 = " + I_ALPHA + ".aaaa;\n"); // w("}\n"); // return tempShader; //} w("vec4 c0 = " + I_COLORS + "[1], c1 = " + I_COLORS + "[2], c2 = " + I_COLORS + "[3], prev = vec4(0.0f, 0.0f, 0.0f, 0.0f), textemp = vec4(0.0f, 0.0f, 0.0f, 0.0f), rastemp = vec4(0.0f, 0.0f, 0.0f, 0.0f), konsttemp = vec4(0.0f, 0.0f, 0.0f, 0.0f);\n"); w("vec3 comp16 = vec3(1.0f, 255.0f, 0.0f), comp24 = vec3(1.0f, 255.0f, 255.0f*255.0f);\n"); w("vec4 alphabump = vec4(0.0f,0.0f,0.0f,0.0f);\n"); w("vec3 tevcoord = vec3(0.0f, 0.0f, 0.0f);\n"); w("vec2 wrappedcoord=vec2(0.0f,0.0f), tempcoord=vec2(0.0f,0.0f);\n"); w("vec4 cc0 = vec4(0.0f,0.0f,0.0f,0.0f), cc1 = vec4(0.0f,0.0f,0.0f,0.0f);\n"); w("vec4 cc2 = vec4(0.0f,0.0f,0.0f,0.0f), cprev = vec4(0.0f,0.0f,0.0f,0.0f);\n"); w("vec4 crastemp=vec4(0.0f,0.0f,0.0f,0.0f), ckonsttemp = vec4(0.0f,0.0f,0.0f,0.0f);\n\n"); if (Children.Count < 7) { w("vec3 _norm0 = normalize(Normal.xyz);\n\n"); w("vec3 pos = vec3(clipPos.x,clipPos.y,Normal.w);\n"); } else { w("vec3 _norm0 = normalize(vec3(uv4.w,uv5.w,uv6.w));\n\n"); w("vec3 pos = vec3(uv0.w,uv1.w,uv7.w);\n"); } w("vec4 mat, lacc;\nvec3 ldir, h;\nfloat dist, dist2, attn;\n"); Object.tabs = tabs; tempShader += Object.GenerateLightingShader(I_PMATERIALS, I_PLIGHTS, "colors_", "colors_"); //if (numTexgen < 7) // w("clipPos = vec4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n"); //else // w("vec4 clipPos = vec4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n"); // HACK to handle cases where the tex gen is not enabled if (numTexgen == 0) w("vec3 uv0 = vec3(0.0f, 0.0f, 0.0f);\n"); else { for (int i = 0; i < numTexgen; ++i) { // optional perspective divides if (((MDL0MaterialRefNode)Children[i]).Projection == TexProjection.STQ) { w("if (uv{0}.z != 0.0f)\n", i); w(" uv{0}.xy = uv{0}.xy / uv{0}.z;\n", i); } //w("uv{0}.xy = uv{0}.xy * "+I_TEXDIMS+"[{0}].zw;\n", i); } } for (int i = 0; i < IndirectShaderStages; i++) { if ((nIndirectStagesUsed & (1 << i)) != 0) { uint texcoord = (ShaderNode._swapBlock._Value16.Value >> ((i + 1) * 3) & 7); if (texcoord < numTexgen) w("tempcoord = uv{0}.xy * " + I_INDTEXSCALE + "[{1}].{2};\n", texcoord, i / 2, (i & 1) != 0 ? "zw" : "xy"); else w("tempcoord = vec2(0.0f, 0.0f);\n"); SampleTexture(String.Format("vec3 indtex{0}", i), "tempcoord", "abg", (ShaderNode._swapBlock._Value16.Value >> (i * 3) & 7)); } } foreach (TEVStage stage in ShaderNode.Children) if (stage.Index < ActiveShaderStages) w(stage.Write(this, Object)); else break; if (numStages > 0) { w("prev.rgb = {0};\n", tevCOutputTable[(int)((TEVStage)ShaderNode.Children[numStages - 1]).ColorRegister]); w("prev.a = {0};\n", tevAOutputTable[(int)((TEVStage)ShaderNode.Children[numStages - 1]).AlphaRegister]); } // emulation of unsigned 8 overflow when casting //w("prev = fract(4.0f + prev * (255.0f/256.0f)) * (256.0f/255.0f);\n"); if (Pretest == AlphaPretest.AlwaysFail) { w("ocol0 = vec4(0.0f);\n"); //if (DepthTextureEnable) // w("depth = 1.0f;\n"); //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND) // w("ocol1 = vec4(0.0f);\n"); //else w("gl_FragColor = ocol0;\n"); if (DepthTextureEnable) w("gl_FragDepth = depth;\n"); w("discard;\n"); w("return;\n"); } else { if (Pretest != AlphaPretest.AlwaysPass) WriteAlphaTest(PSGRenderMode); //if (_fog != null && (_fog.Type != 0) || DepthTextureEnable) //{ // // the screen space depth value = far z + (clip z / clip w) * z range // w("float zCoord = " + I_ZBIAS + "[1].x + (clipPos.z / clipPos.w) * " + I_ZBIAS + "[1].y;\n"); //} //if (DepthTextureEnable) //{ // // use the texture input of the last texture stage (textemp), hopefully this has been read and is in correct format... // if (/*bpmem.ztex2.op != ZTEXTURE_DISABLE && */!ZCompLoc && EnableDepthTest && EnableDepthUpdate) // { // //if (bpmem.ztex2.op == ZTEXTURE_ADD) // // Write("zCoord = dot("+I_ZBIAS+"[0].xyzw, textemp.xyzw) + "+I_ZBIAS+"[1].w + zCoord;\n"); // //else // w("zCoord = dot(" + I_ZBIAS + "[0].xyzw, textemp.xyzw) + " + I_ZBIAS + "[1].w;\n"); // // scale to make result from frac correct // w("zCoord = zCoord * (16777215.0f/16777216.0f);\n"); // w("zCoord = fract(zCoord);\n"); // w("zCoord = zCoord * (16777216.0f/16777215.0f);\n"); // } // w("depth = zCoord;\n"); //} //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_ALPHA_PASS) // w("ocol0 = vec4(prev.rgb, " + I_ALPHA + ".a);\n"); //else { WriteFog(); w("ocol0 = prev;\n"); } //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND) //{ // w("ocol1 = ocol0;\n"); // w("ocol0.a = " + I_ALPHA + ".a;\n"); //} //if (DepthTextureEnable) // w("gl_FragDepth = depth;\n"); //if (PSGRenderMode != PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND) w("gl_FragColor = ocol0;\n"); } w("}\n"); return tempShader; }
public string GeneratePixelShaderCode(MDL0ObjectNode Object, PSGRENDER_MODE PSGRenderMode, TKContext ctx) { tempShader = ""; int numStages = ShaderNode.Children.Count; int numTexgen = Children.Count; w("//Pixel Shader for TEV stages\n"); w("//{0} TEV stages, {1} texgens, {2} IND stages\n", numStages, numTexgen, IndirectShaderStages); int nIndirectStagesUsed = 0; if (IndirectShaderStages > 0) { for (int i = 0; i < numStages; ++i) { TEVStage stage = ShaderNode.Children[i] as TEVStage; if (stage.IndirectActive && stage.bt < IndirectShaderStages) { nIndirectStagesUsed |= 1 << stage.bt; } } } DepthTextureEnable = (/*bpmem.ztex2.op != ZTEXTURE_DISABLE && */ !ZCompareLoc && EnableDepthTest && EnableDepthUpdate) /* || g_ActiveConfig.bEnablePerPixelDepth*/; //A few required defines and ones that will make our lives a lot easier if (ctx.bSupportsGLSLBinding || ctx.bSupportsGLSLUBO) { w("#version 330 compatibility\n"); if (ctx.bSupportsGLSLBinding) { w("#extension GL_ARB_shading_language_420pack : enable\n"); } //if (ctx.bSupportsGLSLUBO) // w("#extension GL_ARB_uniform_buffer_object : enable\n"); } else { w("#version 120\n"); } if (ctx.bSupportsGLSLATTRBind) { w("#extension GL_ARB_explicit_attrib_location : enable\n"); } w("#define saturate(x) clamp(x, 0.0f, 1.0f)\n"); w("#define lerp(x, y, z) mix(x, y, z)\n"); w("float fmod(float x, float y)\n"); w("{\n"); w("float z = fract(abs(x / y)) * abs(y);\n"); w("return (x < 0) ? -z : z;\n"); w("}\n"); for (uint i = 0; i < 8; i++) { w("{0}uniform sampler2D samp{1};\n", WriteBinding(i, ctx), i); } w("\n"); w("uniform vec4 " + I_COLORS + "[4];\n"); w("uniform vec4 " + I_KCOLORS + "[4];\n"); w("uniform vec4 " + I_ALPHA + ";\n"); w("uniform vec4 " + I_TEXDIMS + "[8];\n"); w("uniform vec4 " + I_ZBIAS + "[2];\n"); w("uniform vec4 " + I_INDTEXSCALE + "[2];\n"); w("uniform vec4 " + I_INDTEXMTX + "[6];\n"); w("uniform vec4 " + I_FOG + "[3];\n"); // Compiler will optimize these out by itself. w("uniform vec4 " + I_PLIGHTS + "[40];\n"); w("uniform vec4 " + I_PMATERIALS + "[4];\n"); w("vec4 ocol0;\n"); if (DepthTextureEnable) { w("float depth;\n"); } w("vec4 rawpos = gl_FragCoord;\n"); w("vec4 colors_0 = gl_Color;\n"); w("vec4 colors_1 = gl_SecondaryColor;\n"); if (numTexgen < 7) { for (int i = 0; i < numTexgen; i++) { w("vec3 uv{0} = gl_TexCoord[{0}].xyz;\n", i); } w("vec4 clipPos = gl_TexCoord[{0}];\n", numTexgen); w("vec4 Normal = gl_TexCoord[{0}];\n", numTexgen + 1); } else { for (int i = 0; i < 8; ++i) { w("vec4 uv{0} = gl_TexCoord[{0}];\n", i); } } w("void main()\n{\n"); AlphaPretest Pretest = PretestAlpha(); //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_ALPHA_PASS && !DepthTextureEnable && Pretest >= 0) //{ // if (Pretest == AlphaPretest.AlwaysFail) // { // w("ocol0 = vec4(0);\n"); // w("discard;\n"); // if(PSGRenderMode != PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND) // w("gl_FragColor = ocol0;\n"); // w("return;\n"); // } // else // w("ocol0 = " + I_ALPHA + ".aaaa;\n"); // w("}\n"); // return tempShader; //} w("vec4 c0 = " + I_COLORS + "[1], c1 = " + I_COLORS + "[2], c2 = " + I_COLORS + "[3], prev = vec4(0.0f, 0.0f, 0.0f, 0.0f), textemp = vec4(0.0f, 0.0f, 0.0f, 0.0f), rastemp = vec4(0.0f, 0.0f, 0.0f, 0.0f), konsttemp = vec4(0.0f, 0.0f, 0.0f, 0.0f);\n"); w("vec3 comp16 = vec3(1.0f, 255.0f, 0.0f), comp24 = vec3(1.0f, 255.0f, 255.0f*255.0f);\n"); w("vec4 alphabump = vec4(0.0f,0.0f,0.0f,0.0f);\n"); w("vec3 tevcoord = vec3(0.0f, 0.0f, 0.0f);\n"); w("vec2 wrappedcoord=vec2(0.0f,0.0f), tempcoord=vec2(0.0f,0.0f);\n"); w("vec4 cc0 = vec4(0.0f,0.0f,0.0f,0.0f), cc1 = vec4(0.0f,0.0f,0.0f,0.0f);\n"); w("vec4 cc2 = vec4(0.0f,0.0f,0.0f,0.0f), cprev = vec4(0.0f,0.0f,0.0f,0.0f);\n"); w("vec4 crastemp=vec4(0.0f,0.0f,0.0f,0.0f), ckonsttemp = vec4(0.0f,0.0f,0.0f,0.0f);\n\n"); if (Children.Count < 7) { w("vec3 _norm0 = normalize(Normal.xyz);\n\n"); w("vec3 pos = vec3(clipPos.x,clipPos.y,Normal.w);\n"); } else { w("vec3 _norm0 = normalize(vec3(uv4.w,uv5.w,uv6.w));\n\n"); w("vec3 pos = vec3(uv0.w,uv1.w,uv7.w);\n"); } w("vec4 mat, lacc;\nvec3 ldir, h;\nfloat dist, dist2, attn;\n"); Object.tabs = tabs; tempShader += Object.GenerateLightingShader(I_PMATERIALS, I_PLIGHTS, "colors_", "colors_"); //if (numTexgen < 7) // w("clipPos = vec4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n"); //else // w("vec4 clipPos = vec4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n"); // HACK to handle cases where the tex gen is not enabled if (numTexgen == 0) { w("vec3 uv0 = vec3(0.0f, 0.0f, 0.0f);\n"); } else { for (int i = 0; i < numTexgen; ++i) { // optional perspective divides if (((MDL0MaterialRefNode)Children[i]).Projection == TexProjection.STQ) { w("if (uv{0}.z != 0.0f)\n", i); w(" uv{0}.xy = uv{0}.xy / uv{0}.z;\n", i); } //w("uv{0}.xy = uv{0}.xy * "+I_TEXDIMS+"[{0}].zw;\n", i); } } for (int i = 0; i < IndirectShaderStages; i++) { if ((nIndirectStagesUsed & (1 << i)) != 0) { uint texcoord = (ShaderNode._swapBlock._Value16.Value >> ((i + 1) * 3) & 7); if (texcoord < numTexgen) { w("tempcoord = uv{0}.xy * " + I_INDTEXSCALE + "[{1}].{2};\n", texcoord, i / 2, (i & 1) != 0 ? "zw" : "xy"); } else { w("tempcoord = vec2(0.0f, 0.0f);\n"); } SampleTexture(String.Format("vec3 indtex{0}", i), "tempcoord", "abg", (ShaderNode._swapBlock._Value16.Value >> (i * 3) & 7)); } } foreach (TEVStage stage in ShaderNode.Children) { if (stage.Index < ActiveShaderStages) { w(stage.Write(this, Object)); } else { break; } } if (numStages > 0) { w("prev.rgb = {0};\n", tevCOutputTable[(int)((TEVStage)ShaderNode.Children[numStages - 1]).ColorRegister]); w("prev.a = {0};\n", tevAOutputTable[(int)((TEVStage)ShaderNode.Children[numStages - 1]).AlphaRegister]); } // emulation of unsigned 8 overflow when casting //w("prev = fract(4.0f + prev * (255.0f/256.0f)) * (256.0f/255.0f);\n"); if (Pretest == AlphaPretest.AlwaysFail) { w("ocol0 = vec4(0.0f);\n"); //if (DepthTextureEnable) // w("depth = 1.0f;\n"); //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND) // w("ocol1 = vec4(0.0f);\n"); //else w("gl_FragColor = ocol0;\n"); if (DepthTextureEnable) { w("gl_FragDepth = depth;\n"); } w("discard;\n"); w("return;\n"); } else { if (Pretest != AlphaPretest.AlwaysPass) { WriteAlphaTest(PSGRenderMode); } //if (_fog != null && (_fog.Type != 0) || DepthTextureEnable) //{ // // the screen space depth value = far z + (clip z / clip w) * z range // w("float zCoord = " + I_ZBIAS + "[1].x + (clipPos.z / clipPos.w) * " + I_ZBIAS + "[1].y;\n"); //} //if (DepthTextureEnable) //{ // // use the texture input of the last texture stage (textemp), hopefully this has been read and is in correct format... // if (/*bpmem.ztex2.op != ZTEXTURE_DISABLE && */!ZCompLoc && EnableDepthTest && EnableDepthUpdate) // { // //if (bpmem.ztex2.op == ZTEXTURE_ADD) // // Write("zCoord = dot("+I_ZBIAS+"[0].xyzw, textemp.xyzw) + "+I_ZBIAS+"[1].w + zCoord;\n"); // //else // w("zCoord = dot(" + I_ZBIAS + "[0].xyzw, textemp.xyzw) + " + I_ZBIAS + "[1].w;\n"); // // scale to make result from frac correct // w("zCoord = zCoord * (16777215.0f/16777216.0f);\n"); // w("zCoord = fract(zCoord);\n"); // w("zCoord = zCoord * (16777216.0f/16777215.0f);\n"); // } // w("depth = zCoord;\n"); //} //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_ALPHA_PASS) // w("ocol0 = vec4(prev.rgb, " + I_ALPHA + ".a);\n"); //else { WriteFog(); w("ocol0 = prev;\n"); } //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND) //{ // w("ocol1 = ocol0;\n"); // w("ocol0.a = " + I_ALPHA + ".a;\n"); //} //if (DepthTextureEnable) // w("gl_FragDepth = depth;\n"); //if (PSGRenderMode != PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND) w("gl_FragColor = ocol0;\n"); } w("}\n"); return(tempShader); }