diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 462dd1f69..d8963480f 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -292,22 +292,22 @@ static const char *vertexShader_100 = {"\ // Fragment Shader GLSL 1.00 static const char *fragmentShader_100 = {"\ - varying vec4 vtxPosition; \n\ - varying vec2 vtxTexCoord; \n\ - varying vec4 vtxColor; \n\ + varying vec4 vtxPosition;\n\ + varying vec2 vtxTexCoord;\n\ + varying vec4 vtxColor;\n\ \n\ - uniform sampler2D texRenderObject; \n\ - uniform sampler1D texToonTable; \n\ + uniform sampler2D texRenderObject;\n\ + uniform sampler1D texToonTable;\n\ \n\ - uniform int stateToonShadingMode; \n\ - uniform bool stateEnableAlphaTest; \n\ + uniform int stateToonShadingMode;\n\ + uniform bool stateEnableAlphaTest;\n\ uniform bool stateEnableAntialiasing;\n\ uniform bool stateEnableEdgeMarking;\n\ - uniform bool stateUseWDepth; \n\ - uniform float stateAlphaTestRef; \n\ + uniform bool stateUseWDepth;\n\ + uniform float stateAlphaTestRef;\n\ \n\ - uniform int polyMode; \n\ - uniform bool polyEnableDepthWrite;\n\ + uniform int polyMode;\n\ + uniform bool polySetupShadow;\n\ uniform bool polySetNewDepthForTranslucent;\n\ uniform int polyID;\n\ \n\ @@ -322,58 +322,67 @@ static const char *fragmentShader_100 = {"\ return packedValue;\n\ }\n\ \n\ - void main() \n\ - { \n\ - vec4 mainTexColor = (polyEnableTexture) ? texture2D(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0); \n\ + void main()\n\ + {\n\ + vec4 newFragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\ + vec4 newPolyID = vec4(0.0, 0.0, 0.0, 0.0);\n\ + vec4 newFogAttributes = vec4(0.0, 0.0, 0.0, 0.0);\n\ + vec4 newFragDepth = vec4(0.0, 0.0, 0.0, 0.0);\n\ \n\ - if (texSingleBitAlpha)\n\ + float vertW = (vtxPosition.w == 0.0) ? 0.00000001 : vtxPosition.w;\n\ + // hack: when using z-depth, drop some LSBs so that the overworld map in Dragon Quest IV shows up correctly\n\ + float newFragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp( (floor((((vtxPosition.z/vertW) * 0.5 + 0.5) * 16777215.0) / 4.0) * 4.0) / 16777215.0, 0.0, 1.0);\n\ + \n\ + if (!bool(polySetupShadow))\n\ {\n\ - if (mainTexColor.a < 0.500)\n\ + vec4 mainTexColor = (polyEnableTexture) ? texture2D(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0);\n\ + \n\ + if (texSingleBitAlpha)\n\ {\n\ - mainTexColor.a = 0.0;\n\ + if (mainTexColor.a < 0.500)\n\ + {\n\ + mainTexColor.a = 0.0;\n\ + }\n\ + else\n\ + {\n\ + mainTexColor.rgb = mainTexColor.rgb / mainTexColor.a;\n\ + mainTexColor.a = 1.0;\n\ + }\n\ }\n\ - else\n\ + \n\ + vec4 newFragColor = mainTexColor * vtxColor;\n\ + \n\ + if(polyMode == 1)\n\ {\n\ - mainTexColor.rgb = mainTexColor.rgb / mainTexColor.a;\n\ - mainTexColor.a = 1.0;\n\ + newFragColor.rgb = (polyEnableTexture) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb;\n\ + newFragColor.a = vtxColor.a;\n\ }\n\ + else if(polyMode == 2)\n\ + {\n\ + vec3 toonColor = vec3(texture1D(texToonTable, vtxColor.r).rgb);\n\ + newFragColor.rgb = (stateToonShadingMode == 0) ? mainTexColor.rgb * toonColor.rgb : min((mainTexColor.rgb * vtxColor.r) + toonColor.rgb, 1.0);\n\ + }\n\ + else if(polyMode == 3)\n\ + {\n\ + newFragColor = vtxColor;\n\ + }\n\ + \n\ + if (newFragColor.a < 0.001 || (stateEnableAlphaTest && newFragColor.a < stateAlphaTestRef))\n\ + {\n\ + discard;\n\ + }\n\ + \n\ + newFragDepth = vec4( packVec3FromFloat(newFragDepth), float(polyEnableDepthWrite && (newFragColor.a > 0.999 || polySetNewDepthForTranslucent)));\n\ + newPolyID = vec4(float(polyID)/63.0, 0.0, 0.0, float(newFragColor.a > 0.999));\n\ + newFogAttributes = vec4(float(polyEnableFog), 0.0, 0.0, float((newFragColor.a > 0.999) ? 1.0 : 0.5));\n\ }\n\ \n\ - vec4 newFragColor = mainTexColor * vtxColor; \n\ - \n\ - if(polyMode == 1) \n\ - { \n\ - newFragColor.rgb = (polyEnableTexture) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb; \n\ - newFragColor.a = vtxColor.a; \n\ - } \n\ - else if(polyMode == 2) \n\ - { \n\ - vec3 toonColor = vec3(texture1D(texToonTable, vtxColor.r).rgb); \n\ - newFragColor.rgb = (stateToonShadingMode == 0) ? mainTexColor.rgb * toonColor.rgb : min((mainTexColor.rgb * vtxColor.r) + toonColor.rgb, 1.0); \n\ - } \n\ - else if(polyMode == 3) \n\ - { \n\ - if (polyID != 0) \n\ - { \n\ - newFragColor = vtxColor; \n\ - } \n\ - } \n\ - \n\ - if (newFragColor.a < 0.001 || (stateEnableAlphaTest && newFragColor.a < stateAlphaTestRef)) \n\ - { \n\ - discard; \n\ - } \n\ - \n\ - float vertW = (vtxPosition.w == 0.0) ? 0.00000001 : vtxPosition.w; \n\ - // hack: when using z-depth, drop some LSBs so that the overworld map in Dragon Quest IV shows up correctly\n\ - float newFragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp( (floor((((vtxPosition.z/vertW) * 0.5 + 0.5) * 16777215.0) / 4.0) * 4.0) / 16777215.0, 0.0, 1.0); \n\ - \n\ gl_FragData[0] = newFragColor;\n\ - gl_FragData[1] = vec4( packVec3FromFloat(newFragDepth), float(polyEnableDepthWrite && (newFragColor.a > 0.999 || polySetNewDepthForTranslucent)));\n\ - gl_FragData[2] = vec4(float(polyID)/63.0, 0.0, 0.0, float(newFragColor.a > 0.999));\n\ - gl_FragData[3] = vec4(float(polyEnableFog), 0.0, 0.0, float((newFragColor.a > 0.999) ? 1.0 : 0.5));\n\ + gl_FragData[1] = newFragDepth;\n\ + gl_FragData[2] = newPolyID;\n\ + gl_FragData[3] = newFogAttributes;\n\ gl_FragDepth = newFragDepth;\n\ - } \n\ + }\n\ "}; // Vertex shader for applying edge marking, GLSL 1.00 @@ -1623,7 +1632,7 @@ Render3DError OpenGLRenderer_1_2::InitGeometryProgramShaderLocations() OGLRef.uniformPolyTexScale = glGetUniformLocation(OGLRef.programGeometryID, "polyTexScale"); OGLRef.uniformPolyMode = glGetUniformLocation(OGLRef.programGeometryID, "polyMode"); - OGLRef.uniformPolyEnableDepthWrite = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableDepthWrite"); + OGLRef.uniformPolySetupShadow = glGetUniformLocation(OGLRef.programGeometryID, "polySetupShadow"); OGLRef.uniformPolySetNewDepthForTranslucent = glGetUniformLocation(OGLRef.programGeometryID, "polySetNewDepthForTranslucent"); OGLRef.uniformPolyAlpha = glGetUniformLocation(OGLRef.programGeometryID, "polyAlpha"); OGLRef.uniformPolyID = glGetUniformLocation(OGLRef.programGeometryID, "polyID"); @@ -2980,24 +2989,40 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly) glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]); // Set up culling mode - static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; - GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; - - if (cullingMode == 0) + if ( (attr.polygonMode == POLYGON_MODE_SHADOW) && (attr.polygonID != 0) ) { - glDisable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); } else { - glEnable(GL_CULL_FACE); - glCullFace(cullingMode); + static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; + GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; + + if (cullingMode == 0) + { + glDisable(GL_CULL_FACE); + } + else + { + glEnable(GL_CULL_FACE); + glCullFace(cullingMode); + } } - // Set up depth write - GLboolean enableDepthWrite = GL_TRUE; + // Set up color and depth write + if ( (attr.polygonMode == POLYGON_MODE_SHADOW) && (attr.polygonID == 0) ) + { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glDepthMask(GL_FALSE); + } + else + { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_TRUE); + } - // Handle shadow polys. Do this after checking for depth write, since shadow polys - // can change this too. + // Set up stencil testing if (attr.polygonMode == POLYGON_MODE_SHADOW) { glEnable(GL_STENCIL_TEST); @@ -3009,8 +3034,6 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly) //do not write color or depth information. glStencilFunc(GL_NOTEQUAL, 0x80, 0xFF); glStencilOp(GL_KEEP, GL_ZERO, GL_KEEP); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - enableDepthWrite = GL_FALSE; } else { @@ -3018,27 +3041,19 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly) //only draw the shadow poly where the stencilbuf==1. glStencilFunc(GL_EQUAL, 0, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - enableDepthWrite = GL_TRUE; } } else if ( attr.isTranslucent || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), attr.polygonID) == this->_shadowPolyID.end()) ) { glDisable(GL_STENCIL_TEST); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - enableDepthWrite = (!attr.isTranslucent || attr.isOpaque || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE; } else { glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 0x80, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - enableDepthWrite = GL_TRUE; } - glDepthMask(enableDepthWrite); - // Set up polygon attributes if (this->isShaderSupported) { @@ -3047,7 +3062,7 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly) glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog && !(attr.polygonMode == POLYGON_MODE_SHADOW && attr.polygonID == 0)) ? GL_TRUE : GL_FALSE); glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f); glUniform1i(OGLRef.uniformPolyID, attr.polygonID); - glUniform1i(OGLRef.uniformPolyEnableDepthWrite, (!(attr.polygonMode == POLYGON_MODE_SHADOW && attr.polygonID == 0)) ? GL_TRUE : GL_FALSE); + glUniform1i(OGLRef.uniformPolySetupShadow, ( (attr.polygonMode == POLYGON_MODE_SHADOW) && (attr.polygonID == 0) ) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE); } else @@ -4582,24 +4597,40 @@ Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY &thePoly) glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]); // Set up culling mode - static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; - GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; - - if (cullingMode == 0) + if ( (attr.polygonMode == POLYGON_MODE_SHADOW) && (attr.polygonID != 0) ) { - glDisable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); } else { - glEnable(GL_CULL_FACE); - glCullFace(cullingMode); + static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; + GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; + + if (cullingMode == 0) + { + glDisable(GL_CULL_FACE); + } + else + { + glEnable(GL_CULL_FACE); + glCullFace(cullingMode); + } } - // Set up depth write - GLboolean enableDepthWrite = GL_TRUE; + // Set up color and depth write + if ( (attr.polygonMode == POLYGON_MODE_SHADOW) && (attr.polygonID == 0) ) + { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glDepthMask(GL_FALSE); + } + else + { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_TRUE); + } - // Handle shadow polys. Do this after checking for depth write, since shadow polys - // can change this too. + // Set up stencil testing if (attr.polygonMode == POLYGON_MODE_SHADOW) { glEnable(GL_STENCIL_TEST); @@ -4611,8 +4642,6 @@ Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY &thePoly) //do not write color or depth information. glStencilFunc(GL_NOTEQUAL, 0x80, 0xFF); glStencilOp(GL_KEEP, GL_ZERO, GL_KEEP); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - enableDepthWrite = GL_FALSE; } else { @@ -4620,34 +4649,26 @@ Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY &thePoly) //only draw the shadow poly where the stencilbuf==1. glStencilFunc(GL_EQUAL, 0, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - enableDepthWrite = GL_TRUE; } } else if ( attr.isTranslucent || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), attr.polygonID) == this->_shadowPolyID.end()) ) { glDisable(GL_STENCIL_TEST); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - enableDepthWrite = (!attr.isTranslucent || attr.isOpaque || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE; } else { glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 0x80, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - enableDepthWrite = GL_TRUE; } - glDepthMask(enableDepthWrite); - // Set up polygon attributes OGLRenderRef &OGLRef = *this->ref; glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode); glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog && !(attr.polygonMode == POLYGON_MODE_SHADOW && attr.polygonID == 0)) ? GL_TRUE : GL_FALSE); glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f); glUniform1i(OGLRef.uniformPolyID, attr.polygonID); - glUniform1i(OGLRef.uniformPolyEnableDepthWrite, (!(attr.polygonMode == POLYGON_MODE_SHADOW && attr.polygonID == 0)) ? GL_TRUE : GL_FALSE); + glUniform1i(OGLRef.uniformPolySetupShadow, ( (attr.polygonMode == POLYGON_MODE_SHADOW) && (attr.polygonID == 0) ) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE); return OGLERROR_NOERR; diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index 89e35c88e..c356f2ac5 100644 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -377,7 +377,7 @@ struct OGLPolyStates { union { - struct { GLubyte enableTexture, enableFog, enableDepthWrite, setNewDepthForTranslucent; }; + struct { GLubyte enableTexture, enableFog, setupShadowPoly, setNewDepthForTranslucent; }; GLubyte flags[4]; }; @@ -474,7 +474,7 @@ struct OGLRenderRef GLint uniformPolyTexScale; GLint uniformPolyMode; - GLint uniformPolyEnableDepthWrite; + GLint uniformPolySetupShadow; GLint uniformPolySetNewDepthForTranslucent; GLint uniformPolyAlpha; GLint uniformPolyID; diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 94eb62356..640fb4dd5 100644 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -116,7 +116,7 @@ static const char *GeometryVtxShader_150 = {"\ out vec4 vtxColor; \n\ flat out uint polyEnableTexture;\n\ flat out uint polyEnableFog;\n\ - flat out uint polyEnableDepthWrite;\n\ + flat out uint polySetupShadow;\n\ flat out uint polySetNewDepthForTranslucent;\n\ flat out uint polyMode;\n\ flat out uint polyID;\n\ @@ -133,7 +133,7 @@ static const char *GeometryVtxShader_150 = {"\ \n\ polyEnableTexture = polyStateFlags[0];\n\ polyEnableFog = polyStateFlags[1];\n\ - polyEnableDepthWrite = polyStateFlags[2];\n\ + polySetupShadow = polyStateFlags[2];\n\ polySetNewDepthForTranslucent = polyStateFlags[3];\n\ polyMode = polyStateValues[1];\n\ polyID = polyStateValues[2];\n\ @@ -154,12 +154,12 @@ static const char *GeometryVtxShader_150 = {"\ static const char *GeometryFragShader_150 = {"\ #version 150 \n\ \n\ - in vec4 vtxPosition; \n\ - in vec2 vtxTexCoord; \n\ - in vec4 vtxColor; \n\ + in vec4 vtxPosition;\n\ + in vec2 vtxTexCoord;\n\ + in vec4 vtxColor;\n\ flat in uint polyEnableTexture;\n\ flat in uint polyEnableFog;\n\ - flat in uint polyEnableDepthWrite;\n\ + flat in uint polySetupShadow;\n\ flat in uint polySetNewDepthForTranslucent;\n\ flat in uint polyMode;\n\ flat in uint polyID;\n\ @@ -184,7 +184,7 @@ static const char *GeometryFragShader_150 = {"\ vec4 toonColor[32];\n\ } state;\n\ \n\ - uniform sampler2D texRenderObject; \n\ + uniform sampler2D texRenderObject;\n\ uniform usamplerBuffer PolyStates;\n\ uniform int polyIndex;\n\ \n\ @@ -200,58 +200,67 @@ static const char *GeometryFragShader_150 = {"\ return packedValue;\n\ }\n\ \n\ - void main() \n\ - { \n\ - vec4 mainTexColor = bool(polyEnableTexture) ? texture(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0);\n\ + void main()\n\ + {\n\ + vec4 newFragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\ + vec4 newPolyID = vec4(0.0, 0.0, 0.0, 0.0);\n\ + vec4 newFogAttributes = vec4(0.0, 0.0, 0.0, 0.0);\n\ + vec4 newFragDepth = vec4(0.0, 0.0, 0.0, 0.0);\n\ \n\ - if (bool(texSingleBitAlpha))\n\ - {\n\ - if (mainTexColor.a < 0.500)\n\ - {\n\ - mainTexColor.a = 0.0;\n\ - }\n\ - else\n\ - {\n\ - mainTexColor.rgb = mainTexColor.rgb / mainTexColor.a;\n\ - mainTexColor.a = 1.0;\n\ - }\n\ - }\n\ - \n\ - vec4 newFragColor = mainTexColor * vtxColor; \n\ - \n\ - if (polyMode == 1u) \n\ - { \n\ - newFragColor.rgb = bool(polyEnableTexture) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb;\n\ - newFragColor.a = vtxColor.a; \n\ - } \n\ - else if (polyMode == 2u) \n\ - { \n\ - vec3 newToonColor = state.toonColor[int((vtxColor.r * 31.0) + 0.5)].rgb;\n\ - newFragColor.rgb = (state.toonShadingMode == 0) ? mainTexColor.rgb * newToonColor.rgb : min((mainTexColor.rgb * vtxColor.r) + newToonColor.rgb, 1.0); \n\ - } \n\ - else if (polyMode == 3u) \n\ - { \n\ - if (polyID != 0u) \n\ - { \n\ - newFragColor = vtxColor; \n\ - } \n\ - } \n\ - \n\ - if (newFragColor.a < 0.001 || (state.enableAlphaTest && newFragColor.a < state.alphaTestRef))\n\ - {\n\ - discard;\n\ - }\n\ - \n\ - float vertW = (vtxPosition.w == 0.0) ? 0.00000001 : vtxPosition.w; \n\ + float vertW = (vtxPosition.w == 0.0) ? 0.00000001 : vtxPosition.w;\n\ // hack: when using z-depth, drop some LSBs so that the overworld map in Dragon Quest IV shows up correctly\n\ - float newFragDepth = (state.useWDepth) ? vtxPosition.w/4096.0 : clamp( (floor((((vtxPosition.z/vertW) * 0.5 + 0.5) * 16777215.0) / 4.0) * 4.0) / 16777215.0, 0.0, 1.0); \n\ + float newFragDepthValue = (state.useWDepth) ? vtxPosition.w/4096.0 : clamp( (floor((((vtxPosition.z/vertW) * 0.5 + 0.5) * 16777215.0) / 4.0) * 4.0) / 16777215.0, 0.0, 1.0);\n\ + \n\ + if (!bool(polySetupShadow))\n\ + {\n\ + vec4 mainTexColor = bool(polyEnableTexture) ? texture(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0);\n\ + \n\ + if (bool(texSingleBitAlpha))\n\ + {\n\ + if (mainTexColor.a < 0.500)\n\ + {\n\ + mainTexColor.a = 0.0;\n\ + }\n\ + else\n\ + {\n\ + mainTexColor.rgb = mainTexColor.rgb / mainTexColor.a;\n\ + mainTexColor.a = 1.0;\n\ + }\n\ + }\n\ + \n\ + newFragColor = mainTexColor * vtxColor;\n\ + \n\ + if (polyMode == 1u)\n\ + {\n\ + newFragColor.rgb = bool(polyEnableTexture) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb;\n\ + newFragColor.a = vtxColor.a;\n\ + }\n\ + else if (polyMode == 2u)\n\ + {\n\ + vec3 newToonColor = state.toonColor[int((vtxColor.r * 31.0) + 0.5)].rgb;\n\ + newFragColor.rgb = (state.toonShadingMode == 0) ? mainTexColor.rgb * newToonColor.rgb : min((mainTexColor.rgb * vtxColor.r) + newToonColor.rgb, 1.0);\n\ + }\n\ + else if (polyMode == 3u)\n\ + {\n\ + newFragColor = vtxColor;\n\ + }\n\ + \n\ + if (newFragColor.a < 0.001 || (state.enableAlphaTest && newFragColor.a < state.alphaTestRef))\n\ + {\n\ + discard;\n\ + }\n\ + \n\ + newFragDepth = vec4( packVec3FromFloat(newFragDepthValue), float((newFragColor.a > 0.999) || bool(polySetNewDepthForTranslucent)) );\n\ + newPolyID = vec4(float(polyID)/63.0, 0.0, 0.0, float(newFragColor.a > 0.999));\n\ + newFogAttributes = vec4(float(polyEnableFog), 0.0, 0.0, float((newFragColor.a > 0.999) ? 1.0 : 0.5));\n\ + }\n\ \n\ outFragColor = newFragColor;\n\ - outFragDepth = vec4( packVec3FromFloat(newFragDepth), float(bool(polyEnableDepthWrite) && (newFragColor.a > 0.999 || bool(polySetNewDepthForTranslucent))));\n\ - outPolyID = vec4(float(polyID)/63.0, 0.0, 0.0, float(newFragColor.a > 0.999));\n\ - outFogAttributes = vec4(float(polyEnableFog), 0.0, 0.0, float((newFragColor.a > 0.999) ? 1.0 : 0.5));\n\ - gl_FragDepth = newFragDepth;\n\ - } \n\ + outFragDepth = newFragDepth;\n\ + outPolyID = newPolyID;\n\ + outFogAttributes = newFogAttributes;\n\ + gl_FragDepth = newFragDepthValue;\n\ + }\n\ "}; // Vertex shader for applying edge marking, GLSL 1.50 @@ -1431,7 +1440,7 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine) polyStates[i].enableTexture = (this->_textureList[i]->IsSamplingEnabled()) ? GL_TRUE : GL_FALSE; polyStates[i].enableFog = (polyAttr.enableRenderFog && !(polyAttr.polygonMode == POLYGON_MODE_SHADOW && polyAttr.polygonID == 0)) ? GL_TRUE : GL_FALSE; - polyStates[i].enableDepthWrite = !(polyAttr.polygonMode == POLYGON_MODE_SHADOW && polyAttr.polygonID == 0) ? GL_TRUE : GL_FALSE; + polyStates[i].setupShadowPoly = (polyAttr.polygonMode == POLYGON_MODE_SHADOW && polyAttr.polygonID == 0) ? GL_TRUE : GL_FALSE; polyStates[i].setNewDepthForTranslucent = (polyAttr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE; polyStates[i].polyAlpha = (!polyAttr.isWireframe && polyAttr.isTranslucent) ? polyAttr.alpha : 0x1F; polyStates[i].polyMode = polyAttr.polygonMode; @@ -1623,24 +1632,40 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly) glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]); // Set up culling mode - static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; - GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; - - if (cullingMode == 0) + if ( (attr.polygonMode == POLYGON_MODE_SHADOW) && (attr.polygonID != 0) ) { - glDisable(GL_CULL_FACE); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); } else { - glEnable(GL_CULL_FACE); - glCullFace(cullingMode); + static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; + GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; + + if (cullingMode == 0) + { + glDisable(GL_CULL_FACE); + } + else + { + glEnable(GL_CULL_FACE); + glCullFace(cullingMode); + } } - // Set up depth write - GLboolean enableDepthWrite = GL_TRUE; + // Set up color and depth write + if ( (attr.polygonMode == POLYGON_MODE_SHADOW) && (attr.polygonID == 0) ) + { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glDepthMask(GL_FALSE); + } + else + { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_TRUE); + } - // Handle shadow polys. Do this after checking for depth write, since shadow polys - // can change this too. + // Set up stencil testing if (attr.polygonMode == POLYGON_MODE_SHADOW) { glEnable(GL_STENCIL_TEST); @@ -1652,8 +1677,6 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly) //do not write color or depth information. glStencilFunc(GL_NOTEQUAL, 0x80, 0xFF); glStencilOp(GL_KEEP, GL_ZERO, GL_KEEP); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - enableDepthWrite = GL_FALSE; } else { @@ -1661,27 +1684,19 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly) //only draw the shadow poly where the stencilbuf==1. glStencilFunc(GL_EQUAL, 0, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - enableDepthWrite = GL_TRUE; } } else if ( attr.isTranslucent || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), attr.polygonID) == this->_shadowPolyID.end()) ) { glDisable(GL_STENCIL_TEST); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - enableDepthWrite = (!attr.isTranslucent || attr.isOpaque || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE; } else { glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 0x80, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - enableDepthWrite = GL_TRUE; } - glDepthMask(enableDepthWrite); - return OGLERROR_NOERR; }