OpenGL Renderer:

- Fix some rendering issues with shadow polygons. As a byproduct, this also fixes the drawing of certain missing polygons.
This commit is contained in:
rogerman 2016-03-02 05:30:40 +00:00
parent 891fd01f82
commit 2f473cd113
3 changed files with 79 additions and 70 deletions

View File

@ -842,6 +842,7 @@ OpenGLRenderer::OpenGLRenderer()
_mappedFramebuffer = NULL; _mappedFramebuffer = NULL;
_pixelReadNeedsFinish = false; _pixelReadNeedsFinish = false;
_currentPolyIndex = 0; _currentPolyIndex = 0;
_shadowPolyID.reserve(POLYLIST_SIZE);
} }
OpenGLRenderer::~OpenGLRenderer() OpenGLRenderer::~OpenGLRenderer()
@ -941,7 +942,10 @@ Render3DError OpenGLRenderer::_FlushFramebufferConvertOnCPU(const FragmentColor
// to the DS Y-coordinate. // to the DS Y-coordinate.
const size_t pixCount = this->_framebufferWidth; const size_t pixCount = this->_framebufferWidth;
#if defined(ENABLE_SSSE3) && defined(LOCAL_LE)
const size_t ssePixCount = pixCount - (pixCount % 4); const size_t ssePixCount = pixCount - (pixCount % 4);
#endif
if ( (dstRGBA6665 != NULL) && (dstRGBA5551 != NULL) ) if ( (dstRGBA6665 != NULL) && (dstRGBA5551 != NULL) )
{ {
@ -2483,7 +2487,6 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
if (polyCount > 0) if (polyCount > 0)
{ {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
if(renderState.enableAlphaBlending) if(renderState.enableAlphaBlending)
{ {
@ -2496,6 +2499,26 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState,
this->EnableVertexAttributes(); this->EnableVertexAttributes();
this->_shadowPolyID.clear();
for (size_t i = 0; i < polyCount; i++)
{
const POLY &thePoly = polyList->list[i];
if (thePoly.getAttributePolygonMode() != POLYGON_MODE_SHADOW)
{
continue;
}
const u8 polyID = thePoly.getAttributePolygonID();
if ( (polyID == 0) || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), polyID) != this->_shadowPolyID.end()) )
{
continue;
}
this->_shadowPolyID.push_back(polyID);
}
const POLY &firstPoly = polyList->list[indexList->list[0]]; const POLY &firstPoly = polyList->list[indexList->list[0]];
u32 lastPolyAttr = firstPoly.polyAttr; u32 lastPolyAttr = firstPoly.polyAttr;
u32 lastTexParams = firstPoly.texParam; u32 lastTexParams = firstPoly.texParam;
@ -2704,7 +2727,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const FragmentColor &clearCol
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // texGColorID glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // texGColorID
glClearColor(divide5bitBy31_LUT[clearColor.r], divide5bitBy31_LUT[clearColor.g], divide5bitBy31_LUT[clearColor.b], divide5bitBy31_LUT[clearColor.a]); glClearColor(divide5bitBy31_LUT[clearColor.r], divide5bitBy31_LUT[clearColor.g], divide5bitBy31_LUT[clearColor.b], divide5bitBy31_LUT[clearColor.a]);
glClearDepth((GLclampd)clearAttributes.depth / (GLclampd)0x00FFFFFF); glClearDepth((GLclampd)clearAttributes.depth / (GLclampd)0x00FFFFFF);
glClearStencil(clearAttributes.opaquePolyID); glClearStencil(0xFF);
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);
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); // texGDepthID glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); // texGDepthID
@ -2739,7 +2762,6 @@ void OpenGLRenderer_1_2::SetPolygonIndex(const size_t index)
Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly) Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly)
{ {
OGLRenderRef &OGLRef = *this->ref;
const PolygonAttributes attr = thePoly.getAttributes(); const PolygonAttributes attr = thePoly.getAttributes();
// Set up depth test mode // Set up depth test mode
@ -2767,13 +2789,15 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly)
// can change this too. // can change this too.
if (attr.polygonMode == POLYGON_MODE_SHADOW) if (attr.polygonMode == POLYGON_MODE_SHADOW)
{ {
glEnable(GL_STENCIL_TEST);
if (attr.polygonID == 0) if (attr.polygonID == 0)
{ {
//when the polyID is zero, we are writing the shadow mask. //when the polyID is zero, we are writing the shadow mask.
//set stencilbuf = 1 where the shadow volume is obstructed by geometry. //set stencilbuf = 1 where the shadow volume is obstructed by geometry.
//do not write color or depth information. //do not write color or depth information.
glStencilFunc(GL_ALWAYS, 65, 255); glStencilFunc(GL_NOTEQUAL, 0x80, 0xFF);
glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); glStencilOp(GL_KEEP, GL_ZERO, GL_KEEP);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
enableDepthWrite = GL_FALSE; enableDepthWrite = GL_FALSE;
} }
@ -2781,32 +2805,25 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly)
{ {
//when the polyid is nonzero, we are drawing the shadow poly. //when the polyid is nonzero, we are drawing the shadow poly.
//only draw the shadow poly where the stencilbuf==1. //only draw the shadow poly where the stencilbuf==1.
//I am not sure whether to update the depth buffer here--so I chose not to. glStencilFunc(GL_EQUAL, 0, 0xFF);
glStencilFunc(GL_EQUAL, 65, 255);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
enableDepthWrite = GL_TRUE; enableDepthWrite = GL_TRUE;
} }
} }
else if ( attr.isTranslucent || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), attr.polygonID) == this->_shadowPolyID.end()) )
{
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
enableDepthWrite = (!attr.isTranslucent || ( (attr.polygonMode == POLYGON_MODE_DECAL) && attr.isOpaque ) || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE;
}
else else
{ {
if (attr.isTranslucent) glEnable(GL_STENCIL_TEST);
{ glStencilFunc(GL_ALWAYS, 0x80, 0xFF);
glStencilFunc(GL_NOTEQUAL, attr.polygonID, 255); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = GL_TRUE;
}
else
{
glStencilFunc(GL_ALWAYS, 64, 255);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
}
if (attr.isTranslucent && !attr.enableAlphaDepthWrite)
{
enableDepthWrite = GL_FALSE;
} }
glDepthMask(enableDepthWrite); glDepthMask(enableDepthWrite);
@ -2814,6 +2831,7 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly)
// Set up polygon attributes // Set up polygon attributes
if (this->isShaderSupported) if (this->isShaderSupported)
{ {
OGLRenderRef &OGLRef = *this->ref;
glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode); glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode);
glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f); glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f);
@ -4285,7 +4303,6 @@ Render3DError OpenGLRenderer_2_0::RenderFog(const u8 *densityTable, const u32 co
Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY &thePoly) Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY &thePoly)
{ {
OGLRenderRef &OGLRef = *this->ref;
const PolygonAttributes attr = thePoly.getAttributes(); const PolygonAttributes attr = thePoly.getAttributes();
// Set up depth test mode // Set up depth test mode
@ -4313,13 +4330,15 @@ Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY &thePoly)
// can change this too. // can change this too.
if (attr.polygonMode == POLYGON_MODE_SHADOW) if (attr.polygonMode == POLYGON_MODE_SHADOW)
{ {
glEnable(GL_STENCIL_TEST);
if (attr.polygonID == 0) if (attr.polygonID == 0)
{ {
//when the polyID is zero, we are writing the shadow mask. //when the polyID is zero, we are writing the shadow mask.
//set stencilbuf = 1 where the shadow volume is obstructed by geometry. //set stencilbuf = 1 where the shadow volume is obstructed by geometry.
//do not write color or depth information. //do not write color or depth information.
glStencilFunc(GL_ALWAYS, 65, 255); glStencilFunc(GL_NOTEQUAL, 0x80, 0xFF);
glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); glStencilOp(GL_KEEP, GL_ZERO, GL_KEEP);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
enableDepthWrite = GL_FALSE; enableDepthWrite = GL_FALSE;
} }
@ -4327,37 +4346,31 @@ Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY &thePoly)
{ {
//when the polyid is nonzero, we are drawing the shadow poly. //when the polyid is nonzero, we are drawing the shadow poly.
//only draw the shadow poly where the stencilbuf==1. //only draw the shadow poly where the stencilbuf==1.
//I am not sure whether to update the depth buffer here--so I chose not to. glStencilFunc(GL_EQUAL, 0, 0xFF);
glStencilFunc(GL_EQUAL, 65, 255);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
enableDepthWrite = GL_TRUE; enableDepthWrite = GL_TRUE;
} }
} }
else if ( attr.isTranslucent || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), attr.polygonID) == this->_shadowPolyID.end()) )
{
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
enableDepthWrite = (!attr.isTranslucent || ( (attr.polygonMode == POLYGON_MODE_DECAL) && attr.isOpaque ) || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE;
}
else else
{ {
if (attr.isTranslucent) glEnable(GL_STENCIL_TEST);
{ glStencilFunc(GL_ALWAYS, 0x80, 0xFF);
glStencilFunc(GL_NOTEQUAL, attr.polygonID, 255); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = GL_TRUE;
}
else
{
glStencilFunc(GL_ALWAYS, 64, 255);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
}
if (attr.isTranslucent && !attr.enableAlphaDepthWrite)
{
enableDepthWrite = GL_FALSE;
} }
glDepthMask(enableDepthWrite); glDepthMask(enableDepthWrite);
// Set up polygon attributes // Set up polygon attributes
OGLRenderRef &OGLRef = *this->ref;
glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode); glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode);
glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f); glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f);

View File

@ -593,6 +593,7 @@ protected:
FragmentColor *_mappedFramebuffer; FragmentColor *_mappedFramebuffer;
bool _pixelReadNeedsFinish; bool _pixelReadNeedsFinish;
size_t _currentPolyIndex; size_t _currentPolyIndex;
std::vector<u8> _shadowPolyID;
Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551); Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstRGBA6665, u16 *__restrict dstRGBA5551);

View File

@ -1366,7 +1366,7 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine)
PolygonTexParams texParams = thePoly->getTexParams(); PolygonTexParams texParams = thePoly->getTexParams();
polyStates[i].enableTexture = (texParams.texFormat != TEXMODE_NONE && engine.renderState.enableTexturing) ? GL_TRUE : GL_FALSE; polyStates[i].enableTexture = (texParams.texFormat != TEXMODE_NONE && engine.renderState.enableTexturing) ? GL_TRUE : GL_FALSE;
polyStates[i].enableFog = (polyAttr.enableRenderFog) ? GL_TRUE : GL_FALSE; polyStates[i].enableFog = (polyAttr.enableRenderFog && !(polyAttr.polygonMode == POLYGON_MODE_SHADOW && polyAttr.polygonID == 0)) ? GL_TRUE : GL_FALSE;
polyStates[i].enableDepthWrite = ((!polyAttr.isTranslucent || polyAttr.enableAlphaDepthWrite) && !(polyAttr.polygonMode == POLYGON_MODE_SHADOW && polyAttr.polygonID == 0)) ? GL_TRUE : GL_FALSE; polyStates[i].enableDepthWrite = ((!polyAttr.isTranslucent || polyAttr.enableAlphaDepthWrite) && !(polyAttr.polygonMode == POLYGON_MODE_SHADOW && polyAttr.polygonID == 0)) ? GL_TRUE : GL_FALSE;
polyStates[i].setNewDepthForTranslucent = (polyAttr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE; polyStates[i].setNewDepthForTranslucent = (polyAttr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE;
polyStates[i].polyAlpha = (!polyAttr.isWireframe && polyAttr.isTranslucent) ? polyAttr.alpha : 0x1F; polyStates[i].polyAlpha = (!polyAttr.isWireframe && polyAttr.isTranslucent) ? polyAttr.alpha : 0x1F;
@ -1556,7 +1556,7 @@ Render3DError OpenGLRenderer_3_2::ClearUsingValues(const FragmentColor &clearCol
const GLfloat oglPolyID[4] = {(GLfloat)clearAttributes.opaquePolyID/63.0f, 0.0, 0.0, 1.0}; const GLfloat oglPolyID[4] = {(GLfloat)clearAttributes.opaquePolyID/63.0f, 0.0, 0.0, 1.0};
const GLfloat oglFogAttr[4] = {(GLfloat)clearAttributes.isFogged, 0.0, 0.0, 1.0}; const GLfloat oglFogAttr[4] = {(GLfloat)clearAttributes.isFogged, 0.0, 0.0, 1.0};
glClearBufferfi(GL_DEPTH_STENCIL, 0, (GLfloat)clearAttributes.depth / (GLfloat)0x00FFFFFF, clearAttributes.opaquePolyID); glClearBufferfi(GL_DEPTH_STENCIL, 0, (GLfloat)clearAttributes.depth / (GLfloat)0x00FFFFFF, 0xFF);
glClearBufferfv(GL_COLOR, 0, oglColor); // texGColorID glClearBufferfv(GL_COLOR, 0, oglColor); // texGColorID
glClearBufferfv(GL_COLOR, 1, oglDepth); // texGDepthID glClearBufferfv(GL_COLOR, 1, oglDepth); // texGDepthID
glClearBufferfv(GL_COLOR, 2, oglPolyID); // texGPolyID glClearBufferfv(GL_COLOR, 2, oglPolyID); // texGPolyID
@ -1600,13 +1600,15 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly)
// can change this too. // can change this too.
if (attr.polygonMode == POLYGON_MODE_SHADOW) if (attr.polygonMode == POLYGON_MODE_SHADOW)
{ {
if(attr.polygonID == 0) glEnable(GL_STENCIL_TEST);
if (attr.polygonID == 0)
{ {
//when the polyID is zero, we are writing the shadow mask. //when the polyID is zero, we are writing the shadow mask.
//set stencilbuf = 1 where the shadow volume is obstructed by geometry. //set stencilbuf = 1 where the shadow volume is obstructed by geometry.
//do not write color or depth information. //do not write color or depth information.
glStencilFunc(GL_ALWAYS, 65, 255); glStencilFunc(GL_NOTEQUAL, 0x80, 0xFF);
glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); glStencilOp(GL_KEEP, GL_ZERO, GL_KEEP);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
enableDepthWrite = GL_FALSE; enableDepthWrite = GL_FALSE;
} }
@ -1614,32 +1616,25 @@ Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly)
{ {
//when the polyid is nonzero, we are drawing the shadow poly. //when the polyid is nonzero, we are drawing the shadow poly.
//only draw the shadow poly where the stencilbuf==1. //only draw the shadow poly where the stencilbuf==1.
//I am not sure whether to update the depth buffer here--so I chose not to. glStencilFunc(GL_EQUAL, 0, 0xFF);
glStencilFunc(GL_EQUAL, 65, 255);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
enableDepthWrite = GL_TRUE; enableDepthWrite = GL_TRUE;
} }
} }
else if ( attr.isTranslucent || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), attr.polygonID) == this->_shadowPolyID.end()) )
{
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
enableDepthWrite = (!attr.isTranslucent || ( (attr.polygonMode == POLYGON_MODE_DECAL) && attr.isOpaque ) || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE;
}
else else
{ {
if (attr.isTranslucent) glEnable(GL_STENCIL_TEST);
{ glStencilFunc(GL_ALWAYS, 0x80, 0xFF);
glStencilFunc(GL_NOTEQUAL, attr.polygonID, 255); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); enableDepthWrite = GL_TRUE;
}
else
{
glStencilFunc(GL_ALWAYS, 64, 255);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
}
if (attr.isTranslucent && !attr.enableAlphaDepthWrite)
{
enableDepthWrite = GL_FALSE;
} }
glDepthMask(enableDepthWrite); glDepthMask(enableDepthWrite);