diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 182ae9eca..d2fef94fe 100755 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -84,11 +84,15 @@ CACHE_ALIGN const GLfloat divide6bitBy63_LUT[64] = {0.0, 0.015873015 const GLfloat PostprocessVtxBuffer[16] = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f}; -const GLenum GeometryDrawBuffersList[4][3] = { - { GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_NONE }, - { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_NONE }, - { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_NONE }, - { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT } +const GLenum GeometryDrawBuffersList[8][4] = { + { GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_NONE, GL_NONE }, + { GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2_EXT }, + { GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_COLOR_ATTACHMENT1_EXT, GL_NONE }, + { GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT }, + { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_NONE, GL_NONE }, + { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_NONE, GL_COLOR_ATTACHMENT2_EXT }, + { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_NONE }, + { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT } }; bool BEGINGL() @@ -318,9 +322,14 @@ uniform bool polyEnableFog;\n\ uniform bool texDrawOpaque;\n\ uniform bool texSingleBitAlpha;\n\ \n\ +uniform bool drawModeDepthEqualsTest;\n\ uniform bool polyDrawShadow;\n\ uniform int polyDepthOffsetMode;\n\ \n\ +#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\ +uniform sampler2D inBackFacing;\n\ +#endif\n\ +\n\ void main()\n\ {\n\ vec4 newFragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\ @@ -386,6 +395,17 @@ void main()\n\ discard;\n\ }\n\ \n\ +#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\ + if (drawModeDepthEqualsTest)\n\ + {\n\ + bool isOpaqueDstBackFacing = bool( texture2D(inBackFacing, vec2(gl_FragCoord.x/FRAMEBUFFER_SIZE_X, gl_FragCoord.y/FRAMEBUFFER_SIZE_Y)).r );\n\ + if ( !gl_FrontFacing || !isOpaqueDstBackFacing )\n\ + {\n\ + discard;\n\ + }\n\ + }\n\ +#endif\n\ + \n\ #if ENABLE_EDGE_MARK\n\ newPolyID = vec4( float(polyID)/63.0, float(polyIsWireframe), 0.0, float(newFragColor.a > 0.999) );\n\ #endif\n\ @@ -396,13 +416,14 @@ void main()\n\ \n\ gl_FragData[0] = newFragColor;\n\ \n\ -#if ENABLE_EDGE_MARK && ENABLE_FOG\n\ - gl_FragData[1] = newPolyID;\n\ - gl_FragData[2] = newFogAttributes;\n\ -#elif ENABLE_EDGE_MARK\n\ - gl_FragData[1] = newPolyID;\n\ -#elif ENABLE_FOG\n\ - gl_FragData[1] = newFogAttributes;\n\ +#if USE_DEPTH_LEQUAL_POLYGON_FACING && DRAW_MODE_OPAQUE\n\ + gl_FragData[1] = vec4(float(!gl_FrontFacing), 0.0, 0.0, 1.0);\n\ +#endif\n\ +#if ENABLE_EDGE_MARK\n\ + gl_FragData[2] = newPolyID;\n\ +#endif\n\ +#if ENABLE_FOG\n\ + gl_FragData[3] = newFogAttributes;\n\ #endif\n\ #if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\n\ // It is tempting to perform the NDS depth calculation in the vertex shader rather than in the fragment shader.\n\ @@ -1256,6 +1277,7 @@ OpenGLRenderer::OpenGLRenderer() _needsZeroDstAlphaPass = true; _renderNeedsDepthEqualsTest = false; _currentPolyIndex = 0; + _currentAlphaTestRef = 0; _lastTextureDrawTarget = OGLTextureUnitID_GColor; _geometryProgramFlags.value = 0; _fogProgramMap.clear(); @@ -2133,6 +2155,15 @@ Render3DError OpenGLRenderer::DrawAlphaTexturePolygon(const GLenum polyPrimitive else if (DRAWMODE != OGLPolyDrawMode_DrawOpaquePolys) { // Draw the translucent fragments. + if (this->_emulateDepthLEqualPolygonFacing && isPolyFrontFacing) + { + glDepthFunc(GL_EQUAL); + glUniform1i(OGLRef.uniformDrawModeDepthEqualsTest[this->_geometryProgramFlags.value], GL_TRUE); + glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); + + glDepthFunc(GL_LESS); + glUniform1i(OGLRef.uniformDrawModeDepthEqualsTest[this->_geometryProgramFlags.value], GL_FALSE); + } glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); // Draw the opaque fragments if they might exist. @@ -2146,6 +2177,15 @@ Render3DError OpenGLRenderer::DrawAlphaTexturePolygon(const GLenum polyPrimitive } glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_TRUE); + if (this->_emulateDepthLEqualPolygonFacing && isPolyFrontFacing) + { + glDepthFunc(GL_EQUAL); + glUniform1i(OGLRef.uniformDrawModeDepthEqualsTest[this->_geometryProgramFlags.value], GL_TRUE); + glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); + + glDepthFunc(GL_LESS); + glUniform1i(OGLRef.uniformDrawModeDepthEqualsTest[this->_geometryProgramFlags.value], GL_FALSE); + } glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); @@ -2285,38 +2325,54 @@ Render3DError OpenGLRenderer::DrawOtherPolygon(const GLenum polyPrimitive, glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(((DRAWMODE == OGLPolyDrawMode_DrawOpaquePolys) || enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE); } - else if ((DRAWMODE == OGLPolyDrawMode_DrawOpaquePolys) && this->_emulateDepthLEqualPolygonFacing) + else if (DRAWMODE == OGLPolyDrawMode_DrawOpaquePolys) { - if (isPolyFrontFacing) + if (this->_emulateDepthLEqualPolygonFacing) { - glDepthFunc(GL_EQUAL); - glStencilFunc(GL_EQUAL, 0x40 | opaquePolyID, 0x40); - glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); - - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - glDepthMask(GL_FALSE); - glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); - glStencilMask(0x40); - glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); - - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask(GL_TRUE); - glDepthFunc(GL_LESS); - glStencilFunc(GL_ALWAYS, opaquePolyID, 0x3F); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glStencilMask(0xFF); - glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); + if (isPolyFrontFacing) + { + glDepthFunc(GL_EQUAL); + glStencilFunc(GL_EQUAL, 0x40 | opaquePolyID, 0x40); + glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); + + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glDepthMask(GL_FALSE); + glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); + glStencilMask(0x40); + glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_TRUE); + glDepthFunc(GL_LESS); + glStencilFunc(GL_ALWAYS, opaquePolyID, 0x3F); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilMask(0xFF); + glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); + } + else + { + glStencilFunc(GL_ALWAYS, 0x40 | opaquePolyID, 0x40); + glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); + + glStencilFunc(GL_ALWAYS, opaquePolyID, 0x3F); + } } else { - glStencilFunc(GL_ALWAYS, 0x40 | opaquePolyID, 0x40); glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); - - glStencilFunc(GL_ALWAYS, opaquePolyID, 0x3F); } } else { + if (this->_emulateDepthLEqualPolygonFacing && isPolyFrontFacing) + { + glDepthFunc(GL_EQUAL); + glUniform1i(OGLRef.uniformDrawModeDepthEqualsTest[this->_geometryProgramFlags.value], GL_TRUE); + glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); + + glDepthFunc(GL_LESS); + glUniform1i(OGLRef.uniformDrawModeDepthEqualsTest[this->_geometryProgramFlags.value], GL_FALSE); + } glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); } @@ -2330,11 +2386,12 @@ Render3DError OpenGLRenderer::ApplyRenderingSettings(const GFX3D_State &renderSt const bool didSelectedMultisampleSizeChange = (this->_selectedMultisampleSize != CommonSettings.GFX3D_Renderer_MultisampleSize); const bool didEmulateNDSDepthCalculationChange = (this->_emulateNDSDepthCalculation != CommonSettings.OpenGL_Emulation_NDSDepthCalculation); const bool didEnableTextureSmoothingChange = (this->_enableTextureSmoothing != CommonSettings.GFX3D_Renderer_TextureSmoothing); + const bool didEmulateDepthLEqualPolygonFacingChange = (this->_emulateDepthLEqualPolygonFacing != (CommonSettings.OpenGL_Emulation_DepthLEqualPolygonFacing && this->isShaderSupported)); this->_emulateShadowPolygon = CommonSettings.OpenGL_Emulation_ShadowPolygon; this->_emulateSpecialZeroAlphaBlending = CommonSettings.OpenGL_Emulation_SpecialZeroAlphaBlending; this->_emulateNDSDepthCalculation = CommonSettings.OpenGL_Emulation_NDSDepthCalculation; - this->_emulateDepthLEqualPolygonFacing = CommonSettings.OpenGL_Emulation_DepthLEqualPolygonFacing; + this->_emulateDepthLEqualPolygonFacing = CommonSettings.OpenGL_Emulation_DepthLEqualPolygonFacing && this->isShaderSupported; this->_selectedMultisampleSize = CommonSettings.GFX3D_Renderer_MultisampleSize; this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported); @@ -2347,7 +2404,8 @@ Render3DError OpenGLRenderer::ApplyRenderingSettings(const GFX3D_State &renderSt if (didSelectedMultisampleSizeChange || didEmulateNDSDepthCalculationChange || - didEnableTextureSmoothingChange ) + didEnableTextureSmoothingChange || + didEmulateDepthLEqualPolygonFacingChange) { if (!BEGINGL()) { @@ -2362,7 +2420,8 @@ Render3DError OpenGLRenderer::ApplyRenderingSettings(const GFX3D_State &renderSt if ( this->isShaderSupported && (didEmulateNDSDepthCalculationChange || - didEnableTextureSmoothingChange) ) + didEnableTextureSmoothingChange || + didEmulateDepthLEqualPolygonFacingChange) ) { glUseProgram(0); this->DestroyGeometryPrograms(); @@ -2955,12 +3014,15 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO(GLsizei numSamples) // Set up FBO render targets glGenRenderbuffersEXT(1, &OGLRef.rboMSGColorID); + glGenRenderbuffersEXT(1, &OGLRef.rboMSGWorkingID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGWorkingID); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); @@ -2974,6 +3036,7 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO(GLsizei numSamples) glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGWorkingID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); @@ -3006,11 +3069,17 @@ void OpenGLRenderer_1_2::DestroyMultisampledFBO() glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGColorID); + glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGWorkingID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); OGLRef.fboMSIntermediateRenderID = 0; + OGLRef.rboMSGColorID = 0; + OGLRef.rboMSGWorkingID = 0; + OGLRef.rboMSGPolyID = 0; + OGLRef.rboMSGFogAttrID = 0; + OGLRef.rboMSGDepthStencilID = 0; this->isMultisampledFBOSupported = false; } @@ -3037,6 +3106,8 @@ void OpenGLRenderer_1_2::ResizeMultisampledFBOs(GLsizei numSamples) glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, w, h); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGWorkingID); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, w, h); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, w, h); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); @@ -3054,22 +3125,27 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms() programFlags.value = 0; std::stringstream fragShaderHeader; + fragShaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n"; + fragShaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n"; + fragShaderHeader << "\n"; fragShaderHeader << "#define DEPTH_EQUALS_TEST_TOLERANCE " << DEPTH_EQUALS_TEST_TOLERANCE << ".0 \n"; fragShaderHeader << "\n"; - for (size_t flagsValue = 0; flagsValue < 128; flagsValue++, programFlags.value++) + for (size_t flagsValue = 0; flagsValue < 256; flagsValue++, programFlags.value++) { std::stringstream shaderFlags; shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n"; shaderFlags << "#define USE_NDS_DEPTH_CALCULATION " << ((this->_emulateNDSDepthCalculation) ? 1 : 0) << "\n"; + shaderFlags << "#define USE_DEPTH_LEQUAL_POLYGON_FACING " << ((this->_emulateDepthLEqualPolygonFacing) ? 1 : 0) << "\n"; shaderFlags << "\n"; shaderFlags << "#define ENABLE_W_DEPTH " << ((programFlags.EnableWDepth) ? 1 : 0) << "\n"; shaderFlags << "#define ENABLE_ALPHA_TEST " << ((programFlags.EnableAlphaTest) ? "true\n" : "false\n"); shaderFlags << "#define ENABLE_TEXTURE_SAMPLING " << ((programFlags.EnableTextureSampling) ? "true\n" : "false\n"); - shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog) ? 1 : 0) << "\n"; - shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark) ? 1 : 0) << "\n"; shaderFlags << "#define TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n"; shaderFlags << "#define NEEDS_DEPTH_EQUALS_TEST " << ((programFlags.NeedsDepthEqualsTest) ? 1 : 0) << "\n"; + shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog) ? 1 : 0) << "\n"; + shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark) ? 1 : 0) << "\n"; + shaderFlags << "#define DRAW_MODE_OPAQUE " << ((programFlags.OpaqueDrawMode) ? 1 : 0) << "\n"; shaderFlags << "\n"; std::string fragShaderCode = fragShaderHeader.str() + shaderFlags.str() + std::string(GeometryFragShader_100); @@ -3108,6 +3184,12 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms() glUniform1i(uniformTexRenderObject, 0); glUniform1i(uniformTexToonTable, OGLTextureUnitID_ToonTable); + if (this->_emulateDepthLEqualPolygonFacing && !programFlags.OpaqueDrawMode) + { + const GLint uniformTexBackfacing = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "inBackFacing"); + glUniform1i(uniformTexBackfacing, OGLTextureUnitID_FinalColor); + } + OGLRef.uniformStateAlphaTestRef[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "stateAlphaTestRef"); OGLRef.uniformPolyTexScale[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyTexScale"); @@ -3122,6 +3204,7 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms() OGLRef.uniformTexSingleBitAlpha[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texSingleBitAlpha"); OGLRef.uniformTexDrawOpaque[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texDrawOpaque"); + OGLRef.uniformDrawModeDepthEqualsTest[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "drawModeDepthEqualsTest"); OGLRef.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow"); OGLRef.uniformPolyDepthOffsetMode[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffsetMode"); } @@ -3140,7 +3223,7 @@ void OpenGLRenderer_1_2::DestroyGeometryPrograms() OGLRenderRef &OGLRef = *this->ref; - for (size_t flagsValue = 0; flagsValue < 128; flagsValue++) + for (size_t flagsValue = 0; flagsValue < 256; flagsValue++) { if (OGLRef.programGeometryID[flagsValue] == 0) { @@ -3896,6 +3979,33 @@ void OpenGLRenderer_1_2::GetExtensionSet(std::set *oglExtensionSet) } } +void OpenGLRenderer_1_2::_SetupGeometryShaders(const OGLGeometryFlags flags) +{ + const OGLRenderRef &OGLRef = *this->ref; + + if (!this->isShaderSupported) + { + return; + } + + glUseProgram(OGLRef.programGeometryID[flags.value]); + glUniform1i(OGLRef.uniformStateClearPolyID, this->_clearAttributes.opaquePolyID); + glUniform1f(OGLRef.uniformStateClearDepth, (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF); + glUniform1f(OGLRef.uniformStateAlphaTestRef[flags.value], divide5bitBy31_LUT[this->_currentAlphaTestRef]); + glUniform1i(OGLRef.uniformTexDrawOpaque[flags.value], GL_FALSE); + glUniform1i(OGLRef.uniformDrawModeDepthEqualsTest[flags.value], GL_FALSE); + glUniform1i(OGLRef.uniformPolyDrawShadow[flags.value], GL_FALSE); + + if (this->isFBOSupported) + { + glDrawBuffers(4, GeometryDrawBuffersList[flags.DrawBuffersMode]); + } + else + { + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + } +} + Render3DError OpenGLRenderer_1_2::EnableVertexAttributes() { OGLRenderRef &OGLRef = *this->ref; @@ -3989,7 +4099,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); } @@ -4036,17 +4146,14 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags; this->_geometryProgramFlags.EnableEdgeMark = 0; this->_geometryProgramFlags.EnableFog = 0; - - glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); - glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); - glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE); + this->_SetupGeometryShaders(this->_geometryProgramFlags); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); this->EnableVertexAttributes(); // Draw the alpha polys, touching fully transparent pixels only once. - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glEnable(GL_DEPTH_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); @@ -4055,8 +4162,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con // Restore OpenGL states back to normal. this->_geometryProgramFlags = oldGProgramFlags; - glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + this->_SetupGeometryShaders(this->_geometryProgramFlags); glClear(GL_STENCIL_BUFFER_BIT); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); @@ -4074,54 +4180,76 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::DownsampleFBO() +void OpenGLRenderer_1_2::_ResolveWorkingBackFacing() { OGLRenderRef &OGLRef = *this->ref; - if (this->isMultisampledFBOSupported && (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID)) + if (!this->_emulateDepthLEqualPolygonFacing || !this->isMultisampledFBOSupported || (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID)) { - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); - - if (this->isShaderSupported) - { - if (this->_enableEdgeMark) - { - // Blit the polygon ID buffer - glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); - glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - - if (this->_enableFog) - { - // Blit the fog buffer - glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); - glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); - glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - - // Blit the color and depth buffers - glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - - // Reset framebuffer targets - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); - } - else - { - // Blit the color buffer - glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); - glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - } + return; } - return OGLERROR_NOERR; + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + + glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + // Reset framebuffer targets + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); +} + +void OpenGLRenderer_1_2::_ResolveGeometry() +{ + OGLRenderRef &OGLRef = *this->ref; + + if (!this->isMultisampledFBOSupported || (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID)) + { + return; + } + + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + + if (this->isShaderSupported) + { + if (this->_enableEdgeMark) + { + // Blit the polygon ID buffer + glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + + if (this->_enableFog) + { + // Blit the fog buffer + glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + + // Blit the color and depth buffers + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + + // Reset framebuffer targets + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + } + else + { + // Blit the color buffer + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + } } Render3DError OpenGLRenderer_1_2::ReadBackPixels() @@ -4363,17 +4491,14 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine) this->_geometryProgramFlags.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0; this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0; this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0; - this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0; - this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0; this->_geometryProgramFlags.ToonShadingMode = (engine.renderState.shading) ? 1 : 0; this->_geometryProgramFlags.NeedsDepthEqualsTest = (this->_renderNeedsDepthEqualsTest) ? 1 : 0; + this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0; + this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0; + this->_geometryProgramFlags.OpaqueDrawMode = 1; - glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); - glUniform1i(OGLRef.uniformStateClearPolyID, this->_clearAttributes.opaquePolyID); - glUniform1f(OGLRef.uniformStateClearDepth, (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF); - glUniform1f(OGLRef.uniformStateAlphaTestRef[this->_geometryProgramFlags.value], divide5bitBy31_LUT[engine.renderState.alphaTestRef]); - glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); - glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE); + this->_currentAlphaTestRef = engine.renderState.alphaTestRef; + this->_SetupGeometryShaders(this->_geometryProgramFlags); } else { @@ -4390,11 +4515,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine) glLoadIdentity(); } - if (this->isFBOSupported && this->isShaderSupported) - { - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); - } - else + if (!this->isFBOSupported || !this->isShaderSupported) { glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); } @@ -4442,6 +4563,8 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, if (this->_clippedPolyOpaqueCount < this->_clippedPolyCount) { + this->_geometryProgramFlags.OpaqueDrawMode = 0; + if (this->_needsZeroDstAlphaPass && this->_emulateSpecialZeroAlphaBlending) { if (this->_clippedPolyOpaqueCount == 0) @@ -4466,12 +4589,18 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); glStencilMask(0xFF); + + this->_SetupGeometryShaders(this->_geometryProgramFlags); } if (this->_clippedPolyOpaqueCount == 0) { this->SetupPolygon(firstPoly, true, true); } + else + { + this->_ResolveWorkingBackFacing(); + } this->DrawPolygonsForIndexRange(polyList, indexList, this->_clippedPolyOpaqueCount, this->_clippedPolyCount - 1, indexOffset, lastPolyAttr); } @@ -4481,7 +4610,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, this->DisableVertexAttributes(); } - this->DownsampleFBO(); + this->_ResolveGeometry(); this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; @@ -4733,6 +4862,13 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf if (this->isShaderSupported) { + if (this->_emulateDepthLEqualPolygonFacing) + { + glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + } + if (this->_enableEdgeMark) { // Clear the polygon ID buffer @@ -4755,7 +4891,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); } else { @@ -4778,6 +4914,13 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf if (this->isShaderSupported) { + if (this->_emulateDepthLEqualPolygonFacing) + { + glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + } + if (this->_enableEdgeMark) { // Clear the polygon ID buffer @@ -4800,7 +4943,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); } else { @@ -4835,6 +4978,13 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const FragmentColor &clearCol glClearStencil(clearAttributes.opaquePolyID); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + if (this->_emulateDepthLEqualPolygonFacing) + { + glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + } + if (this->_enableEdgeMark) { glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); // texGPolyID @@ -4849,7 +4999,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const FragmentColor &clearCol glClear(GL_COLOR_BUFFER_BIT); } - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); this->_needsZeroDstAlphaPass = (clearColor6665.a == 0); } else @@ -5444,7 +5594,9 @@ Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h) this->DestroyEdgeMarkProgram(); this->DestroyFramebufferOutput6665Programs(); this->DestroyFramebufferOutput8888Programs(); + this->DestroyGeometryPrograms(); + this->CreateGeometryPrograms(); this->CreateEdgeMarkProgram(EdgeMarkVtxShader_100, EdgeMarkFragShader_100); this->CreateFramebufferOutput6665Program(0, FramebufferOutputVtxShader_100, FramebufferOutputRGBA6665FragShader_100); this->CreateFramebufferOutput6665Program(1, FramebufferOutputVtxShader_100, FramebufferOutputRGBA6665FragShader_100); @@ -5605,25 +5757,14 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine) this->_geometryProgramFlags.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0; this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0; this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0; - this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0; - this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0; this->_geometryProgramFlags.ToonShadingMode = (engine.renderState.shading) ? 1 : 0; this->_geometryProgramFlags.NeedsDepthEqualsTest = (this->_renderNeedsDepthEqualsTest) ? 1 : 0; + this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0; + this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0; + this->_geometryProgramFlags.OpaqueDrawMode = 1; - glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); - glUniform1f(OGLRef.uniformStateAlphaTestRef[this->_geometryProgramFlags.value], divide5bitBy31_LUT[engine.renderState.alphaTestRef]); - glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); - glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE); - - if (this->isFBOSupported) - { - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); - } - else - { - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - } - + this->_currentAlphaTestRef = engine.renderState.alphaTestRef; + this->_SetupGeometryShaders(this->_geometryProgramFlags); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index d0383b950..d92e5fed7 100755 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -420,17 +420,17 @@ union OGLGeometryFlags u8 EnableWDepth:1; u8 EnableAlphaTest:1; u8 EnableTextureSampling:1; - u8 EnableFog:1; - u8 EnableEdgeMark:1; u8 ToonShadingMode:1; u8 NeedsDepthEqualsTest:1; - u8 :1; + u8 EnableFog:1; + u8 EnableEdgeMark:1; + u8 OpaqueDrawMode:1; #else - u8 :1; - u8 NeedsDepthEqualsTest:1; - u8 ToonShadingMode:1; + u8 OpaqueDrawMode:1; u8 EnableEdgeMark:1; u8 EnableFog:1; + u8 NeedsDepthEqualsTest:1; + u8 ToonShadingMode:1; u8 EnableTextureSampling:1; u8 EnableAlphaTest:1; u8 EnableWDepth:1; @@ -439,21 +439,12 @@ union OGLGeometryFlags struct { - u8 :3; - u8 DrawBuffersMode:2; - u8 :3; + u8 :5; + u8 DrawBuffersMode:3; }; }; typedef OGLGeometryFlags OGLGeometryFlags; -enum OGLGeometryDrawBuffersMode -{ - OGLGeometryDrawBuffersMode_ColorOnly = 0, - OGLGeometryDrawBuffersMode_Color_Fog = 1, - OGLGeometryDrawBuffersMode_Color_EdgeMark = 2, - OGLGeometryDrawBuffersMode_Color_Fog_EdgeMark = 3 -}; - union OGLFogProgramKey { u32 key; @@ -504,8 +495,10 @@ struct OGLRenderRef GLuint texGDepthStencilID; GLuint texFinalColorID; GLuint texMSGColorID; + GLuint texMSGWorkingID; GLuint rboMSGColorID; + GLuint rboMSGWorkingID; GLuint rboMSGPolyID; GLuint rboMSGFogAttrID; GLuint rboMSGDepthStencilID; @@ -558,6 +551,7 @@ struct OGLRenderRef GLint uniformPolyEnableFog[256]; GLint uniformTexSingleBitAlpha[256]; GLint uniformTexDrawOpaque[256]; + GLint uniformDrawModeDepthEqualsTest[256]; GLint uniformPolyStateIndex[256]; GLint uniformPolyDepthOffsetMode[256]; @@ -592,7 +586,7 @@ extern GPU3DInterface gpu3Dgl; extern GPU3DInterface gpu3DglOld; extern GPU3DInterface gpu3Dgl_3_2; -extern const GLenum GeometryDrawBuffersList[4][3]; +extern const GLenum GeometryDrawBuffersList[8][4]; extern CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32]; extern CACHE_ALIGN const GLfloat divide6bitBy63_LUT[64]; extern const GLfloat PostprocessVtxBuffer[16]; @@ -704,6 +698,7 @@ protected: bool _needsZeroDstAlphaPass; bool _renderNeedsDepthEqualsTest; size_t _currentPolyIndex; + u8 _currentAlphaTestRef; OGLTextureUnitID _lastTextureDrawTarget; OGLGeometryFlags _geometryProgramFlags; std::map _fogProgramMap; @@ -772,9 +767,11 @@ protected: virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID) = 0; virtual void GetExtensionSet(std::set *oglExtensionSet) = 0; + virtual void _SetupGeometryShaders(const OGLGeometryFlags flags) = 0; virtual Render3DError EnableVertexAttributes() = 0; virtual Render3DError DisableVertexAttributes() = 0; - virtual Render3DError DownsampleFBO() = 0; + virtual void _ResolveWorkingBackFacing() = 0; + virtual void _ResolveGeometry() = 0; virtual Render3DError ReadBackPixels() = 0; virtual Render3DError DrawShadowPolygon(const GLenum polyPrimitive, const GLsizei vertIndexCount, const GLushort *indexBufferPtr, const bool performDepthEqualTest, const bool enableAlphaDepthWrite, const bool isTranslucent, const u8 opaquePolyID) = 0; @@ -847,10 +844,12 @@ protected: virtual Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID); virtual void GetExtensionSet(std::set *oglExtensionSet); + virtual void _SetupGeometryShaders(const OGLGeometryFlags flags); virtual Render3DError EnableVertexAttributes(); virtual Render3DError DisableVertexAttributes(); virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr); - virtual Render3DError DownsampleFBO(); + virtual void _ResolveWorkingBackFacing(); + virtual void _ResolveGeometry(); virtual Render3DError ReadBackPixels(); // Base rendering methods diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 090a66e10..58ee85d08 100755 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -202,9 +202,18 @@ layout (std140) uniform RenderStates\n\ \n\ uniform sampler2D texRenderObject;\n\ uniform bool texDrawOpaque;\n\ +uniform bool drawModeDepthEqualsTest;\n\ uniform bool polyDrawShadow;\n\ uniform int polyDepthOffsetMode;\n\ \n\ +#if USE_DEPTH_LEQUAL_POLYGON_FACING\n\ +#if DRAW_MODE_OPAQUE\n\ +out vec4 outBackFacing;\n\ +#else\n\ +uniform sampler2D inBackFacing;\n\ +#endif\n\ +#endif\n\ +\n\ out vec4 outFragColor;\n\ \n\ #if ENABLE_EDGE_MARK\n\ @@ -220,6 +229,9 @@ layout (depth_less) out float gl_FragDepth;\n\ void main()\n\ {\n\ outFragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\ +#if USE_DEPTH_LEQUAL_POLYGON_FACING && DRAW_MODE_OPAQUE\n\ + outBackFacing = vec4(float(!gl_FrontFacing), 0.0, 0.0, 1.0);\n\ +#endif\n\ #if ENABLE_EDGE_MARK\n\ outPolyID = vec4(0.0, 0.0, 0.0, 0.0);\n\ #endif\n\ @@ -289,6 +301,17 @@ void main()\n\ discard;\n\ }\n\ \n\ +#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\ + if (drawModeDepthEqualsTest)\n\ + {\n\ + bool isOpaqueDstBackFacing = bool( texture(inBackFacing, vec2(gl_FragCoord.x/FRAMEBUFFER_SIZE_X, gl_FragCoord.y/FRAMEBUFFER_SIZE_Y)).r );\n\ + if ( !gl_FrontFacing || !isOpaqueDstBackFacing )\n\ + {\n\ + discard;\n\ + }\n\ + }\n\ +#endif\n\ + \n\ #if ENABLE_EDGE_MARK\n\ outPolyID = vec4( float(polyID)/63.0, float(polyIsWireframe == 1), 0.0, float(outFragColor.a > 0.999) );\n\ #endif\n\ @@ -1121,18 +1144,31 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples) if (this->willUsePerSampleZeroDstPass) { glGenTextures(1, &OGLRef.texMSGColorID); + glGenTextures(1, &OGLRef.texMSGWorkingID); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID); glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, GL_TRUE); + + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGWorkingID); + glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, GL_TRUE); } else { glGenRenderbuffers(1, &OGLRef.rboMSGColorID); + glGenRenderbuffers(1, &OGLRef.rboMSGWorkingID); + glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGColorID); glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); + glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGWorkingID); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); } glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGPolyID); @@ -1149,10 +1185,12 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples) if (this->willUsePerSampleZeroDstPass) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGWorkingID, 0); } else { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboMSGColorID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_RENDERBUFFER, OGLRef.rboMSGWorkingID); } glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, OGLRef.rboMSGPolyID); @@ -1185,12 +1223,21 @@ void OpenGLRenderer_3_2::DestroyMultisampledFBO() glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID); glDeleteTextures(1, &OGLRef.texMSGColorID); + glDeleteTextures(1, &OGLRef.texMSGWorkingID); glDeleteRenderbuffers(1, &OGLRef.rboMSGColorID); + glDeleteRenderbuffers(1, &OGLRef.rboMSGWorkingID); glDeleteRenderbuffers(1, &OGLRef.rboMSGPolyID); glDeleteRenderbuffers(1, &OGLRef.rboMSGFogAttrID); glDeleteRenderbuffers(1, &OGLRef.rboMSGDepthStencilID); OGLRef.fboMSIntermediateRenderID = 0; + OGLRef.texMSGColorID = 0; + OGLRef.texMSGWorkingID = 0; + OGLRef.rboMSGColorID = 0; + OGLRef.rboMSGWorkingID = 0; + OGLRef.rboMSGPolyID = 0; + OGLRef.rboMSGFogAttrID = 0; + OGLRef.rboMSGDepthStencilID = 0; this->isMultisampledFBOSupported = false; } @@ -1219,11 +1266,15 @@ void OpenGLRenderer_3_2::ResizeMultisampledFBOs(GLsizei numSamples) { glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA, w, h, GL_TRUE); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGWorkingID); + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA, w, h, GL_TRUE); } else { glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGColorID); glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA, w, h); + glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGWorkingID); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA, w, h); } glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGPolyID); @@ -1355,24 +1406,28 @@ Render3DError OpenGLRenderer_3_2::CreateGeometryPrograms() { fragShaderHeader << "#version 150\n"; } + fragShaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n"; + fragShaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n"; fragShaderHeader << "\n"; fragShaderHeader << "#define IS_CONSERVATIVE_DEPTH_SUPPORTED " << ((this->isConservativeDepthSupported || this->isConservativeDepthAMDSupported) ? 1 : 0) << "\n"; fragShaderHeader << "#define DEPTH_EQUALS_TEST_TOLERANCE " << DEPTH_EQUALS_TEST_TOLERANCE << ".0\n"; fragShaderHeader << "\n"; - for (size_t flagsValue = 0; flagsValue < 128; flagsValue++, programFlags.value++) + for (size_t flagsValue = 0; flagsValue < 256; flagsValue++, programFlags.value++) { std::stringstream shaderFlags; shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n"; shaderFlags << "#define USE_NDS_DEPTH_CALCULATION " << ((this->_emulateNDSDepthCalculation) ? 1 : 0) << "\n"; + shaderFlags << "#define USE_DEPTH_LEQUAL_POLYGON_FACING " << ((this->_emulateDepthLEqualPolygonFacing) ? 1 : 0) << "\n"; shaderFlags << "\n"; shaderFlags << "#define ENABLE_W_DEPTH " << ((programFlags.EnableWDepth) ? 1 : 0) << "\n"; shaderFlags << "#define ENABLE_ALPHA_TEST " << ((programFlags.EnableAlphaTest) ? "true\n" : "false\n"); shaderFlags << "#define ENABLE_TEXTURE_SAMPLING " << ((programFlags.EnableTextureSampling) ? "true\n" : "false\n"); - shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog) ? 1 : 0) << "\n"; - shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark) ? 1 : 0) << "\n"; shaderFlags << "#define TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n"; shaderFlags << "#define NEEDS_DEPTH_EQUALS_TEST " << ((programFlags.NeedsDepthEqualsTest) ? 1 : 0) << "\n"; + shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog) ? 1 : 0) << "\n"; + shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark) ? 1 : 0) << "\n"; + shaderFlags << "#define DRAW_MODE_OPAQUE " << ((programFlags.OpaqueDrawMode) ? 1 : 0) << "\n"; shaderFlags << "\n"; std::string fragShaderCode = fragShaderHeader.str() + shaderFlags.str() + std::string(GeometryFragShader_150); @@ -1395,23 +1450,14 @@ Render3DError OpenGLRenderer_3_2::CreateGeometryPrograms() glBindAttribLocation(OGLRef.programGeometryID[flagsValue], OGLVertexAttributeID_Color, "inColor"); glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 0, "outFragColor"); - switch (programFlags.DrawBuffersMode) + if (programFlags.EnableEdgeMark) { - case OGLGeometryDrawBuffersMode_Color_Fog: - glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outFogAttributes"); - break; - - case OGLGeometryDrawBuffersMode_Color_EdgeMark: - glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outPolyID"); - break; - - case OGLGeometryDrawBuffersMode_Color_Fog_EdgeMark: - glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outPolyID"); - glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 2, "outFogAttributes"); - break; - - default: - break; + glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 2, "outPolyID"); + } + + if (programFlags.EnableFog) + { + glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 3, "outFogAttributes"); } glLinkProgram(OGLRef.programGeometryID[flagsValue]); @@ -1439,19 +1485,33 @@ Render3DError OpenGLRenderer_3_2::CreateGeometryPrograms() if (OGLRef.uboPolyStatesID != 0) { - const GLuint uniformBlockPolyStates = glGetUniformBlockIndex(OGLRef.programGeometryID[flagsValue], "PolyStates"); + const GLuint uniformBlockPolyStates = glGetUniformBlockIndex(OGLRef.programGeometryID[flagsValue], "PolyStates"); glUniformBlockBinding(OGLRef.programGeometryID[flagsValue], uniformBlockPolyStates, OGLBindingPointID_PolyStates); } else { - const GLint uniformTexBufferPolyStates = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "PolyStates"); + const GLint uniformTexBufferPolyStates = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "PolyStates"); glUniform1i(uniformTexBufferPolyStates, OGLTextureUnitID_PolyStates); } - OGLRef.uniformTexDrawOpaque[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texDrawOpaque"); - OGLRef.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow"); - OGLRef.uniformPolyStateIndex[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyIndex"); - OGLRef.uniformPolyDepthOffsetMode[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffsetMode"); + if (this->_emulateDepthLEqualPolygonFacing) + { + if (programFlags.OpaqueDrawMode) + { + glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outBackFacing"); + } + else + { + const GLint uniformTexBackfacing = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "inBackFacing"); + glUniform1i(uniformTexBackfacing, OGLTextureUnitID_FinalColor); + } + } + + OGLRef.uniformTexDrawOpaque[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texDrawOpaque"); + OGLRef.uniformDrawModeDepthEqualsTest[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "drawModeDepthEqualsTest"); + OGLRef.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow"); + OGLRef.uniformPolyStateIndex[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyIndex"); + OGLRef.uniformPolyDepthOffsetMode[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffsetMode"); } return error; @@ -1476,24 +1536,7 @@ void OpenGLRenderer_3_2::DestroyGeometryPrograms() OGLRef.uboPolyStatesID = 0; OGLRef.tboPolyStatesID = 0; - for (size_t flagsValue = 0; flagsValue < 128; flagsValue++) - { - if (OGLRef.programGeometryID[flagsValue] == 0) - { - continue; - } - - glDetachShader(OGLRef.programGeometryID[flagsValue], OGLRef.vertexGeometryShaderID); - glDetachShader(OGLRef.programGeometryID[flagsValue], OGLRef.fragmentGeometryShaderID[flagsValue]); - glDeleteProgram(OGLRef.programGeometryID[flagsValue]); - glDeleteShader(OGLRef.fragmentGeometryShaderID[flagsValue]); - - OGLRef.programGeometryID[flagsValue] = 0; - OGLRef.fragmentGeometryShaderID[flagsValue] = 0; - } - - glDeleteShader(OGLRef.vertexGeometryShaderID); - OGLRef.vertexGeometryShaderID = 0; + OpenGLRenderer_2_1::DestroyGeometryPrograms(); } Render3DError OpenGLRenderer_3_2::CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString) @@ -1935,6 +1978,18 @@ void OpenGLRenderer_3_2::GetExtensionSet(std::set *oglExtensionSet) } } +void OpenGLRenderer_3_2::_SetupGeometryShaders(const OGLGeometryFlags flags) +{ + const OGLRenderRef &OGLRef = *this->ref; + + glUseProgram(OGLRef.programGeometryID[flags.value]); + glUniform1i(OGLRef.uniformTexDrawOpaque[flags.value], GL_FALSE); + glUniform1i(OGLRef.uniformDrawModeDepthEqualsTest[flags.value], GL_FALSE); + glUniform1i(OGLRef.uniformPolyDrawShadow[flags.value], GL_FALSE); + + glDrawBuffers(4, GeometryDrawBuffersList[flags.DrawBuffersMode]); +} + Render3DError OpenGLRenderer_3_2::EnableVertexAttributes() { glBindVertexArray(this->ref->vaoGeometryStatesID); @@ -1967,7 +2022,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); glDrawBuffer(GL_COLOR_ATTACHMENT0); glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); } @@ -1993,17 +2048,14 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags; this->_geometryProgramFlags.EnableEdgeMark = 0; this->_geometryProgramFlags.EnableFog = 0; - - glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); - glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); - glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE); + this->_SetupGeometryShaders(this->_geometryProgramFlags); + glDrawBuffer(GL_COLOR_ATTACHMENT0); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); this->EnableVertexAttributes(); // Draw the alpha polys, touching fully transparent pixels only once. - glDrawBuffer(GL_COLOR_ATTACHMENT0); glEnable(GL_DEPTH_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); @@ -2012,8 +2064,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con // Restore OpenGL states back to normal. this->_geometryProgramFlags = oldGProgramFlags; - glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + this->_SetupGeometryShaders(this->_geometryProgramFlags); glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); @@ -2031,42 +2082,64 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_3_2::DownsampleFBO() +void OpenGLRenderer_3_2::_ResolveWorkingBackFacing() { OGLRenderRef &OGLRef = *this->ref; - if (this->isMultisampledFBOSupported && (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID)) + if (!this->_emulateDepthLEqualPolygonFacing || !this->isMultisampledFBOSupported || (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID)) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); - - if (this->_enableEdgeMark) - { - // Blit the polygon ID buffer - glReadBuffer(GL_COLOR_ATTACHMENT1); - glDrawBuffer(GL_COLOR_ATTACHMENT1); - glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - - if (this->_enableFog) - { - // Blit the fog buffer - glReadBuffer(GL_COLOR_ATTACHMENT2); - glDrawBuffer(GL_COLOR_ATTACHMENT2); - glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - - // Blit the color and depth buffers - glReadBuffer(GL_COLOR_ATTACHMENT0); - glDrawBuffer(GL_COLOR_ATTACHMENT0); - glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - - // Reset framebuffer targets - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + return; } - return OGLERROR_NOERR; + glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); + + glReadBuffer(GL_COLOR_ATTACHMENT3); + glDrawBuffer(GL_COLOR_ATTACHMENT3); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + // Reset framebuffer targets + glReadBuffer(GL_COLOR_ATTACHMENT0); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); +} + +void OpenGLRenderer_3_2::_ResolveGeometry() +{ + OGLRenderRef &OGLRef = *this->ref; + + if (!this->isMultisampledFBOSupported || (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID)) + { + return; + } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); + + if (this->_enableEdgeMark) + { + // Blit the polygon ID buffer + glReadBuffer(GL_COLOR_ATTACHMENT1); + glDrawBuffer(GL_COLOR_ATTACHMENT1); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + + if (this->_enableFog) + { + // Blit the fog buffer + glReadBuffer(GL_COLOR_ATTACHMENT2); + glDrawBuffer(GL_COLOR_ATTACHMENT2); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + + // Blit the color and depth buffers + glReadBuffer(GL_COLOR_ATTACHMENT0); + glDrawBuffer(GL_COLOR_ATTACHMENT0); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + + // Reset framebuffer targets + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); } Render3DError OpenGLRenderer_3_2::ReadBackPixels() @@ -2331,16 +2404,14 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine) this->_geometryProgramFlags.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0; this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0; this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 1 : 0; - this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0; - this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0; this->_geometryProgramFlags.ToonShadingMode = (engine.renderState.shading) ? 1 : 0; this->_geometryProgramFlags.NeedsDepthEqualsTest = (this->_renderNeedsDepthEqualsTest) ? 1 : 0; + this->_geometryProgramFlags.EnableFog = (this->_enableFog) ? 1 : 0; + this->_geometryProgramFlags.EnableEdgeMark = (this->_enableEdgeMark) ? 1 : 0; + this->_geometryProgramFlags.OpaqueDrawMode = 1; - glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); - glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); - glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE); - - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + this->_currentAlphaTestRef = engine.renderState.alphaTestRef; + this->_SetupGeometryShaders(this->_geometryProgramFlags); glReadBuffer(GL_COLOR_ATTACHMENT0); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -2469,13 +2540,19 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboClearImageID); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + + if (this->_emulateDepthLEqualPolygonFacing) + { + const GLfloat oglBackfacing[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + glClearBufferfv(GL_COLOR, 1, oglBackfacing); + } if (this->_enableEdgeMark) { // Clear the polygon ID buffer const GLfloat oglPolyID[4] = {(GLfloat)opaquePolyID/63.0f, 0.0f, 0.0f, 1.0f}; - glClearBufferfv(GL_COLOR, 1, oglPolyID); + glClearBufferfv(GL_COLOR, 2, oglPolyID); } if (this->_enableFog) @@ -2498,13 +2575,19 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf { glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboRenderID); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.selectedRenderingFBO); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + + if (this->_emulateDepthLEqualPolygonFacing) + { + const GLfloat oglBackfacing[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + glClearBufferfv(GL_COLOR, 1, oglBackfacing); + } if (this->_enableEdgeMark) { // Clear the polygon ID buffer const GLfloat oglPolyID[4] = {(GLfloat)opaquePolyID/63.0f, 0.0f, 0.0f, 1.0f}; - glClearBufferfv(GL_COLOR, 1, oglPolyID); + glClearBufferfv(GL_COLOR, 2, oglPolyID); } if (this->_enableFog) @@ -2531,30 +2614,28 @@ Render3DError OpenGLRenderer_3_2::ClearUsingValues(const FragmentColor &clearCol OGLRenderRef &OGLRef = *this->ref; OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); - glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); const GLfloat oglColor[4] = {divide6bitBy63_LUT[clearColor6665.r], divide6bitBy63_LUT[clearColor6665.g], divide6bitBy63_LUT[clearColor6665.b], divide5bitBy31_LUT[clearColor6665.a]}; glClearBufferfv(GL_COLOR, 0, oglColor); // texGColorID glClearBufferfi(GL_DEPTH_STENCIL, 0, (GLfloat)clearAttributes.depth / (GLfloat)0x00FFFFFF, clearAttributes.opaquePolyID); + if (this->_emulateDepthLEqualPolygonFacing) + { + const GLfloat oglBackfacing[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + glClearBufferfv(GL_COLOR, 1, oglBackfacing); + } + if (this->_enableEdgeMark) { const GLfloat oglPolyID[4] = {(GLfloat)clearAttributes.opaquePolyID/63.0f, 0.0f, 0.0f, 1.0f}; - glClearBufferfv(GL_COLOR, 1, oglPolyID); // texGPolyID + glClearBufferfv(GL_COLOR, 2, oglPolyID); // texGPolyID } if (this->_enableFog) { const GLfloat oglFogAttr[4] = {(GLfloat)clearAttributes.isFogged, 0.0f, 0.0f, 1.0f}; - - if (GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode][1] == GL_COLOR_ATTACHMENT2) - { - glClearBufferfv(GL_COLOR, 1, oglFogAttr); - } - else if (GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode][2] == GL_COLOR_ATTACHMENT2) - { - glClearBufferfv(GL_COLOR, 2, oglFogAttr); - } + glClearBufferfv(GL_COLOR, 3, oglFogAttr); } this->_needsZeroDstAlphaPass = (clearColor6665.a == 0); @@ -2760,7 +2841,9 @@ Render3DError OpenGLRenderer_3_2::SetFramebufferSize(size_t w, size_t h) this->DestroyEdgeMarkProgram(); this->DestroyFramebufferOutput6665Programs(); this->DestroyMSGeometryZeroDstAlphaProgram(); + this->DestroyGeometryPrograms(); + this->CreateGeometryPrograms(); this->CreateEdgeMarkProgram(EdgeMarkVtxShader_150, EdgeMarkFragShader_150); this->CreateFramebufferOutput6665Program(0, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150); this->CreateFramebufferOutput6665Program(1, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150); diff --git a/desmume/src/OGLRender_3_2.h b/desmume/src/OGLRender_3_2.h index bbb2d833c..51cd79765 100644 --- a/desmume/src/OGLRender_3_2.h +++ b/desmume/src/OGLRender_3_2.h @@ -90,10 +90,12 @@ protected: virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString); virtual void GetExtensionSet(std::set *oglExtensionSet); + virtual void _SetupGeometryShaders(const OGLGeometryFlags flags); virtual Render3DError EnableVertexAttributes(); virtual Render3DError DisableVertexAttributes(); virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr); - virtual Render3DError DownsampleFBO(); + virtual void _ResolveWorkingBackFacing(); + virtual void _ResolveGeometry(); virtual Render3DError ReadBackPixels(); virtual Render3DError BeginRender(const GFX3D &engine); virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);