diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 55eff9960..fa2a6ffd5 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -3012,25 +3012,17 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly) glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]); // Set up culling mode - if ( (attr.polygonMode == POLYGON_MODE_SHADOW) && (attr.polygonID != 0) ) + static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; + GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; + + if (cullingMode == 0) { - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); + glDisable(GL_CULL_FACE); } else { - 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); - } + glEnable(GL_CULL_FACE); + glCullFace(cullingMode); } // Handle drawing states for the polygon diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 3af1abd98..d7f4cc0bb 100644 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -1660,25 +1660,17 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly) glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]); // Set up culling mode - if ( (attr.polygonMode == POLYGON_MODE_SHADOW) && (attr.polygonID != 0) ) + static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; + GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; + + if (cullingMode == 0) { - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); + glDisable(GL_CULL_FACE); } else { - 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); - } + glEnable(GL_CULL_FACE); + glCullFace(cullingMode); } // Handle drawing states for the polygon diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index 9905ff2e0..cc3b1f1d5 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -1565,15 +1565,37 @@ void SoftRasterizerRenderer::GetAndLoadAllTextures() bool PolygonIsVisible(const PolygonAttributes &polyAttr, const bool backfacing) { - //this was added after adding multi-bit stencil buffer - //it seems that we also need to prevent drawing back faces of shadow polys for rendering + // Force backface culling when drawing shadow polygons. if (polyAttr.polygonMode == POLYGON_MODE_SHADOW && polyAttr.polygonID != 0) return !backfacing; + // 2009/08/02 initial comments: + //this was added after adding multi-bit stencil buffer + //it seems that we also need to prevent drawing back faces of shadow polys for rendering + // //another reasonable possibility is that we should be forcing back faces to draw (mariokart doesnt use them) //and then only using a single bit buffer (but a cursory test of this doesnt actually work) // //this code needs to be here for shadows in wizard of oz to work. + // 2016/12/30 update: + // According to GBATEK, there really shouldn't be any special case for forcing backface culling on shadow + // polygons. All polygons, regardless of what they are, should always respect the culling mode. This is + // necessary for Mario Kart DS, where shadow polygons will fail to render under the Karts during Kart select + // if backface culling is forced (only fails for 150cc MIRROR, but works on the normal 150cc). Apparently, + // Mario Kart does use the backfaces of shadow polygons, but only for 150cc MIRROR and not the normal 150cc! + // + // However, there are a number of test cases where forcing backface culling is beneficial for the proper + // rendering of shadows, including: + // 1. The Wizard of Oz: Beyond the Yellow Brick Road -- shadows under Dorothy and Toto + // 2. Kingdom Hearts Re:coded -- shadow under Sora + // 3. Golden Sun: Dark Dawn -- shadow under the main character + // + // Based on these tests, we will need to rework shadow polygon handling at some point to pass all of these + // conditions. To note, the OpenGL renderer does render shadow polygons properly, without forced backface + // culling, for every one of these test cases. + // + // TODO: Rework shadow polygon handling in SoftRasterizer. + switch (polyAttr.surfaceCullingMode) { case 0: return false;