OpenGL Renderer: Better emulate the special NDS rendering quirk for drawing front-facing fragments on top of back-facing opaque fragments. Completely fixes the Customize screens in Sands of Destruction. (Related to commit 8944328.)

- Specifically, translucent polygons now properly render on top of the back-facing opaque fragments from the opaque polygon rendering pass. Do note that emulating this special NDS rendering quirk is still not complete, as it does not account for drawing any translucent polygons on top of the opaque fragments of back-facing partially-translucent alpha-textured polygons. However, I have not seen any games that actually go so deep into such an edge case. If there is such a game, then this issue will need to be revisited.
- Now that this special rendering quirk is more accurate, this does cost some performance. However, since this rendering quirk is controlled by the "Enable Depth L-Equal Polygon Facing" option, which is OFF by default, this performance loss is deemed acceptable in favor of the increased accuracy.
This commit is contained in:
rogerman 2019-01-29 01:20:13 -08:00
parent 1c937adb9e
commit e4ec1d634a
4 changed files with 473 additions and 248 deletions

View File

@ -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, 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}; 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f};
const GLenum GeometryDrawBuffersList[4][3] = { const GLenum GeometryDrawBuffersList[8][4] = {
{ GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_NONE }, { GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_NONE, GL_NONE },
{ GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_NONE }, { GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_NONE, GL_COLOR_ATTACHMENT2_EXT },
{ GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_NONE }, { GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_COLOR_ATTACHMENT1_EXT, GL_NONE },
{ GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT } { 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() bool BEGINGL()
@ -318,9 +322,14 @@ uniform bool polyEnableFog;\n\
uniform bool texDrawOpaque;\n\ uniform bool texDrawOpaque;\n\
uniform bool texSingleBitAlpha;\n\ uniform bool texSingleBitAlpha;\n\
\n\ \n\
uniform bool drawModeDepthEqualsTest;\n\
uniform bool polyDrawShadow;\n\ uniform bool polyDrawShadow;\n\
uniform int polyDepthOffsetMode;\n\ uniform int polyDepthOffsetMode;\n\
\n\ \n\
#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\
uniform sampler2D inBackFacing;\n\
#endif\n\
\n\
void main()\n\ void main()\n\
{\n\ {\n\
vec4 newFragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\ vec4 newFragColor = vec4(0.0, 0.0, 0.0, 0.0);\n\
@ -386,6 +395,17 @@ void main()\n\
discard;\n\ discard;\n\
}\n\ }\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\ #if ENABLE_EDGE_MARK\n\
newPolyID = vec4( float(polyID)/63.0, float(polyIsWireframe), 0.0, float(newFragColor.a > 0.999) );\n\ newPolyID = vec4( float(polyID)/63.0, float(polyIsWireframe), 0.0, float(newFragColor.a > 0.999) );\n\
#endif\n\ #endif\n\
@ -396,13 +416,14 @@ void main()\n\
\n\ \n\
gl_FragData[0] = newFragColor;\n\ gl_FragData[0] = newFragColor;\n\
\n\ \n\
#if ENABLE_EDGE_MARK && ENABLE_FOG\n\ #if USE_DEPTH_LEQUAL_POLYGON_FACING && DRAW_MODE_OPAQUE\n\
gl_FragData[1] = newPolyID;\n\ gl_FragData[1] = vec4(float(!gl_FrontFacing), 0.0, 0.0, 1.0);\n\
gl_FragData[2] = newFogAttributes;\n\ #endif\n\
#elif ENABLE_EDGE_MARK\n\ #if ENABLE_EDGE_MARK\n\
gl_FragData[1] = newPolyID;\n\ gl_FragData[2] = newPolyID;\n\
#elif ENABLE_FOG\n\ #endif\n\
gl_FragData[1] = newFogAttributes;\n\ #if ENABLE_FOG\n\
gl_FragData[3] = newFogAttributes;\n\
#endif\n\ #endif\n\
#if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\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\ // 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; _needsZeroDstAlphaPass = true;
_renderNeedsDepthEqualsTest = false; _renderNeedsDepthEqualsTest = false;
_currentPolyIndex = 0; _currentPolyIndex = 0;
_currentAlphaTestRef = 0;
_lastTextureDrawTarget = OGLTextureUnitID_GColor; _lastTextureDrawTarget = OGLTextureUnitID_GColor;
_geometryProgramFlags.value = 0; _geometryProgramFlags.value = 0;
_fogProgramMap.clear(); _fogProgramMap.clear();
@ -2133,6 +2155,15 @@ Render3DError OpenGLRenderer::DrawAlphaTexturePolygon(const GLenum polyPrimitive
else if (DRAWMODE != OGLPolyDrawMode_DrawOpaquePolys) else if (DRAWMODE != OGLPolyDrawMode_DrawOpaquePolys)
{ {
// Draw the translucent fragments. // 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); glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr);
// Draw the opaque fragments if they might exist. // 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); 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); glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr);
glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); 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); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(((DRAWMODE == OGLPolyDrawMode_DrawOpaquePolys) || enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE); 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); if (isPolyFrontFacing)
glStencilFunc(GL_EQUAL, 0x40 | opaquePolyID, 0x40); {
glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); glDepthFunc(GL_EQUAL);
glStencilFunc(GL_EQUAL, 0x40 | opaquePolyID, 0x40);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr);
glDepthMask(GL_FALSE);
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glStencilMask(0x40); glDepthMask(GL_FALSE);
glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
glStencilMask(0x40);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LESS); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_ALWAYS, opaquePolyID, 0x3F); glDepthMask(GL_TRUE);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glDepthFunc(GL_LESS);
glStencilMask(0xFF); glStencilFunc(GL_ALWAYS, opaquePolyID, 0x3F);
glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); 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 else
{ {
glStencilFunc(GL_ALWAYS, 0x40 | opaquePolyID, 0x40);
glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr);
glStencilFunc(GL_ALWAYS, opaquePolyID, 0x3F);
} }
} }
else 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); 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 didSelectedMultisampleSizeChange = (this->_selectedMultisampleSize != CommonSettings.GFX3D_Renderer_MultisampleSize);
const bool didEmulateNDSDepthCalculationChange = (this->_emulateNDSDepthCalculation != CommonSettings.OpenGL_Emulation_NDSDepthCalculation); const bool didEmulateNDSDepthCalculationChange = (this->_emulateNDSDepthCalculation != CommonSettings.OpenGL_Emulation_NDSDepthCalculation);
const bool didEnableTextureSmoothingChange = (this->_enableTextureSmoothing != CommonSettings.GFX3D_Renderer_TextureSmoothing); 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->_emulateShadowPolygon = CommonSettings.OpenGL_Emulation_ShadowPolygon;
this->_emulateSpecialZeroAlphaBlending = CommonSettings.OpenGL_Emulation_SpecialZeroAlphaBlending; this->_emulateSpecialZeroAlphaBlending = CommonSettings.OpenGL_Emulation_SpecialZeroAlphaBlending;
this->_emulateNDSDepthCalculation = CommonSettings.OpenGL_Emulation_NDSDepthCalculation; 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->_selectedMultisampleSize = CommonSettings.GFX3D_Renderer_MultisampleSize;
this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported); this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported);
@ -2347,7 +2404,8 @@ Render3DError OpenGLRenderer::ApplyRenderingSettings(const GFX3D_State &renderSt
if (didSelectedMultisampleSizeChange || if (didSelectedMultisampleSizeChange ||
didEmulateNDSDepthCalculationChange || didEmulateNDSDepthCalculationChange ||
didEnableTextureSmoothingChange ) didEnableTextureSmoothingChange ||
didEmulateDepthLEqualPolygonFacingChange)
{ {
if (!BEGINGL()) if (!BEGINGL())
{ {
@ -2362,7 +2420,8 @@ Render3DError OpenGLRenderer::ApplyRenderingSettings(const GFX3D_State &renderSt
if ( this->isShaderSupported && if ( this->isShaderSupported &&
(didEmulateNDSDepthCalculationChange || (didEmulateNDSDepthCalculationChange ||
didEnableTextureSmoothingChange) ) didEnableTextureSmoothingChange ||
didEmulateDepthLEqualPolygonFacingChange) )
{ {
glUseProgram(0); glUseProgram(0);
this->DestroyGeometryPrograms(); this->DestroyGeometryPrograms();
@ -2955,12 +3014,15 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO(GLsizei numSamples)
// Set up FBO render targets // Set up FBO render targets
glGenRenderbuffersEXT(1, &OGLRef.rboMSGColorID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGColorID);
glGenRenderbuffersEXT(1, &OGLRef.rboMSGWorkingID);
glGenRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGPolyID);
glGenRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID);
glGenRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); 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); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); 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_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_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_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_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_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); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID);
glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGColorID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGColorID);
glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGWorkingID);
glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGPolyID);
glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID);
glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID);
OGLRef.fboMSIntermediateRenderID = 0; OGLRef.fboMSIntermediateRenderID = 0;
OGLRef.rboMSGColorID = 0;
OGLRef.rboMSGWorkingID = 0;
OGLRef.rboMSGPolyID = 0;
OGLRef.rboMSGFogAttrID = 0;
OGLRef.rboMSGDepthStencilID = 0;
this->isMultisampledFBOSupported = false; this->isMultisampledFBOSupported = false;
} }
@ -3037,6 +3106,8 @@ void OpenGLRenderer_1_2::ResizeMultisampledFBOs(GLsizei numSamples)
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, w, h); 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); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID);
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, w, h); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, numSamples, GL_RGBA, w, h);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID);
@ -3054,22 +3125,27 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms()
programFlags.value = 0; programFlags.value = 0;
std::stringstream fragShaderHeader; 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 << "#define DEPTH_EQUALS_TEST_TOLERANCE " << DEPTH_EQUALS_TEST_TOLERANCE << ".0 \n";
fragShaderHeader << "\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; std::stringstream shaderFlags;
shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n"; shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n";
shaderFlags << "#define USE_NDS_DEPTH_CALCULATION " << ((this->_emulateNDSDepthCalculation) ? 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 << "\n";
shaderFlags << "#define ENABLE_W_DEPTH " << ((programFlags.EnableWDepth) ? 1 : 0) << "\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_ALPHA_TEST " << ((programFlags.EnableAlphaTest) ? "true\n" : "false\n");
shaderFlags << "#define ENABLE_TEXTURE_SAMPLING " << ((programFlags.EnableTextureSampling) ? "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 TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n";
shaderFlags << "#define NEEDS_DEPTH_EQUALS_TEST " << ((programFlags.NeedsDepthEqualsTest) ? 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"; shaderFlags << "\n";
std::string fragShaderCode = fragShaderHeader.str() + shaderFlags.str() + std::string(GeometryFragShader_100); std::string fragShaderCode = fragShaderHeader.str() + shaderFlags.str() + std::string(GeometryFragShader_100);
@ -3108,6 +3184,12 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms()
glUniform1i(uniformTexRenderObject, 0); glUniform1i(uniformTexRenderObject, 0);
glUniform1i(uniformTexToonTable, OGLTextureUnitID_ToonTable); 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.uniformStateAlphaTestRef[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "stateAlphaTestRef");
OGLRef.uniformPolyTexScale[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyTexScale"); 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.uniformTexSingleBitAlpha[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texSingleBitAlpha");
OGLRef.uniformTexDrawOpaque[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texDrawOpaque"); 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.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow");
OGLRef.uniformPolyDepthOffsetMode[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffsetMode"); OGLRef.uniformPolyDepthOffsetMode[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffsetMode");
} }
@ -3140,7 +3223,7 @@ void OpenGLRenderer_1_2::DestroyGeometryPrograms()
OGLRenderRef &OGLRef = *this->ref; 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) if (OGLRef.programGeometryID[flagsValue] == 0)
{ {
@ -3896,6 +3979,33 @@ void OpenGLRenderer_1_2::GetExtensionSet(std::set<std::string> *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() Render3DError OpenGLRenderer_1_2::EnableVertexAttributes()
{ {
OGLRenderRef &OGLRef = *this->ref; OGLRenderRef &OGLRef = *this->ref;
@ -3989,7 +4099,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
glDrawBuffer(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_NEAREST); 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); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO);
} }
@ -4036,17 +4146,14 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con
OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags; OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags;
this->_geometryProgramFlags.EnableEdgeMark = 0; this->_geometryProgramFlags.EnableEdgeMark = 0;
this->_geometryProgramFlags.EnableFog = 0; this->_geometryProgramFlags.EnableFog = 0;
this->_SetupGeometryShaders(this->_geometryProgramFlags);
glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE);
glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
this->EnableVertexAttributes(); this->EnableVertexAttributes();
// Draw the alpha polys, touching fully transparent pixels only once. // Draw the alpha polys, touching fully transparent pixels only once.
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
@ -4055,8 +4162,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con
// Restore OpenGL states back to normal. // Restore OpenGL states back to normal.
this->_geometryProgramFlags = oldGProgramFlags; this->_geometryProgramFlags = oldGProgramFlags;
glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); this->_SetupGeometryShaders(this->_geometryProgramFlags);
glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]);
glClear(GL_STENCIL_BUFFER_BIT); glClear(GL_STENCIL_BUFFER_BIT);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
@ -4074,54 +4180,76 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con
return OGLERROR_NOERR; return OGLERROR_NOERR;
} }
Render3DError OpenGLRenderer_1_2::DownsampleFBO() void OpenGLRenderer_1_2::_ResolveWorkingBackFacing()
{ {
OGLRenderRef &OGLRef = *this->ref; 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); return;
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 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() 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.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0;
this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0; this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0;
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 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.ToonShadingMode = (engine.renderState.shading) ? 1 : 0;
this->_geometryProgramFlags.NeedsDepthEqualsTest = (this->_renderNeedsDepthEqualsTest) ? 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]); this->_currentAlphaTestRef = engine.renderState.alphaTestRef;
glUniform1i(OGLRef.uniformStateClearPolyID, this->_clearAttributes.opaquePolyID); this->_SetupGeometryShaders(this->_geometryProgramFlags);
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);
} }
else else
{ {
@ -4390,11 +4515,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
glLoadIdentity(); glLoadIdentity();
} }
if (this->isFBOSupported && this->isShaderSupported) if (!this->isFBOSupported || !this->isShaderSupported)
{
glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]);
}
else
{ {
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
} }
@ -4442,6 +4563,8 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
if (this->_clippedPolyOpaqueCount < this->_clippedPolyCount) if (this->_clippedPolyOpaqueCount < this->_clippedPolyCount)
{ {
this->_geometryProgramFlags.OpaqueDrawMode = 0;
if (this->_needsZeroDstAlphaPass && this->_emulateSpecialZeroAlphaBlending) if (this->_needsZeroDstAlphaPass && this->_emulateSpecialZeroAlphaBlending)
{ {
if (this->_clippedPolyOpaqueCount == 0) if (this->_clippedPolyOpaqueCount == 0)
@ -4466,12 +4589,18 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
glClearStencil(0); glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT); glClear(GL_STENCIL_BUFFER_BIT);
glStencilMask(0xFF); glStencilMask(0xFF);
this->_SetupGeometryShaders(this->_geometryProgramFlags);
} }
if (this->_clippedPolyOpaqueCount == 0) if (this->_clippedPolyOpaqueCount == 0)
{ {
this->SetupPolygon(firstPoly, true, true); this->SetupPolygon(firstPoly, true, true);
} }
else
{
this->_ResolveWorkingBackFacing();
}
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(polyList, indexList, this->_clippedPolyOpaqueCount, this->_clippedPolyCount - 1, indexOffset, lastPolyAttr); this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(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->DisableVertexAttributes();
} }
this->DownsampleFBO(); this->_ResolveGeometry();
this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; this->_lastTextureDrawTarget = OGLTextureUnitID_GColor;
@ -4733,6 +4862,13 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf
if (this->isShaderSupported) 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) if (this->_enableEdgeMark)
{ {
// Clear the polygon ID buffer // 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); 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); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]);
} }
else else
{ {
@ -4778,6 +4914,13 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf
if (this->isShaderSupported) 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) if (this->_enableEdgeMark)
{ {
// Clear the polygon ID buffer // 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); 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); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO);
glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]);
} }
else else
{ {
@ -4835,6 +4978,13 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const FragmentColor &clearCol
glClearStencil(clearAttributes.opaquePolyID); glClearStencil(clearAttributes.opaquePolyID);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 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) if (this->_enableEdgeMark)
{ {
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); // texGPolyID glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); // texGPolyID
@ -4849,7 +4999,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const FragmentColor &clearCol
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
} }
glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); glDrawBuffers(4, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]);
this->_needsZeroDstAlphaPass = (clearColor6665.a == 0); this->_needsZeroDstAlphaPass = (clearColor6665.a == 0);
} }
else else
@ -5444,7 +5594,9 @@ Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h)
this->DestroyEdgeMarkProgram(); this->DestroyEdgeMarkProgram();
this->DestroyFramebufferOutput6665Programs(); this->DestroyFramebufferOutput6665Programs();
this->DestroyFramebufferOutput8888Programs(); this->DestroyFramebufferOutput8888Programs();
this->DestroyGeometryPrograms();
this->CreateGeometryPrograms();
this->CreateEdgeMarkProgram(EdgeMarkVtxShader_100, EdgeMarkFragShader_100); this->CreateEdgeMarkProgram(EdgeMarkVtxShader_100, EdgeMarkFragShader_100);
this->CreateFramebufferOutput6665Program(0, FramebufferOutputVtxShader_100, FramebufferOutputRGBA6665FragShader_100); this->CreateFramebufferOutput6665Program(0, FramebufferOutputVtxShader_100, FramebufferOutputRGBA6665FragShader_100);
this->CreateFramebufferOutput6665Program(1, 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.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0;
this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0; this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0;
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 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.ToonShadingMode = (engine.renderState.shading) ? 1 : 0;
this->_geometryProgramFlags.NeedsDepthEqualsTest = (this->_renderNeedsDepthEqualsTest) ? 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]); this->_currentAlphaTestRef = engine.renderState.alphaTestRef;
glUniform1f(OGLRef.uniformStateAlphaTestRef[this->_geometryProgramFlags.value], divide5bitBy31_LUT[engine.renderState.alphaTestRef]); this->_SetupGeometryShaders(this->_geometryProgramFlags);
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);
}
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

View File

@ -420,17 +420,17 @@ union OGLGeometryFlags
u8 EnableWDepth:1; u8 EnableWDepth:1;
u8 EnableAlphaTest:1; u8 EnableAlphaTest:1;
u8 EnableTextureSampling:1; u8 EnableTextureSampling:1;
u8 EnableFog:1;
u8 EnableEdgeMark:1;
u8 ToonShadingMode:1; u8 ToonShadingMode:1;
u8 NeedsDepthEqualsTest:1; u8 NeedsDepthEqualsTest:1;
u8 :1; u8 EnableFog:1;
u8 EnableEdgeMark:1;
u8 OpaqueDrawMode:1;
#else #else
u8 :1; u8 OpaqueDrawMode:1;
u8 NeedsDepthEqualsTest:1;
u8 ToonShadingMode:1;
u8 EnableEdgeMark:1; u8 EnableEdgeMark:1;
u8 EnableFog:1; u8 EnableFog:1;
u8 NeedsDepthEqualsTest:1;
u8 ToonShadingMode:1;
u8 EnableTextureSampling:1; u8 EnableTextureSampling:1;
u8 EnableAlphaTest:1; u8 EnableAlphaTest:1;
u8 EnableWDepth:1; u8 EnableWDepth:1;
@ -439,21 +439,12 @@ union OGLGeometryFlags
struct struct
{ {
u8 :3; u8 :5;
u8 DrawBuffersMode:2; u8 DrawBuffersMode:3;
u8 :3;
}; };
}; };
typedef OGLGeometryFlags OGLGeometryFlags; typedef OGLGeometryFlags OGLGeometryFlags;
enum OGLGeometryDrawBuffersMode
{
OGLGeometryDrawBuffersMode_ColorOnly = 0,
OGLGeometryDrawBuffersMode_Color_Fog = 1,
OGLGeometryDrawBuffersMode_Color_EdgeMark = 2,
OGLGeometryDrawBuffersMode_Color_Fog_EdgeMark = 3
};
union OGLFogProgramKey union OGLFogProgramKey
{ {
u32 key; u32 key;
@ -504,8 +495,10 @@ struct OGLRenderRef
GLuint texGDepthStencilID; GLuint texGDepthStencilID;
GLuint texFinalColorID; GLuint texFinalColorID;
GLuint texMSGColorID; GLuint texMSGColorID;
GLuint texMSGWorkingID;
GLuint rboMSGColorID; GLuint rboMSGColorID;
GLuint rboMSGWorkingID;
GLuint rboMSGPolyID; GLuint rboMSGPolyID;
GLuint rboMSGFogAttrID; GLuint rboMSGFogAttrID;
GLuint rboMSGDepthStencilID; GLuint rboMSGDepthStencilID;
@ -558,6 +551,7 @@ struct OGLRenderRef
GLint uniformPolyEnableFog[256]; GLint uniformPolyEnableFog[256];
GLint uniformTexSingleBitAlpha[256]; GLint uniformTexSingleBitAlpha[256];
GLint uniformTexDrawOpaque[256]; GLint uniformTexDrawOpaque[256];
GLint uniformDrawModeDepthEqualsTest[256];
GLint uniformPolyStateIndex[256]; GLint uniformPolyStateIndex[256];
GLint uniformPolyDepthOffsetMode[256]; GLint uniformPolyDepthOffsetMode[256];
@ -592,7 +586,7 @@ extern GPU3DInterface gpu3Dgl;
extern GPU3DInterface gpu3DglOld; extern GPU3DInterface gpu3DglOld;
extern GPU3DInterface gpu3Dgl_3_2; 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 divide5bitBy31_LUT[32];
extern CACHE_ALIGN const GLfloat divide6bitBy63_LUT[64]; extern CACHE_ALIGN const GLfloat divide6bitBy63_LUT[64];
extern const GLfloat PostprocessVtxBuffer[16]; extern const GLfloat PostprocessVtxBuffer[16];
@ -704,6 +698,7 @@ protected:
bool _needsZeroDstAlphaPass; bool _needsZeroDstAlphaPass;
bool _renderNeedsDepthEqualsTest; bool _renderNeedsDepthEqualsTest;
size_t _currentPolyIndex; size_t _currentPolyIndex;
u8 _currentAlphaTestRef;
OGLTextureUnitID _lastTextureDrawTarget; OGLTextureUnitID _lastTextureDrawTarget;
OGLGeometryFlags _geometryProgramFlags; OGLGeometryFlags _geometryProgramFlags;
std::map<u32, OGLFogShaderID> _fogProgramMap; std::map<u32, OGLFogShaderID> _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 Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID) = 0;
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet) = 0; virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet) = 0;
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags) = 0;
virtual Render3DError EnableVertexAttributes() = 0; virtual Render3DError EnableVertexAttributes() = 0;
virtual Render3DError DisableVertexAttributes() = 0; virtual Render3DError DisableVertexAttributes() = 0;
virtual Render3DError DownsampleFBO() = 0; virtual void _ResolveWorkingBackFacing() = 0;
virtual void _ResolveGeometry() = 0;
virtual Render3DError ReadBackPixels() = 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; 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 Render3DError UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 opaquePolyID);
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet); virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes(); virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes(); virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr); 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 ReadBackPixels();
// Base rendering methods // Base rendering methods

View File

@ -202,9 +202,18 @@ layout (std140) uniform RenderStates\n\
\n\ \n\
uniform sampler2D texRenderObject;\n\ uniform sampler2D texRenderObject;\n\
uniform bool texDrawOpaque;\n\ uniform bool texDrawOpaque;\n\
uniform bool drawModeDepthEqualsTest;\n\
uniform bool polyDrawShadow;\n\ uniform bool polyDrawShadow;\n\
uniform int polyDepthOffsetMode;\n\ uniform int polyDepthOffsetMode;\n\
\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\ out vec4 outFragColor;\n\
\n\ \n\
#if ENABLE_EDGE_MARK\n\ #if ENABLE_EDGE_MARK\n\
@ -220,6 +229,9 @@ layout (depth_less) out float gl_FragDepth;\n\
void main()\n\ void main()\n\
{\n\ {\n\
outFragColor = vec4(0.0, 0.0, 0.0, 0.0);\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\ #if ENABLE_EDGE_MARK\n\
outPolyID = vec4(0.0, 0.0, 0.0, 0.0);\n\ outPolyID = vec4(0.0, 0.0, 0.0, 0.0);\n\
#endif\n\ #endif\n\
@ -289,6 +301,17 @@ void main()\n\
discard;\n\ discard;\n\
}\n\ }\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\ #if ENABLE_EDGE_MARK\n\
outPolyID = vec4( float(polyID)/63.0, float(polyIsWireframe == 1), 0.0, float(outFragColor.a > 0.999) );\n\ outPolyID = vec4( float(polyID)/63.0, float(polyIsWireframe == 1), 0.0, float(outFragColor.a > 0.999) );\n\
#endif\n\ #endif\n\
@ -1121,18 +1144,31 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples)
if (this->willUsePerSampleZeroDstPass) if (this->willUsePerSampleZeroDstPass)
{ {
glGenTextures(1, &OGLRef.texMSGColorID); glGenTextures(1, &OGLRef.texMSGColorID);
glGenTextures(1, &OGLRef.texMSGWorkingID);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID); 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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAG_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_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_WRAP_T, 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); 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 else
{ {
glGenRenderbuffers(1, &OGLRef.rboMSGColorID); glGenRenderbuffers(1, &OGLRef.rboMSGColorID);
glGenRenderbuffers(1, &OGLRef.rboMSGWorkingID);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGColorID); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGColorID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight); 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); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGPolyID);
@ -1149,10 +1185,12 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples)
if (this->willUsePerSampleZeroDstPass) if (this->willUsePerSampleZeroDstPass)
{ {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID, 0); 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 else
{ {
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboMSGColorID); 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); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, OGLRef.rboMSGPolyID);
@ -1185,12 +1223,21 @@ void OpenGLRenderer_3_2::DestroyMultisampledFBO()
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID); glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID);
glDeleteTextures(1, &OGLRef.texMSGColorID); glDeleteTextures(1, &OGLRef.texMSGColorID);
glDeleteTextures(1, &OGLRef.texMSGWorkingID);
glDeleteRenderbuffers(1, &OGLRef.rboMSGColorID); glDeleteRenderbuffers(1, &OGLRef.rboMSGColorID);
glDeleteRenderbuffers(1, &OGLRef.rboMSGWorkingID);
glDeleteRenderbuffers(1, &OGLRef.rboMSGPolyID); glDeleteRenderbuffers(1, &OGLRef.rboMSGPolyID);
glDeleteRenderbuffers(1, &OGLRef.rboMSGFogAttrID); glDeleteRenderbuffers(1, &OGLRef.rboMSGFogAttrID);
glDeleteRenderbuffers(1, &OGLRef.rboMSGDepthStencilID); glDeleteRenderbuffers(1, &OGLRef.rboMSGDepthStencilID);
OGLRef.fboMSIntermediateRenderID = 0; 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; this->isMultisampledFBOSupported = false;
} }
@ -1219,11 +1266,15 @@ void OpenGLRenderer_3_2::ResizeMultisampledFBOs(GLsizei numSamples)
{ {
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA, w, h, GL_TRUE); 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 else
{ {
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGColorID); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGColorID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA, w, h); 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); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGPolyID);
@ -1355,24 +1406,28 @@ Render3DError OpenGLRenderer_3_2::CreateGeometryPrograms()
{ {
fragShaderHeader << "#version 150\n"; 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 << "\n";
fragShaderHeader << "#define IS_CONSERVATIVE_DEPTH_SUPPORTED " << ((this->isConservativeDepthSupported || this->isConservativeDepthAMDSupported) ? 1 : 0) << "\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 << "#define DEPTH_EQUALS_TEST_TOLERANCE " << DEPTH_EQUALS_TEST_TOLERANCE << ".0\n";
fragShaderHeader << "\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; std::stringstream shaderFlags;
shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n"; shaderFlags << "#define USE_TEXTURE_SMOOTHING " << ((this->_enableTextureSmoothing) ? 1 : 0) << "\n";
shaderFlags << "#define USE_NDS_DEPTH_CALCULATION " << ((this->_emulateNDSDepthCalculation) ? 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 << "\n";
shaderFlags << "#define ENABLE_W_DEPTH " << ((programFlags.EnableWDepth) ? 1 : 0) << "\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_ALPHA_TEST " << ((programFlags.EnableAlphaTest) ? "true\n" : "false\n");
shaderFlags << "#define ENABLE_TEXTURE_SAMPLING " << ((programFlags.EnableTextureSampling) ? "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 TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n";
shaderFlags << "#define NEEDS_DEPTH_EQUALS_TEST " << ((programFlags.NeedsDepthEqualsTest) ? 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"; shaderFlags << "\n";
std::string fragShaderCode = fragShaderHeader.str() + shaderFlags.str() + std::string(GeometryFragShader_150); 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"); glBindAttribLocation(OGLRef.programGeometryID[flagsValue], OGLVertexAttributeID_Color, "inColor");
glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 0, "outFragColor"); glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 0, "outFragColor");
switch (programFlags.DrawBuffersMode) if (programFlags.EnableEdgeMark)
{ {
case OGLGeometryDrawBuffersMode_Color_Fog: glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 2, "outPolyID");
glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outFogAttributes"); }
break;
if (programFlags.EnableFog)
case OGLGeometryDrawBuffersMode_Color_EdgeMark: {
glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outPolyID"); glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 3, "outFogAttributes");
break;
case OGLGeometryDrawBuffersMode_Color_Fog_EdgeMark:
glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outPolyID");
glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 2, "outFogAttributes");
break;
default:
break;
} }
glLinkProgram(OGLRef.programGeometryID[flagsValue]); glLinkProgram(OGLRef.programGeometryID[flagsValue]);
@ -1439,19 +1485,33 @@ Render3DError OpenGLRenderer_3_2::CreateGeometryPrograms()
if (OGLRef.uboPolyStatesID != 0) 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); glUniformBlockBinding(OGLRef.programGeometryID[flagsValue], uniformBlockPolyStates, OGLBindingPointID_PolyStates);
} }
else else
{ {
const GLint uniformTexBufferPolyStates = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "PolyStates"); const GLint uniformTexBufferPolyStates = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "PolyStates");
glUniform1i(uniformTexBufferPolyStates, OGLTextureUnitID_PolyStates); glUniform1i(uniformTexBufferPolyStates, OGLTextureUnitID_PolyStates);
} }
OGLRef.uniformTexDrawOpaque[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "texDrawOpaque"); if (this->_emulateDepthLEqualPolygonFacing)
OGLRef.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow"); {
OGLRef.uniformPolyStateIndex[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyIndex"); if (programFlags.OpaqueDrawMode)
OGLRef.uniformPolyDepthOffsetMode[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffsetMode"); {
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; return error;
@ -1476,24 +1536,7 @@ void OpenGLRenderer_3_2::DestroyGeometryPrograms()
OGLRef.uboPolyStatesID = 0; OGLRef.uboPolyStatesID = 0;
OGLRef.tboPolyStatesID = 0; OGLRef.tboPolyStatesID = 0;
for (size_t flagsValue = 0; flagsValue < 128; flagsValue++) OpenGLRenderer_2_1::DestroyGeometryPrograms();
{
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;
} }
Render3DError OpenGLRenderer_3_2::CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString) Render3DError OpenGLRenderer_3_2::CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString)
@ -1935,6 +1978,18 @@ void OpenGLRenderer_3_2::GetExtensionSet(std::set<std::string> *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() Render3DError OpenGLRenderer_3_2::EnableVertexAttributes()
{ {
glBindVertexArray(this->ref->vaoGeometryStatesID); glBindVertexArray(this->ref->vaoGeometryStatesID);
@ -1967,7 +2022,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID);
glDrawBuffer(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_NEAREST); 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); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
} }
@ -1993,17 +2048,14 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con
OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags; OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags;
this->_geometryProgramFlags.EnableEdgeMark = 0; this->_geometryProgramFlags.EnableEdgeMark = 0;
this->_geometryProgramFlags.EnableFog = 0; this->_geometryProgramFlags.EnableFog = 0;
this->_SetupGeometryShaders(this->_geometryProgramFlags);
glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); glDrawBuffer(GL_COLOR_ATTACHMENT0);
glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE);
glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
this->EnableVertexAttributes(); this->EnableVertexAttributes();
// Draw the alpha polys, touching fully transparent pixels only once. // Draw the alpha polys, touching fully transparent pixels only once.
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
@ -2012,8 +2064,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con
// Restore OpenGL states back to normal. // Restore OpenGL states back to normal.
this->_geometryProgramFlags = oldGProgramFlags; this->_geometryProgramFlags = oldGProgramFlags;
glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); this->_SetupGeometryShaders(this->_geometryProgramFlags);
glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]);
glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0); glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
@ -2031,42 +2082,64 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con
return OGLERROR_NOERR; return OGLERROR_NOERR;
} }
Render3DError OpenGLRenderer_3_2::DownsampleFBO() void OpenGLRenderer_3_2::_ResolveWorkingBackFacing()
{ {
OGLRenderRef &OGLRef = *this->ref; 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); return;
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 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() 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.EnableWDepth = (engine.renderState.wbuffer) ? 1 : 0;
this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0; this->_geometryProgramFlags.EnableAlphaTest = (engine.renderState.enableAlphaTest) ? 1 : 0;
this->_geometryProgramFlags.EnableTextureSampling = (this->_enableTextureSampling) ? 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.ToonShadingMode = (engine.renderState.shading) ? 1 : 0;
this->_geometryProgramFlags.NeedsDepthEqualsTest = (this->_renderNeedsDepthEqualsTest) ? 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]); this->_currentAlphaTestRef = engine.renderState.alphaTestRef;
glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); this->_SetupGeometryShaders(this->_geometryProgramFlags);
glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE);
glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]);
glReadBuffer(GL_COLOR_ATTACHMENT0); glReadBuffer(GL_COLOR_ATTACHMENT0);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 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_READ_FRAMEBUFFER, OGLRef.fboClearImageID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); 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) if (this->_enableEdgeMark)
{ {
// Clear the polygon ID buffer // Clear the polygon ID buffer
const GLfloat oglPolyID[4] = {(GLfloat)opaquePolyID/63.0f, 0.0f, 0.0f, 1.0f}; 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) if (this->_enableFog)
@ -2498,13 +2575,19 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf
{ {
glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboRenderID); glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboRenderID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.selectedRenderingFBO); 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) if (this->_enableEdgeMark)
{ {
// Clear the polygon ID buffer // Clear the polygon ID buffer
const GLfloat oglPolyID[4] = {(GLfloat)opaquePolyID/63.0f, 0.0f, 0.0f, 1.0f}; 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) if (this->_enableFog)
@ -2531,30 +2614,28 @@ Render3DError OpenGLRenderer_3_2::ClearUsingValues(const FragmentColor &clearCol
OGLRenderRef &OGLRef = *this->ref; OGLRenderRef &OGLRef = *this->ref;
OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID;
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); 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]}; 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 glClearBufferfv(GL_COLOR, 0, oglColor); // texGColorID
glClearBufferfi(GL_DEPTH_STENCIL, 0, (GLfloat)clearAttributes.depth / (GLfloat)0x00FFFFFF, clearAttributes.opaquePolyID); 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) if (this->_enableEdgeMark)
{ {
const GLfloat oglPolyID[4] = {(GLfloat)clearAttributes.opaquePolyID/63.0f, 0.0f, 0.0f, 1.0f}; 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) if (this->_enableFog)
{ {
const GLfloat oglFogAttr[4] = {(GLfloat)clearAttributes.isFogged, 0.0f, 0.0f, 1.0f}; const GLfloat oglFogAttr[4] = {(GLfloat)clearAttributes.isFogged, 0.0f, 0.0f, 1.0f};
glClearBufferfv(GL_COLOR, 3, oglFogAttr);
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);
}
} }
this->_needsZeroDstAlphaPass = (clearColor6665.a == 0); this->_needsZeroDstAlphaPass = (clearColor6665.a == 0);
@ -2760,7 +2841,9 @@ Render3DError OpenGLRenderer_3_2::SetFramebufferSize(size_t w, size_t h)
this->DestroyEdgeMarkProgram(); this->DestroyEdgeMarkProgram();
this->DestroyFramebufferOutput6665Programs(); this->DestroyFramebufferOutput6665Programs();
this->DestroyMSGeometryZeroDstAlphaProgram(); this->DestroyMSGeometryZeroDstAlphaProgram();
this->DestroyGeometryPrograms();
this->CreateGeometryPrograms();
this->CreateEdgeMarkProgram(EdgeMarkVtxShader_150, EdgeMarkFragShader_150); this->CreateEdgeMarkProgram(EdgeMarkVtxShader_150, EdgeMarkFragShader_150);
this->CreateFramebufferOutput6665Program(0, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150); this->CreateFramebufferOutput6665Program(0, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150);
this->CreateFramebufferOutput6665Program(1, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150); this->CreateFramebufferOutput6665Program(1, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150);

View File

@ -90,10 +90,12 @@ protected:
virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString); virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet); virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes(); virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes(); virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const POLYLIST *polyList, const INDEXLIST *indexList, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr); 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 ReadBackPixels();
virtual Render3DError BeginRender(const GFX3D &engine); virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias); virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);