OpenGL Renderer: Use the fixed-point vertex list data instead of the floating-point based one, alongside other tune-ups.

- To determine polygon facing, use GFX3D's CPoly.isPolyBackFacing instead of using GLSL's gl_FrontFacing. This eases OpenGL version requirements and improves older GPU compatibility a little.
- Also fix a bug where GPUs that support FBOs, but not shaders, were unable to read out their framebuffers properly.
This commit is contained in:
rogerman 2023-02-24 13:49:07 -08:00
parent 37683a708e
commit fac70ce98b
4 changed files with 191 additions and 134 deletions

View File

@ -339,11 +339,11 @@ void main() \n\
mat2 texScaleMtx = mat2( vec2(polyTexScale.x, 0.0), \n\ mat2 texScaleMtx = mat2( vec2(polyTexScale.x, 0.0), \n\
vec2( 0.0, polyTexScale.y)); \n\ vec2( 0.0, polyTexScale.y)); \n\
\n\ \n\
vtxTexCoord = texScaleMtx * inTexCoord0; \n\ vtxTexCoord = (texScaleMtx * inTexCoord0) / 16.0; \n\
vtxColor = vec4(inColor / 63.0, polyAlpha); \n\ vtxColor = vec4(inColor / 63.0, polyAlpha); \n\
isPolyDrawable = ((polyMode != 3) || polyDrawShadow) ? 1.0 : -1.0;\n\ isPolyDrawable = ((polyMode != 3) || polyDrawShadow) ? 1.0 : -1.0;\n\
\n\ \n\
gl_Position = inPosition;\n\ gl_Position = inPosition / 4096.0;\n\
} \n\ } \n\
"}; "};
@ -367,20 +367,21 @@ uniform bool polyEnableTexture;\n\
uniform bool polyEnableFog;\n\ uniform bool polyEnableFog;\n\
uniform bool texDrawOpaque;\n\ uniform bool texDrawOpaque;\n\
uniform bool texSingleBitAlpha;\n\ uniform bool texSingleBitAlpha;\n\
uniform bool polyIsBackFacing;\n\
\n\ \n\
uniform bool drawModeDepthEqualsTest;\n\ uniform bool drawModeDepthEqualsTest;\n\
uniform bool polyDrawShadow;\n\ uniform bool polyDrawShadow;\n\
uniform float polyDepthOffset;\n\ uniform float polyDepthOffset;\n\
\n\ \n\
#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\ #if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\
uniform sampler2D inBackFacing;\n\ uniform sampler2D inDstBackFacing;\n\
#endif\n\ #endif\n\
\n\ \n\
void main()\n\ void main()\n\
{\n\ {\n\
#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\ #if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\
bool isOpaqueDstBackFacing = bool( texture2D(inBackFacing, vec2(gl_FragCoord.x/FRAMEBUFFER_SIZE_X, gl_FragCoord.y/FRAMEBUFFER_SIZE_Y)).r );\n\ bool isOpaqueDstBackFacing = bool( texture2D(inDstBackFacing, vec2(gl_FragCoord.x/FRAMEBUFFER_SIZE_X, gl_FragCoord.y/FRAMEBUFFER_SIZE_Y)).r );\n\
if (drawModeDepthEqualsTest && (!gl_FrontFacing || !isOpaqueDstBackFacing))\n\ if (drawModeDepthEqualsTest && (polyIsBackFacing || !isOpaqueDstBackFacing))\n\
{\n\ {\n\
discard;\n\ discard;\n\
}\n\ }\n\
@ -445,7 +446,7 @@ void main()\n\
gl_FragData[ATTACHMENT_FOG_ATTRIBUTES] = (isPolyDrawable > 0.0) ? vec4( float(polyEnableFog), 0.0, 0.0, float((newFragColor.a > 0.999) ? 1.0 : 0.5) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\ gl_FragData[ATTACHMENT_FOG_ATTRIBUTES] = (isPolyDrawable > 0.0) ? vec4( float(polyEnableFog), 0.0, 0.0, float((newFragColor.a > 0.999) ? 1.0 : 0.5) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\
#endif\n\ #endif\n\
#if DRAW_MODE_OPAQUE\n\ #if DRAW_MODE_OPAQUE\n\
gl_FragData[ATTACHMENT_WORKING_BUFFER] = vec4(float(!gl_FrontFacing), 0.0, 0.0, 1.0);\n\ gl_FragData[ATTACHMENT_WORKING_BUFFER] = vec4(float(polyIsBackFacing), 0.0, 0.0, 1.0);\n\
#endif\n\ #endif\n\
\n\ \n\
#if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\n\ #if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\n\
@ -1796,7 +1797,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLY *rawPolyList, const
if (lastPolyAttr.value != rawPoly.attribute.value) if (lastPolyAttr.value != rawPoly.attribute.value)
{ {
lastPolyAttr = rawPoly.attribute; lastPolyAttr = rawPoly.attribute;
this->SetupPolygon(rawPoly, (DRAWMODE != OGLPolyDrawMode_DrawOpaquePolys), (DRAWMODE != OGLPolyDrawMode_ZeroAlphaPass)); this->SetupPolygon(rawPoly, (DRAWMODE != OGLPolyDrawMode_DrawOpaquePolys), (DRAWMODE != OGLPolyDrawMode_ZeroAlphaPass), clippedPoly.isPolyBackFacing);
} }
// Set up the texture if it changed // Set up the texture if it changed
@ -2350,7 +2351,13 @@ OpenGLRenderer_1_2::~OpenGLRenderer_1_2()
_pixelReadNeedsFinish = false; _pixelReadNeedsFinish = false;
delete[] ref->color4fBuffer; free_aligned(ref->position4fBuffer);
ref->position4fBuffer = NULL;
free_aligned(ref->texCoord2fBuffer);
ref->texCoord2fBuffer = NULL;
free_aligned(ref->color4fBuffer);
ref->color4fBuffer = NULL; ref->color4fBuffer = NULL;
if (this->isShaderSupported) if (this->isShaderSupported)
@ -2439,14 +2446,6 @@ Render3DError OpenGLRenderer_1_2::InitExtensions()
} }
} }
this->isVAOSupported = this->isVBOSupported &&
(this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_array_object") ||
this->IsExtensionPresent(&oglExtensionSet, "GL_APPLE_vertex_array_object"));
if (this->isVAOSupported)
{
this->CreateVAOs();
}
this->isPBOSupported = this->isVBOSupported && this->isPBOSupported = this->isVBOSupported &&
(this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_pixel_buffer_object") || (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_pixel_buffer_object") ||
this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_pixel_buffer_object")); this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_pixel_buffer_object"));
@ -2604,6 +2603,20 @@ Render3DError OpenGLRenderer_1_2::InitExtensions()
{ {
return error; return error;
} }
// If shaders aren't available, we need to take care of the vertex data format
// conversion on the CPU instead of on the GPU using these client-side buffers.
OGLRef.position4fBuffer = (GLfloat *)malloc_alignedPage(VERTLIST_SIZE * sizeof(GLfloat) * 4);
OGLRef.texCoord2fBuffer = (GLfloat *)malloc_alignedPage(VERTLIST_SIZE * sizeof(GLfloat) * 2);
OGLRef.color4fBuffer = (GLfloat *)malloc_alignedPage(VERTLIST_SIZE * sizeof(GLfloat) * 4);
}
this->isVAOSupported = this->isVBOSupported &&
(this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_array_object") ||
this->IsExtensionPresent(&oglExtensionSet, "GL_APPLE_vertex_array_object"));
if (this->isVAOSupported)
{
this->CreateVAOs();
} }
// Set rendering support flags based on driver features. // Set rendering support flags based on driver features.
@ -2613,8 +2626,7 @@ Render3DError OpenGLRenderer_1_2::InitExtensions()
this->_deviceInfo.isFogSupported = this->isShaderSupported && this->isVBOSupported && this->isFBOSupported; this->_deviceInfo.isFogSupported = this->isShaderSupported && this->isVBOSupported && this->isFBOSupported;
this->_deviceInfo.isTextureSmoothingSupported = this->isShaderSupported; this->_deviceInfo.isTextureSmoothingSupported = this->isShaderSupported;
// We're requiring OpenGL v2.1 for this feature because it relies on gl_FrontFacing, which may not be supported on v2.0 drivers. this->_isDepthLEqualPolygonFacingSupported = this->isShaderSupported && this->isVBOSupported && this->isFBOSupported;
this->_isDepthLEqualPolygonFacingSupported = this->IsVersionSupported(2, 1, 0) && this->isShaderSupported && this->isVBOSupported && this->isFBOSupported;
this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported); this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported);
@ -2632,7 +2644,7 @@ Render3DError OpenGLRenderer_1_2::CreateVBOs()
glGenBuffersARB(1, &OGLRef.vboPostprocessVtxID); glGenBuffersARB(1, &OGLRef.vboPostprocessVtxID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID); glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, VERTLIST_SIZE * sizeof(VERT), NULL, GL_STREAM_DRAW_ARB); glBufferDataARB(GL_ARRAY_BUFFER_ARB, VERTLIST_SIZE * sizeof(NDSVertex), NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(OGLRef.vertIndexBuffer), NULL, GL_STREAM_DRAW_ARB); glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(OGLRef.vertIndexBuffer), NULL, GL_STREAM_DRAW_ARB);
@ -2703,25 +2715,48 @@ Render3DError OpenGLRenderer_1_2::CreateVAOs()
glGenVertexArrays(1, &OGLRef.vaoPostprocessStatesID); glGenVertexArrays(1, &OGLRef.vaoPostprocessStatesID);
glBindVertexArray(OGLRef.vaoGeometryStatesID); glBindVertexArray(OGLRef.vaoGeometryStatesID);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
if (this->isShaderSupported)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glEnableVertexAttribArray(OGLVertexAttributeID_Color); glEnableVertexAttribArray(OGLVertexAttributeID_Color);
glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord)); glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, position));
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord)); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, texCoord));
glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color)); glVertexAttribPointer(OGLVertexAttributeID_Color, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, color));
}
else
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(4, GL_FLOAT, 0, OGLRef.position4fBuffer);
glTexCoordPointer(2, GL_FLOAT, 0, OGLRef.texCoord2fBuffer);
glColorPointer(4, GL_FLOAT, 0, OGLRef.color4fBuffer);
}
glBindVertexArray(0); glBindVertexArray(0);
glBindVertexArray(OGLRef.vaoPostprocessStatesID); glBindVertexArray(OGLRef.vaoPostprocessStatesID);
if (this->isShaderSupported)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboPostprocessVtxID); glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboPostprocessVtxID);
glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0); glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8));
}
else
{
// Do nothing. Framebuffer post-processing requires shaders.
}
glBindVertexArray(0); glBindVertexArray(0);
@ -2822,6 +2857,7 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs()
// Set up FBOs // Set up FBOs
glGenFramebuffersEXT(1, &OGLRef.fboClearImageID); glGenFramebuffersEXT(1, &OGLRef.fboClearImageID);
glGenFramebuffersEXT(1, &OGLRef.fboFramebufferFlipID);
glGenFramebuffersEXT(1, &OGLRef.fboRenderID); glGenFramebuffersEXT(1, &OGLRef.fboRenderID);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboClearImageID); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboClearImageID);
@ -2838,6 +2874,18 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs()
return OGLERROR_FBO_CREATE_ERROR; return OGLERROR_FBO_CREATE_ERROR;
} }
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboFramebufferFlipID);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGColorID, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_WORKING_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0);
if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
{
INFO("OpenGL: Failed to create FBOs!\n");
this->DestroyFBOs();
return OGLERROR_FBO_CREATE_ERROR;
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGColorID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGColorID, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_POLYID_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_POLYID_ATTACHMENT_ID, GL_TEXTURE_2D, OGLRef.texGPolyID, 0);
@ -2874,6 +2922,7 @@ void OpenGLRenderer_1_2::DestroyFBOs()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID);
glDeleteFramebuffersEXT(1, &OGLRef.fboFramebufferFlipID);
glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID); glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID);
glDeleteTextures(1, &OGLRef.texCIColorID); glDeleteTextures(1, &OGLRef.texCIColorID);
glDeleteTextures(1, &OGLRef.texCIFogAttrID); glDeleteTextures(1, &OGLRef.texCIFogAttrID);
@ -2884,6 +2933,7 @@ void OpenGLRenderer_1_2::DestroyFBOs()
glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texGDepthStencilID);
OGLRef.fboClearImageID = 0; OGLRef.fboClearImageID = 0;
OGLRef.fboFramebufferFlipID = 0;
OGLRef.fboRenderID = 0; OGLRef.fboRenderID = 0;
this->isFBOSupported = false; this->isFBOSupported = false;
@ -3049,7 +3099,7 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms()
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 && this->IsVersionSupported(2, 1, 0) && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n"; shaderFlags << "#define USE_DEPTH_LEQUAL_POLYGON_FACING " << ((this->_emulateDepthLEqualPolygonFacing && this->isVBOSupported && this->isFBOSupported) ? 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");
@ -3057,7 +3107,7 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms()
shaderFlags << "#define TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n"; shaderFlags << "#define TOON_SHADING_MODE " << ((programFlags.ToonShadingMode) ? 1 : 0) << "\n";
shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n"; shaderFlags << "#define ENABLE_FOG " << ((programFlags.EnableFog && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n";
shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n"; shaderFlags << "#define ENABLE_EDGE_MARK " << ((programFlags.EnableEdgeMark && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n";
shaderFlags << "#define DRAW_MODE_OPAQUE " << ((programFlags.OpaqueDrawMode && this->IsVersionSupported(2, 1, 0) && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n"; shaderFlags << "#define DRAW_MODE_OPAQUE " << ((programFlags.OpaqueDrawMode && this->isVBOSupported && this->isFBOSupported) ? 1 : 0) << "\n";
shaderFlags << "\n"; shaderFlags << "\n";
shaderFlags << "#define ATTACHMENT_WORKING_BUFFER " << GeometryAttachmentWorkingBuffer[programFlags.DrawBuffersMode] << "\n"; shaderFlags << "#define ATTACHMENT_WORKING_BUFFER " << GeometryAttachmentWorkingBuffer[programFlags.DrawBuffersMode] << "\n";
shaderFlags << "#define ATTACHMENT_POLY_ID " << GeometryAttachmentPolyID[programFlags.DrawBuffersMode] << "\n"; shaderFlags << "#define ATTACHMENT_POLY_ID " << GeometryAttachmentPolyID[programFlags.DrawBuffersMode] << "\n";
@ -3103,7 +3153,7 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms()
if (this->_emulateDepthLEqualPolygonFacing && this->_isDepthLEqualPolygonFacingSupported && !programFlags.OpaqueDrawMode) if (this->_emulateDepthLEqualPolygonFacing && this->_isDepthLEqualPolygonFacingSupported && !programFlags.OpaqueDrawMode)
{ {
const GLint uniformTexBackfacing = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "inBackFacing"); const GLint uniformTexBackfacing = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "inDstBackFacing");
glUniform1i(uniformTexBackfacing, OGLTextureUnitID_FinalColor); glUniform1i(uniformTexBackfacing, OGLTextureUnitID_FinalColor);
} }
@ -3122,6 +3172,7 @@ Render3DError OpenGLRenderer_1_2::CreateGeometryPrograms()
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.uniformDrawModeDepthEqualsTest[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "drawModeDepthEqualsTest");
OGLRef.uniformPolyIsBackFacing[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyIsBackFacing");
OGLRef.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow"); OGLRef.uniformPolyDrawShadow[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDrawShadow");
OGLRef.uniformPolyDepthOffset[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffset"); OGLRef.uniformPolyDepthOffset[flagsValue] = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "polyDepthOffset");
} }
@ -3658,12 +3709,6 @@ Render3DError OpenGLRenderer_1_2::InitFinalRenderStates(const std::set<std::stri
// Mirrored Repeat Mode Support // Mirrored Repeat Mode Support
OGLRef.stateTexMirroredRepeat = (isTexMirroredRepeatSupported) ? GL_MIRRORED_REPEAT : GL_REPEAT; OGLRef.stateTexMirroredRepeat = (isTexMirroredRepeatSupported) ? GL_MIRRORED_REPEAT : GL_REPEAT;
// Map the vertex list's colors with 4 floats per color. This is being done
// because OpenGL needs 4-colors per vertex to support translucency. (The DS
// uses 3-colors per vertex, and adds alpha through the poly, so we can't
// simply reference the colors+alpha from just the vertices by themselves.)
OGLRef.color4fBuffer = (this->isShaderSupported) ? NULL : new GLfloat[VERTLIST_SIZE * 4];
return OGLERROR_NOERR; return OGLERROR_NOERR;
} }
@ -3828,29 +3873,18 @@ Render3DError OpenGLRenderer_1_2::EnableVertexAttributes()
glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glEnableVertexAttribArray(OGLVertexAttributeID_Color); glEnableVertexAttribArray(OGLVertexAttributeID_Color);
glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrPosition); glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, position));
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrTexCoord); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, texCoord));
glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrColor); glVertexAttribPointer(OGLVertexAttributeID_Color, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, color));
} }
else else
{ {
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(4, GL_FLOAT, 0, OGLRef.position4fBuffer);
glTexCoordPointer(2, GL_FLOAT, 0, OGLRef.texCoord2fBuffer);
if (this->isVBOSupported) glColorPointer(4, GL_FLOAT, 0, OGLRef.color4fBuffer);
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glColorPointer(4, GL_FLOAT, 0, OGLRef.vtxPtrColor);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
}
else
{
glColorPointer(4, GL_FLOAT, 0, OGLRef.vtxPtrColor);
}
glVertexPointer(4, GL_FLOAT, sizeof(VERT), OGLRef.vtxPtrPosition);
glTexCoordPointer(2, GL_FLOAT, sizeof(VERT), OGLRef.vtxPtrTexCoord);
} }
} }
@ -3874,8 +3908,8 @@ Render3DError OpenGLRenderer_1_2::DisableVertexAttributes()
else else
{ {
glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
} }
} }
@ -4130,20 +4164,16 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels()
{ {
// Just flips the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware. // Just flips the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware.
// Further colorspace conversion will need to be done in a later step. // Further colorspace conversion will need to be done in a later step.
if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor)
{ const GLenum flipTarget = (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) ? GL_WORKING_ATTACHMENT_ID : GL_COLOROUT_ATTACHMENT_ID;
glDrawBuffer(GL_WORKING_ATTACHMENT_ID);
glReadBuffer(GL_COLOROUT_ATTACHMENT_ID); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboFramebufferFlipID);
glDrawBuffer(flipTarget);
glBlitFramebufferEXT(0, (GLint)this->_framebufferHeight, (GLint)this->_framebufferWidth, 0, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBlitFramebufferEXT(0, (GLint)this->_framebufferHeight, (GLint)this->_framebufferWidth, 0, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glReadBuffer(GL_WORKING_ATTACHMENT_ID);
} glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboFramebufferFlipID);
else glReadBuffer(flipTarget);
{
glDrawBuffer(GL_COLOROUT_ATTACHMENT_ID);
glReadBuffer(GL_WORKING_ATTACHMENT_ID);
glBlitFramebufferEXT(0, (GLint)this->_framebufferHeight, (GLint)this->_framebufferWidth, 0, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glReadBuffer(GL_COLOROUT_ATTACHMENT_ID);
}
} }
if (this->isPBOSupported) if (this->isPBOSupported)
@ -4181,18 +4211,18 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
if (this->isVBOSupported) if (this->isVBOSupported)
{ {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
// Only copy as much vertex data as we need to, since this can be a potentially large upload size. if (this->isShaderSupported)
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(VERT) * renderGList.rawVertCount, renderGList.rawVertList); {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(NDSVertex) * renderGList.rawVertCount, renderGList.rawVtxList);
} }
else else
{ {
// If VBOs aren't supported, we need to use the client-side buffers here. // If shaders aren't supported, we need to use the client-side buffers here.
OGLRef.vtxPtrPosition = (GLvoid *)&renderGList.rawVertList[0].coord; glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
OGLRef.vtxPtrTexCoord = (GLvoid *)&renderGList.rawVertList[0].texcoord; }
OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)&renderGList.rawVertList[0].color : OGLRef.color4fBuffer;
} }
// Generate the clipped polygon list. // Generate the clipped polygon list.
@ -4234,27 +4264,38 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
for (size_t j = 0; j < polyType; j++) for (size_t j = 0; j < polyType; j++)
{ {
const GLushort vertIndex = rawPoly.vertIndexes[j]; const GLushort vtxIndex = rawPoly.vertIndexes[j];
const size_t colorIndex = vertIndex * 4; const size_t positionIndex = vtxIndex * 4;
const size_t texCoordIndex = vtxIndex * 2;
const size_t colorIndex = vtxIndex * 4;
const NDSVertex &vtx = renderGList.rawVtxList[vtxIndex];
// Consolidate the vertex color and the poly alpha to our internal color buffer // Since we can't use shaders, we can't perform any data format conversions
// so that OpenGL can use it. // of the vertex data on the GPU. Therefore, we need to do the conversions
const VERT *vertForAlpha = &renderGList.rawVertList[vertIndex]; // on the CPU instead.
OGLRef.color4fBuffer[colorIndex+0] = divide6bitBy63_LUT[vertForAlpha->color[0]]; OGLRef.position4fBuffer[positionIndex+0] = (float)vtx.position.x / 4096.0f;
OGLRef.color4fBuffer[colorIndex+1] = divide6bitBy63_LUT[vertForAlpha->color[1]]; OGLRef.position4fBuffer[positionIndex+1] = (float)vtx.position.y / 4096.0f;
OGLRef.color4fBuffer[colorIndex+2] = divide6bitBy63_LUT[vertForAlpha->color[2]]; OGLRef.position4fBuffer[positionIndex+2] = (float)vtx.position.z / 4096.0f;
OGLRef.position4fBuffer[positionIndex+3] = (float)vtx.position.w / 4096.0f;
OGLRef.texCoord2fBuffer[texCoordIndex+0] = (float)vtx.texCoord.s / 16.0f;
OGLRef.texCoord2fBuffer[texCoordIndex+1] = (float)vtx.texCoord.t / 16.0f;
OGLRef.color4fBuffer[colorIndex+0] = divide6bitBy63_LUT[vtx.color.r];
OGLRef.color4fBuffer[colorIndex+1] = divide6bitBy63_LUT[vtx.color.g];
OGLRef.color4fBuffer[colorIndex+2] = divide6bitBy63_LUT[vtx.color.b];
OGLRef.color4fBuffer[colorIndex+3] = thePolyAlpha; OGLRef.color4fBuffer[colorIndex+3] = thePolyAlpha;
// While we're looping through our vertices, add each vertex index to a // While we're looping through our vertices, add each vertex index to a
// buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional // buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
// vertices here to convert them to GL_TRIANGLES, which are much easier // vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions. // to work with and won't be deprecated in future OpenGL versions.
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex; OGLRef.vertIndexBuffer[vertIndexCount++] = vtxIndex;
if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP)) if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
{ {
if (j == 2) if (j == 2)
{ {
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex; OGLRef.vertIndexBuffer[vertIndexCount++] = vtxIndex;
} }
else if (j == 3) else if (j == 3)
{ {
@ -4396,13 +4437,14 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry()
size_t indexOffset = 0; size_t indexOffset = 0;
const CPoly &firstCPoly = this->_clippedPolyList[0];
const POLY *rawPolyList = this->_rawPolyList; const POLY *rawPolyList = this->_rawPolyList;
const POLY &firstPoly = rawPolyList[this->_clippedPolyList[0].index]; const POLY &firstPoly = rawPolyList[firstCPoly.index];
POLYGON_ATTR lastPolyAttr = firstPoly.attribute; POLYGON_ATTR lastPolyAttr = firstPoly.attribute;
if (this->_clippedPolyOpaqueCount > 0) if (this->_clippedPolyOpaqueCount > 0)
{ {
this->SetupPolygon(firstPoly, false, true); this->SetupPolygon(firstPoly, false, true, firstCPoly.isPolyBackFacing);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(rawPolyList, this->_clippedPolyList, this->_clippedPolyCount, 0, this->_clippedPolyOpaqueCount - 1, indexOffset, lastPolyAttr); this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(rawPolyList, this->_clippedPolyList, this->_clippedPolyCount, 0, this->_clippedPolyOpaqueCount - 1, indexOffset, lastPolyAttr);
} }
@ -4414,16 +4456,17 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry()
{ {
if (this->_clippedPolyOpaqueCount == 0) if (this->_clippedPolyOpaqueCount == 0)
{ {
this->SetupPolygon(firstPoly, true, false); this->SetupPolygon(firstPoly, true, false, firstCPoly.isPolyBackFacing);
} }
this->ZeroDstAlphaPass(rawPolyList, this->_clippedPolyList, this->_clippedPolyCount, this->_clippedPolyOpaqueCount, this->_enableAlphaBlending, indexOffset, lastPolyAttr); this->ZeroDstAlphaPass(rawPolyList, this->_clippedPolyList, this->_clippedPolyCount, this->_clippedPolyOpaqueCount, this->_enableAlphaBlending, indexOffset, lastPolyAttr);
if (this->_clippedPolyOpaqueCount > 0) if (this->_clippedPolyOpaqueCount > 0)
{ {
const POLY &lastOpaquePoly = rawPolyList[this->_clippedPolyList[this->_clippedPolyOpaqueCount - 1].index]; const CPoly &lastOpaqueCPoly = this->_clippedPolyList[this->_clippedPolyOpaqueCount - 1];
const POLY &lastOpaquePoly = rawPolyList[lastOpaqueCPoly.index];
lastPolyAttr = lastOpaquePoly.attribute; lastPolyAttr = lastOpaquePoly.attribute;
this->SetupPolygon(lastOpaquePoly, false, true); this->SetupPolygon(lastOpaquePoly, false, true, lastOpaqueCPoly.isPolyBackFacing);
} }
} }
else else
@ -4440,7 +4483,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry()
if (this->_clippedPolyOpaqueCount == 0) if (this->_clippedPolyOpaqueCount == 0)
{ {
this->SetupPolygon(firstPoly, true, true); this->SetupPolygon(firstPoly, true, true, firstCPoly.isPolyBackFacing);
} }
else else
{ {
@ -4781,7 +4824,7 @@ void OpenGLRenderer_1_2::SetPolygonIndex(const size_t index)
this->_currentPolyIndex = index; this->_currentPolyIndex = index;
} }
Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer) Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer, bool isBackFacing)
{ {
// Set up depth test mode // Set up depth test mode
glDepthFunc((thePoly.attribute.DepthEqualTest_Enable) ? GL_EQUAL : GL_LESS); glDepthFunc((thePoly.attribute.DepthEqualTest_Enable) ? GL_EQUAL : GL_LESS);
@ -4860,6 +4903,7 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly, bool treatAs
glUniform1i(OGLRef.uniformPolyIsWireframe[this->_geometryProgramFlags.value], (GFX3D_IsPolyWireframe(thePoly)) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformPolyIsWireframe[this->_geometryProgramFlags.value], (GFX3D_IsPolyWireframe(thePoly)) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent[this->_geometryProgramFlags.value], (thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent[this->_geometryProgramFlags.value], (thePoly.attribute.TranslucentDepthWrite_Enable) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformPolyDepthOffset[this->_geometryProgramFlags.value], 0.0f); glUniform1f(OGLRef.uniformPolyDepthOffset[this->_geometryProgramFlags.value], 0.0f);
glUniform1i(OGLRef.uniformPolyIsBackFacing[this->_geometryProgramFlags.value], (isBackFacing) ? GL_TRUE : GL_FALSE);
} }
else else
{ {
@ -5119,6 +5163,16 @@ Render3DError OpenGLRenderer_1_2::Reset()
this->_pixelReadNeedsFinish = false; this->_pixelReadNeedsFinish = false;
if (OGLRef.position4fBuffer != NULL)
{
memset(OGLRef.position4fBuffer, 0, VERTLIST_SIZE * 4 * sizeof(GLfloat));
}
if (OGLRef.texCoord2fBuffer != NULL)
{
memset(OGLRef.texCoord2fBuffer, 0, VERTLIST_SIZE * 2 * sizeof(GLfloat));
}
if (OGLRef.color4fBuffer != NULL) if (OGLRef.color4fBuffer != NULL)
{ {
memset(OGLRef.color4fBuffer, 0, VERTLIST_SIZE * 4 * sizeof(GLfloat)); memset(OGLRef.color4fBuffer, 0, VERTLIST_SIZE * 4 * sizeof(GLfloat));
@ -5126,10 +5180,6 @@ Render3DError OpenGLRenderer_1_2::Reset()
this->_currentPolyIndex = 0; this->_currentPolyIndex = 0;
OGLRef.vtxPtrPosition = (GLvoid *)offsetof(VERT, coord);
OGLRef.vtxPtrTexCoord = (GLvoid *)offsetof(VERT, texcoord);
OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)offsetof(VERT, color) : OGLRef.color4fBuffer;
memset(&this->_pendingRenderStates, 0, sizeof(this->_pendingRenderStates)); memset(&this->_pendingRenderStates, 0, sizeof(this->_pendingRenderStates));
texCache.Reset(); texCache.Reset();
@ -5371,6 +5421,8 @@ Render3DError OpenGLRenderer_2_0::InitFinalRenderStates(const std::set<std::stri
OGLRef.stateTexMirroredRepeat = GL_MIRRORED_REPEAT; OGLRef.stateTexMirroredRepeat = GL_MIRRORED_REPEAT;
// Ignore our color buffer since we'll transfer the polygon alpha through a uniform. // Ignore our color buffer since we'll transfer the polygon alpha through a uniform.
OGLRef.position4fBuffer = NULL;
OGLRef.texCoord2fBuffer = NULL;
OGLRef.color4fBuffer = NULL; OGLRef.color4fBuffer = NULL;
return OGLERROR_NOERR; return OGLERROR_NOERR;
@ -5389,9 +5441,9 @@ Render3DError OpenGLRenderer_2_0::EnableVertexAttributes()
glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glEnableVertexAttribArray(OGLVertexAttributeID_Color); glEnableVertexAttribArray(OGLVertexAttributeID_Color);
glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrPosition); glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, position));
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrTexCoord); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, texCoord));
glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrColor); glVertexAttribPointer(OGLVertexAttributeID_Color, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, color));
} }
return OGLERROR_NOERR; return OGLERROR_NOERR;
@ -5433,7 +5485,7 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, co
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
// Only copy as much vertex data as we need to, since this can be a potentially large upload size. // Only copy as much vertex data as we need to, since this can be a potentially large upload size.
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * renderGList.rawVertCount, renderGList.rawVertList); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(NDSVertex) * renderGList.rawVertCount, renderGList.rawVtxList);
// Generate the clipped polygon list. // Generate the clipped polygon list.
bool renderNeedsToonTable = false; bool renderNeedsToonTable = false;

View File

@ -425,7 +425,8 @@ union OGLPolyStates
u8 TexSizeShiftS:3; u8 TexSizeShiftS:3;
u8 TexSizeShiftT:3; u8 TexSizeShiftT:3;
u8 :8; u8 IsBackFacing:1;
u8 :7;
}; };
}; };
@ -536,6 +537,7 @@ struct OGLRenderRef
GLuint fboClearImageID; GLuint fboClearImageID;
GLuint fboRenderID; GLuint fboRenderID;
GLuint fboFramebufferFlipID;
GLuint fboMSIntermediateRenderID; GLuint fboMSIntermediateRenderID;
GLuint selectedRenderingFBO; GLuint selectedRenderingFBO;
@ -581,6 +583,7 @@ struct OGLRenderRef
GLint uniformTexSingleBitAlpha[256]; GLint uniformTexSingleBitAlpha[256];
GLint uniformTexDrawOpaque[256]; GLint uniformTexDrawOpaque[256];
GLint uniformDrawModeDepthEqualsTest[256]; GLint uniformDrawModeDepthEqualsTest[256];
GLint uniformPolyIsBackFacing[256];
GLint uniformPolyStateIndex[256]; GLint uniformPolyStateIndex[256];
GLfloat uniformPolyDepthOffset[256]; GLfloat uniformPolyDepthOffset[256];
@ -591,16 +594,13 @@ struct OGLRenderRef
GLuint vaoPostprocessStatesID; GLuint vaoPostprocessStatesID;
// Client-side Buffers // Client-side Buffers
GLfloat *position4fBuffer;
GLfloat *texCoord2fBuffer;
GLfloat *color4fBuffer; GLfloat *color4fBuffer;
CACHE_ALIGN GLushort vertIndexBuffer[OGLRENDER_VERT_INDEX_BUFFER_COUNT]; CACHE_ALIGN GLushort vertIndexBuffer[OGLRENDER_VERT_INDEX_BUFFER_COUNT];
CACHE_ALIGN GLushort workingCIColorBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT]; CACHE_ALIGN GLushort workingCIColorBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
CACHE_ALIGN GLuint workingCIDepthStencilBuffer[2][GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT]; CACHE_ALIGN GLuint workingCIDepthStencilBuffer[2][GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
CACHE_ALIGN GLuint workingCIFogAttributesBuffer[2][GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT]; CACHE_ALIGN GLuint workingCIFogAttributesBuffer[2][GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
// Vertex Attributes Pointers
GLvoid *vtxPtrPosition;
GLvoid *vtxPtrTexCoord;
GLvoid *vtxPtrColor;
}; };
struct GFX3D_State; struct GFX3D_State;
@ -804,7 +804,7 @@ protected:
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;
virtual void SetPolygonIndex(const size_t index) = 0; virtual void SetPolygonIndex(const size_t index) = 0;
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer) = 0; virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer, bool isBackFacing) = 0;
public: public:
OpenGLRenderer(); OpenGLRenderer();
@ -888,7 +888,7 @@ protected:
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes); virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes);
virtual void SetPolygonIndex(const size_t index); virtual void SetPolygonIndex(const size_t index);
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer); virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer, bool isBackFacing);
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex); virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
virtual Render3DError SetupViewport(const GFX3D_Viewport viewport); virtual Render3DError SetupViewport(const GFX3D_Viewport viewport);

View File

@ -142,6 +142,7 @@ flat out int polySetNewDepthForTranslucent;\n\
flat out int polyMode;\n\ flat out int polyMode;\n\
flat out int polyID;\n\ flat out int polyID;\n\
flat out int texSingleBitAlpha;\n\ flat out int texSingleBitAlpha;\n\
flat out int polyIsBackFacing;\n\
flat out int isPolyDrawable;\n\ flat out int isPolyDrawable;\n\
\n\ \n\
void main()\n\ void main()\n\
@ -165,15 +166,16 @@ void main()\n\
polySetNewDepthForTranslucent = (polyStateBits >> 15) & 0x01;\n\ polySetNewDepthForTranslucent = (polyStateBits >> 15) & 0x01;\n\
polyEnableTexture = (polyStateBits >> 16) & 0x01;\n\ polyEnableTexture = (polyStateBits >> 16) & 0x01;\n\
texSingleBitAlpha = (polyStateBits >> 17) & 0x01;\n\ texSingleBitAlpha = (polyStateBits >> 17) & 0x01;\n\
polyIsBackFacing = (polyStateBits >> 24) & 0x01;\n\
\n\ \n\
isPolyDrawable = int((polyMode != 3) || polyDrawShadow);\n\ isPolyDrawable = int((polyMode != 3) || polyDrawShadow);\n\
\n\ \n\
mat2 texScaleMtx = mat2( vec2(polyTexScale.x, 0.0), \n\ mat2 texScaleMtx = mat2( vec2(polyTexScale.x, 0.0), \n\
vec2( 0.0, polyTexScale.y)); \n\ vec2( 0.0, polyTexScale.y)); \n\
\n\ \n\
vtxTexCoord = texScaleMtx * inTexCoord0;\n\ vtxTexCoord = (texScaleMtx * inTexCoord0) / 16.0;\n\
vtxColor = vec4(inColor / 63.0, polyAlpha);\n\ vtxColor = vec4(inColor / 63.0, polyAlpha);\n\
gl_Position = inPosition;\n\ gl_Position = inPosition / 4096.0;\n\
}\n\ }\n\
"}; "};
@ -188,6 +190,7 @@ flat in int polySetNewDepthForTranslucent;\n\
flat in int polyMode;\n\ flat in int polyMode;\n\
flat in int polyID;\n\ flat in int polyID;\n\
flat in int texSingleBitAlpha;\n\ flat in int texSingleBitAlpha;\n\
flat in int polyIsBackFacing;\n\
flat in int isPolyDrawable;\n\ flat in int isPolyDrawable;\n\
\n\ \n\
layout (std140) uniform RenderStates\n\ layout (std140) uniform RenderStates\n\
@ -212,9 +215,9 @@ uniform bool polyDrawShadow;\n\
uniform float polyDepthOffset;\n\ uniform float polyDepthOffset;\n\
\n\ \n\
#if DRAW_MODE_OPAQUE\n\ #if DRAW_MODE_OPAQUE\n\
out vec4 outBackFacing;\n\ out vec4 outDstBackFacing;\n\
#elif USE_DEPTH_LEQUAL_POLYGON_FACING\n\ #elif USE_DEPTH_LEQUAL_POLYGON_FACING\n\
uniform sampler2D inBackFacing;\n\ uniform sampler2D inDstBackFacing;\n\
#endif\n\ #endif\n\
\n\ \n\
out vec4 outFragColor;\n\ out vec4 outFragColor;\n\
@ -232,8 +235,8 @@ layout (depth_less) out float gl_FragDepth;\n\
void main()\n\ void main()\n\
{\n\ {\n\
#if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\ #if USE_DEPTH_LEQUAL_POLYGON_FACING && !DRAW_MODE_OPAQUE\n\
bool isOpaqueDstBackFacing = bool( texelFetch(inBackFacing, ivec2(gl_FragCoord.xy), 0).r );\n\ bool isOpaqueDstBackFacing = bool( texelFetch(inDstBackFacing, ivec2(gl_FragCoord.xy), 0).r );\n\
if ( drawModeDepthEqualsTest && (!gl_FrontFacing || !isOpaqueDstBackFacing) )\n\ if ( drawModeDepthEqualsTest && (bool(polyIsBackFacing) || !isOpaqueDstBackFacing) )\n\
{\n\ {\n\
discard;\n\ discard;\n\
}\n\ }\n\
@ -305,7 +308,7 @@ void main()\n\
outFogAttributes = (isPolyDrawable != 0) ? vec4( float(polyEnableFog), 0.0, 0.0, float((outFragColor.a > 0.999) ? 1.0 : 0.5) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\ outFogAttributes = (isPolyDrawable != 0) ? vec4( float(polyEnableFog), 0.0, 0.0, float((outFragColor.a > 0.999) ? 1.0 : 0.5) ) : vec4(0.0, 0.0, 0.0, 0.0);\n\
#endif\n\ #endif\n\
#if DRAW_MODE_OPAQUE\n\ #if DRAW_MODE_OPAQUE\n\
outBackFacing = vec4(float(!gl_FrontFacing), 0.0, 0.0, 1.0);\n\ outDstBackFacing = vec4(float(polyIsBackFacing), 0.0, 0.0, 1.0);\n\
#endif\n\ #endif\n\
\n\ \n\
#if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\n\ #if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\n\
@ -791,7 +794,7 @@ Render3DError OpenGLRenderer_3_2::InitExtensions()
INFO("OpenGL: Driver does not support at least 2x multisampled FBOs.\n"); INFO("OpenGL: Driver does not support at least 2x multisampled FBOs.\n");
} }
this->_isDepthLEqualPolygonFacingSupported = this->isShaderSupported && this->isVBOSupported && this->isFBOSupported; this->_isDepthLEqualPolygonFacingSupported = true;
this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported); this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported);
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
@ -1111,9 +1114,9 @@ Render3DError OpenGLRenderer_3_2::CreateVAOs()
glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glEnableVertexAttribArray(OGLVertexAttributeID_Color); glEnableVertexAttribArray(OGLVertexAttributeID_Color);
glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord)); glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, position));
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord)); glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_INT, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, texCoord));
glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color)); glVertexAttribPointer(OGLVertexAttributeID_Color, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(NDSVertex), (const GLvoid *)offsetof(NDSVertex, color));
glBindVertexArray(0); glBindVertexArray(0);
@ -1280,7 +1283,7 @@ Render3DError OpenGLRenderer_3_2::CreateGeometryPrograms()
if (programFlags.OpaqueDrawMode) if (programFlags.OpaqueDrawMode)
{ {
glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], GeometryAttachmentWorkingBuffer[programFlags.DrawBuffersMode], "outBackFacing"); glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], GeometryAttachmentWorkingBuffer[programFlags.DrawBuffersMode], "outDstBackFacing");
} }
glLinkProgram(OGLRef.programGeometryID[flagsValue]); glLinkProgram(OGLRef.programGeometryID[flagsValue]);
@ -1319,7 +1322,7 @@ Render3DError OpenGLRenderer_3_2::CreateGeometryPrograms()
if (this->_emulateDepthLEqualPolygonFacing && !programFlags.OpaqueDrawMode) if (this->_emulateDepthLEqualPolygonFacing && !programFlags.OpaqueDrawMode)
{ {
const GLint uniformTexBackfacing = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "inBackFacing"); const GLint uniformTexBackfacing = glGetUniformLocation(OGLRef.programGeometryID[flagsValue], "inDstBackFacing");
glUniform1i(uniformTexBackfacing, OGLTextureUnitID_FinalColor); glUniform1i(uniformTexBackfacing, OGLTextureUnitID_FinalColor);
} }
@ -1999,9 +2002,9 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
glDeleteSync(this->_syncBufferSetup); glDeleteSync(this->_syncBufferSetup);
} }
const size_t vtxBufferSize = sizeof(VERT) * renderGList.rawVertCount; const size_t vtxBufferSize = sizeof(NDSVertex) * renderGList.rawVertCount;
VERT *vtxPtr = (VERT *)glMapBufferRange(GL_ARRAY_BUFFER, 0, vtxBufferSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); NDSVertex *vtxPtr = (NDSVertex *)glMapBufferRange(GL_ARRAY_BUFFER, 0, vtxBufferSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
memcpy(vtxPtr, renderGList.rawVertList, vtxBufferSize); memcpy(vtxPtr, renderGList.rawVtxList, vtxBufferSize);
glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_ARRAY_BUFFER);
this->_syncBufferSetup = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); this->_syncBufferSetup = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
@ -2143,6 +2146,8 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
polyStates[i].TexSingleBitAlpha = (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? 1 : 0; polyStates[i].TexSingleBitAlpha = (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? 1 : 0;
polyStates[i].TexSizeShiftS = rawPoly.texParam.SizeShiftS; // Note that we are using the preshifted size of S polyStates[i].TexSizeShiftS = rawPoly.texParam.SizeShiftS; // Note that we are using the preshifted size of S
polyStates[i].TexSizeShiftT = rawPoly.texParam.SizeShiftT; // Note that we are using the preshifted size of T polyStates[i].TexSizeShiftT = rawPoly.texParam.SizeShiftT; // Note that we are using the preshifted size of T
polyStates[i].IsBackFacing = (this->_clippedPolyList[i].isPolyBackFacing) ? 1 : 0;
} }
if (OGLRef.uboPolyStatesID != 0) if (OGLRef.uboPolyStatesID != 0)
@ -2401,7 +2406,7 @@ void OpenGLRenderer_3_2::SetPolygonIndex(const size_t index)
} }
} }
Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer) Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer, bool isBackFacing)
{ {
OGLRenderRef &OGLRef = *this->ref; OGLRenderRef &OGLRef = *this->ref;

View File

@ -109,7 +109,7 @@ protected:
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes); virtual Render3DError ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes);
virtual void SetPolygonIndex(const size_t index); virtual void SetPolygonIndex(const size_t index);
virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer); virtual Render3DError SetupPolygon(const POLY &thePoly, bool treatAsTranslucent, bool willChangeStencilBuffer, bool isBackFacing);
virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex); virtual Render3DError SetupTexture(const POLY &thePoly, size_t polyRenderIndex);
virtual Render3DError SetFramebufferSize(size_t w, size_t h); virtual Render3DError SetFramebufferSize(size_t w, size_t h);