diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 0deb66d40..a152485cd 100755 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -454,7 +454,11 @@ static const char *EdgeMarkFragShader_100 = {"\ \n\ uniform sampler2D texInFragDepth;\n\ uniform sampler2D texInPolyID;\n\ + \n\ + uniform vec2 framebufferSize;\n\ uniform vec4 stateEdgeColor[8];\n\ + uniform int clearPolyID;\n\ + uniform float clearDepth;\n\ \n\ void main()\n\ {\n\ @@ -491,12 +495,51 @@ static const char *EdgeMarkFragShader_100 = {"\ isWireframe[3] = bool(polyIDInfo[3].g);\n\ isWireframe[4] = bool(polyIDInfo[4].g);\n\ \n\ - for (int i = 1; i < 5; i++)\n\ + bool isEdgeMarkingClearValues = ((polyID[0] != clearPolyID) && (depth[0] < clearDepth) && !isWireframe[0]);\n\ + vec2 pixelCoord = texCoord[0] * framebufferSize;\n\ + \n\ + if ( ((pixelCoord.x >= framebufferSize.x-1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[1]) && (depth[0] >= depth[1]) && !isWireframe[1])) )\n\ {\n\ - if ( (polyID[0] != polyID[i]) && (depth[0] >= depth[i]) && !isWireframe[i] )\n\ + if (pixelCoord.x >= framebufferSize.x-1.0)\n\ {\n\ - newEdgeColor = stateEdgeColor[polyID[i]/8];\n\ - break;\n\ + newEdgeColor = stateEdgeColor[polyID[0]/8];\n\ + }\n\ + else\n\ + {\n\ + newEdgeColor = stateEdgeColor[polyID[1]/8];\n\ + }\n\ + }\n\ + else if ( ((pixelCoord.y >= framebufferSize.y-1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[2]) && (depth[0] >= depth[2]) && !isWireframe[2])) )\n\ + {\n\ + if (pixelCoord.y >= framebufferSize.y-1.0)\n\ + {\n\ + newEdgeColor = stateEdgeColor[polyID[0]/8];\n\ + }\n\ + else\n\ + {\n\ + newEdgeColor = stateEdgeColor[polyID[2]/8];\n\ + }\n\ + }\n\ + else if ( ((pixelCoord.x < 1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[3]) && (depth[0] >= depth[3]) && !isWireframe[3])) )\n\ + {\n\ + if (pixelCoord.x < 1.0)\n\ + {\n\ + newEdgeColor = stateEdgeColor[polyID[0]/8];\n\ + }\n\ + else\n\ + {\n\ + newEdgeColor = stateEdgeColor[polyID[3]/8];\n\ + }\n\ + }\n\ + else if ( ((pixelCoord.y < 1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[4]) && (depth[0] >= depth[4]) && !isWireframe[4])) )\n\ + {\n\ + if (pixelCoord.y < 1.0)\n\ + {\n\ + newEdgeColor = stateEdgeColor[polyID[0]/8];\n\ + }\n\ + else\n\ + {\n\ + newEdgeColor = stateEdgeColor[polyID[4]/8];\n\ }\n\ }\n\ }\n\ @@ -3406,13 +3449,15 @@ Render3DError OpenGLRenderer_1_2::InitEdgeMarkProgramShaderLocations() glUseProgram(OGLRef.programEdgeMarkID); - const GLint uniformTexGDepth = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth"); - const GLint uniformTexGPolyID = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID"); + const GLint uniformTexGDepth = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth"); + const GLint uniformTexGPolyID = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID"); glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil); glUniform1i(uniformTexGPolyID, OGLTextureUnitID_GPolyID); - OGLRef.uniformFramebufferSize = glGetUniformLocation(OGLRef.programEdgeMarkID, "framebufferSize"); - OGLRef.uniformStateEdgeColor = glGetUniformLocation(OGLRef.programEdgeMarkID, "stateEdgeColor"); + OGLRef.uniformFramebufferSize_EdgeMark = glGetUniformLocation(OGLRef.programEdgeMarkID, "framebufferSize"); + OGLRef.uniformStateClearPolyID = glGetUniformLocation(OGLRef.programEdgeMarkID, "clearPolyID"); + OGLRef.uniformStateClearDepth = glGetUniformLocation(OGLRef.programEdgeMarkID, "clearDepth"); + OGLRef.uniformStateEdgeColor = glGetUniformLocation(OGLRef.programEdgeMarkID, "stateEdgeColor"); return OGLERROR_NOERR; } @@ -3939,6 +3984,8 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine) glUniform1i(OGLRef.uniformStateEnableAntialiasing, (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (this->_enableEdgeMark) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE); + glUniform1i(OGLRef.uniformStateClearPolyID, this->_clearAttributes.opaquePolyID); + glUniform1f(OGLRef.uniformStateClearDepth, (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF); glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]); glUniform1i(OGLRef.uniformTexDrawOpaque, GL_FALSE); glUniform1i(OGLRef.uniformPolyDrawShadow, GL_FALSE); @@ -4236,7 +4283,9 @@ Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const // Pass 2: Unblended edge mark colors to zero-alpha pixels glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glUseProgram(OGLRef.programEdgeMarkID); - glUniform2f(OGLRef.uniformFramebufferSize, this->_framebufferWidth, this->_framebufferHeight); + glUniform2f(OGLRef.uniformFramebufferSize_EdgeMark, this->_framebufferWidth, this->_framebufferHeight); + glUniform1i(OGLRef.uniformStateClearPolyID, this->_clearAttributes.opaquePolyID); + glUniform1f(OGLRef.uniformStateClearDepth, (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF); glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); @@ -4251,7 +4300,9 @@ Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const else { glUseProgram(OGLRef.programEdgeMarkID); - glUniform2f(OGLRef.uniformFramebufferSize, this->_framebufferWidth, this->_framebufferHeight); + glUniform2f(OGLRef.uniformFramebufferSize_EdgeMark, this->_framebufferWidth, this->_framebufferHeight); + glUniform1i(OGLRef.uniformStateClearPolyID, this->_clearAttributes.opaquePolyID); + glUniform1f(OGLRef.uniformStateClearDepth, (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF); glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glDisable(GL_STENCIL_TEST); diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index 38faa359d..b5c0dc73b 100755 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -372,10 +372,12 @@ struct OGLRenderStates GLuint enableEdgeMarking; GLuint enableFogAlphaOnly; GLuint useWDepth; + GLuint clearPolyID; + GLfloat clearDepth; GLfloat alphaTestRef; GLfloat fogOffset; GLfloat fogStep; - GLfloat pad_0; // This needs to be here to preserve alignment + GLfloat pad[3]; // This needs to be here to preserve alignment GLvec4 fogColor; GLvec4 fogDensity[32]; // Array of floats need to be padded as vec4 GLvec4 edgeColor[8]; @@ -471,7 +473,6 @@ struct OGLRenderRef GLuint programFramebufferRGBA6665OutputID; GLuint programFramebufferRGBA8888OutputID; - GLint uniformFramebufferSize; GLint uniformFramebufferSize_ConvertRGBA6665; GLint uniformFramebufferSize_ConvertRGBA8888; GLint uniformTexInFragColor_ConvertRGBA6665; @@ -483,6 +484,9 @@ struct OGLRenderRef GLint uniformStateEnableFogAlphaOnly; GLint uniformStateUseWDepth; GLint uniformStateAlphaTestRef; + GLint uniformFramebufferSize_EdgeMark; + GLint uniformStateClearPolyID; + GLint uniformStateClearDepth; GLint uniformStateEdgeColor; GLint uniformStateFogColor; GLint uniformStateFogDensity; @@ -639,6 +643,9 @@ protected: bool _emulateDepthEqualsTestTolerance; bool _emulateDepthLEqualPolygonFacing; + float _clearDepth; + + FragmentColor *_mappedFramebuffer; FragmentColor *_workingTextureUnpackBuffer; bool _pixelReadNeedsFinish; diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp old mode 100644 new mode 100755 index 2d697d3f2..15fd9c64e --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -23,6 +23,7 @@ #include #include +#include "utils/bits.h" #include "common.h" #include "debug.h" #include "NDSSystem.h" @@ -177,6 +178,8 @@ static const char *GeometryFragShader_150 = {"\ bool enableEdgeMarking;\n\ bool enableFogAlphaOnly;\n\ bool useWDepth;\n\ + int clearPolyID;\n\ + float clearDepth;\n\ float alphaTestRef;\n\ float fogOffset;\n\ float fogStep;\n\ @@ -351,6 +354,7 @@ static const char *EdgeMarkVtxShader_150 = {"\ \n\ in vec2 inPosition;\n\ in vec2 inTexCoord0;\n\ + \n\ layout (std140) uniform RenderStates\n\ {\n\ vec2 framebufferSize;\n\ @@ -360,6 +364,8 @@ static const char *EdgeMarkVtxShader_150 = {"\ bool enableEdgeMarking;\n\ bool enableFogAlphaOnly;\n\ bool useWDepth;\n\ + int clearPolyID;\n\ + float clearDepth;\n\ float alphaTestRef;\n\ float fogOffset;\n\ float fogStep;\n\ @@ -401,6 +407,8 @@ static const char *EdgeMarkFragShader_150 = {"\ bool enableEdgeMarking;\n\ bool enableFogAlphaOnly;\n\ bool useWDepth;\n\ + int clearPolyID;\n\ + float clearDepth;\n\ float alphaTestRef;\n\ float fogOffset;\n\ float fogStep;\n\ @@ -451,12 +459,51 @@ static const char *EdgeMarkFragShader_150 = {"\ isWireframe[3] = bool(polyIDInfo[3].g);\n\ isWireframe[4] = bool(polyIDInfo[4].g);\n\ \n\ - for (int i = 1; i < 5; i++)\n\ + bool isEdgeMarkingClearValues = ((polyID[0] != state.clearPolyID) && (depth[0] < state.clearDepth) && !isWireframe[0]);\n\ + vec2 pixelCoord = texCoord[0] * state.framebufferSize;\n\ + \n\ + if ( ((pixelCoord.x >= state.framebufferSize.x-1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[1]) && (depth[0] >= depth[1]) && !isWireframe[1])) )\n\ {\n\ - if ( (polyID[0] != polyID[i]) && (depth[0] >= depth[i]) && !isWireframe[i] )\n\ + if (pixelCoord.x >= state.framebufferSize.x-1.0)\n\ {\n\ - newEdgeColor = state.edgeColor[polyID[i]/8];\n\ - break;\n\ + newEdgeColor = state.edgeColor[polyID[0]/8];\n\ + }\n\ + else\n\ + {\n\ + newEdgeColor = state.edgeColor[polyID[1]/8];\n\ + }\n\ + }\n\ + else if ( ((pixelCoord.y >= state.framebufferSize.y-1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[2]) && (depth[0] >= depth[2]) && !isWireframe[2])) )\n\ + {\n\ + if (pixelCoord.y >= state.framebufferSize.y-1.0)\n\ + {\n\ + newEdgeColor = state.edgeColor[polyID[0]/8];\n\ + }\n\ + else\n\ + {\n\ + newEdgeColor = state.edgeColor[polyID[2]/8];\n\ + }\n\ + }\n\ + else if ( ((pixelCoord.x < 1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[3]) && (depth[0] >= depth[3]) && !isWireframe[3])) )\n\ + {\n\ + if (pixelCoord.x < 1.0)\n\ + {\n\ + newEdgeColor = state.edgeColor[polyID[0]/8];\n\ + }\n\ + else\n\ + {\n\ + newEdgeColor = state.edgeColor[polyID[3]/8];\n\ + }\n\ + }\n\ + else if ( ((pixelCoord.y < 1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[4]) && (depth[0] >= depth[4]) && !isWireframe[4])) )\n\ + {\n\ + if (pixelCoord.y < 1.0)\n\ + {\n\ + newEdgeColor = state.edgeColor[polyID[0]/8];\n\ + }\n\ + else\n\ + {\n\ + newEdgeColor = state.edgeColor[polyID[4]/8];\n\ }\n\ }\n\ }\n\ @@ -495,6 +542,8 @@ static const char *FogFragShader_150 = {"\ bool enableEdgeMarking;\n\ bool enableFogAlphaOnly;\n\ bool useWDepth;\n\ + int clearPolyID;\n\ + float clearDepth;\n\ float alphaTestRef;\n\ float fogOffset;\n\ float fogStep;\n\ @@ -1560,6 +1609,8 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine) state->enableEdgeMarking = (this->_enableEdgeMark) ? GL_TRUE : GL_FALSE; state->enableFogAlphaOnly = (engine.renderState.enableFogAlphaOnly) ? GL_TRUE : GL_FALSE; state->useWDepth = (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE; + state->clearPolyID = this->_clearAttributes.opaquePolyID; + state->clearDepth = (GLfloat)this->_clearAttributes.depth / (GLfloat)0x00FFFFFF; state->alphaTestRef = divide5bitBy31_LUT[engine.renderState.alphaTestRef]; state->fogColor.r = divide5bitBy31_LUT[(engine.renderState.fogColor ) & 0x0000001F]; state->fogColor.g = divide5bitBy31_LUT[(engine.renderState.fogColor >> 5) & 0x0000001F]; diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 15d014c27..da4a2ca72 100755 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -408,7 +408,11 @@ static void makeTables() for (size_t i = 0; i < 32768; i++) { // 15-bit to 24-bit depth formula from http://problemkaputt.de/gbatek.htm#ds3drearplane - dsDepthExtend_15bit_to_24bit[i] = LE_TO_LOCAL_32( (i*0x200)+((i+1)>>15)*0x01FF ); + //dsDepthExtend_15bit_to_24bit[i] = LE_TO_LOCAL_32( (i*0x0200) + ((i+1)>>15)*0x01FF ); + + // Is GBATEK actually correct here? Let's try using a simplified formula and see if it's + // more accurate. + dsDepthExtend_15bit_to_24bit[i] = LE_TO_LOCAL_32( (i*0x0200) + 0x01FF ); } for (size_t i = 0; i < 65536; i++) diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index cad782499..a64092787 100755 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -62,6 +62,7 @@ #include "render3D.h" #include "MMU.h" #include "NDSSystem.h" +#include "utils/bits.h" #include "utils/task.h" #include "filter/filter.h" #include "filter/xbrz.h" @@ -2131,77 +2132,6 @@ Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State &renderSt return RENDER3DERROR_NOERR; } -// This method is currently unused right now, in favor of the new multithreaded -// SoftRasterizerRenderer::RenderEdgeMarkingAndFog() method. But let's keep this -// one around for reference just in case something goes horribly wrong with the -// new multithreaded method. -Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias) -{ - // TODO: Old edge marking algorithm which tests only polyID, but checks the 8 surrounding pixels. Can this be removed? - - // this looks ok although it's still pretty much a hack, - // it needs to be redone with low-level accuracy at some point, - // but that should probably wait until the shape renderer is more accurate. - // a good test case for edge marking is Sonic Rush: - // - the edges are completely sharp/opaque on the very brief title screen intro, - // - the level-start intro gets a pseudo-antialiasing effect around the silhouette, - // - the character edges in-level are clearly transparent, and also show well through shield powerups. - - for (size_t i = 0, y = 0; y < this->_framebufferHeight; y++) - { - for (size_t x = 0; x < this->_framebufferWidth; x++, i++) - { - const u8 polyID = this->_framebufferAttributes->opaquePolyID[i]; - - if (this->edgeMarkDisabled[polyID>>3]) continue; - if (this->_framebufferAttributes->isTranslucentPoly[i] != 0) continue; - - // > is used instead of != to prevent double edges - // between overlapping polys of different IDs. - // also note that the edge generally goes on the outside, not the inside, (maybe needs to change later) - // and that polys with the same edge color can make edges against each other. - - const FragmentColor edgeColor = this->edgeMarkTable[polyID>>3]; - -#define PIXOFFSET(dx,dy) ((dx)+(this->_framebufferWidth*(dy))) -#define ISEDGE(dx,dy) ((x+(dx) < this->_framebufferWidth) && (y+(dy) < this->_framebufferHeight) && polyID > this->_framebufferAttributes->opaquePolyID[i+PIXOFFSET(dx,dy)]) -#define DRAWEDGE(dx,dy) EdgeBlend(this->_framebufferColor[i+PIXOFFSET(dx,dy)], edgeColor) - - bool upleft = ISEDGE(-1,-1); - bool up = ISEDGE( 0,-1); - bool upright = ISEDGE( 1,-1); - bool left = ISEDGE(-1, 0); - bool right = ISEDGE( 1, 0); - bool downleft = ISEDGE(-1, 1); - bool down = ISEDGE( 0, 1); - bool downright = ISEDGE( 1, 1); - - if(upleft && upright && downleft && !downright) - DRAWEDGE(-1,-1); - if(up && !down) - DRAWEDGE(0,-1); - if(upleft && upright && !downleft && downright) - DRAWEDGE(1,-1); - if(left && !right) - DRAWEDGE(-1,0); - if(right && !left) - DRAWEDGE(1,0); - if(upleft && !upright && downleft && downright) - DRAWEDGE(-1,1); - if(down && !up) - DRAWEDGE(0,1); - if(!upleft && upright && downleft && downright) - DRAWEDGE(1,1); - -#undef PIXOFFSET -#undef ISEDGE -#undef DRAWEDGE - } - } - - return RENDER3DERROR_NOERR; -} - Render3DError SoftRasterizerRenderer::UpdateEdgeMarkColorTable(const u16 *edgeMarkColorTable) { //TODO: need to test and find out whether these get grabbed at flush time, or at render time @@ -2286,48 +2216,6 @@ Render3DError SoftRasterizerRenderer::UpdateFogTable(const u8 *fogDensityTable) return RENDER3DERROR_NOERR; } -// This method is currently unused right now, in favor of the new multithreaded -// SoftRasterizerRenderer::RenderEdgeMarkingAndFog() method. But let's keep this -// one around for reference just in case something goes horribly wrong with the -// new multithreaded method. -Render3DError SoftRasterizerRenderer::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly) -{ - FragmentColor fogColor; - fogColor.color = COLOR555TO6665( color & 0x7FFF, (color>>16) & 0x1F ); - - const size_t framebufferFragmentCount = this->_framebufferWidth * this->_framebufferHeight; - - if (!alphaOnly) - { - for (size_t i = 0; i < framebufferFragmentCount; i++) - { - const size_t fogIndex = this->_framebufferAttributes->depth[i] >> 9; - assert(fogIndex < 32768); - const u8 fog = (this->_framebufferAttributes->isFogged[i] != 0) ? this->fogTable[fogIndex] : 0; - - FragmentColor &destFragmentColor = this->_framebufferColor[i]; - destFragmentColor.r = ((128-fog)*destFragmentColor.r + fogColor.r*fog)>>7; - destFragmentColor.g = ((128-fog)*destFragmentColor.g + fogColor.g*fog)>>7; - destFragmentColor.b = ((128-fog)*destFragmentColor.b + fogColor.b*fog)>>7; - destFragmentColor.a = ((128-fog)*destFragmentColor.a + fogColor.a*fog)>>7; - } - } - else - { - for (size_t i = 0; i < framebufferFragmentCount; i++) - { - const size_t fogIndex = this->_framebufferAttributes->depth[i] >> 9; - assert(fogIndex < 32768); - const u8 fog = (this->_framebufferAttributes->isFogged[i] != 0) ? this->fogTable[fogIndex] : 0; - - FragmentColor &destFragmentColor = this->_framebufferColor[i]; - destFragmentColor.a = ((128-fog)*destFragmentColor.a + fogColor.a*fog)>>7; - } - } - - return RENDER3DERROR_NOERR; -} - Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasterizerPostProcessParams ¶m) { for (size_t i = param.startLine * this->_framebufferWidth, y = param.startLine; y < param.endLine; y++) @@ -2338,45 +2226,75 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasteriz const u32 depth = this->_framebufferAttributes->depth[i]; const u8 polyID = this->_framebufferAttributes->opaquePolyID[i]; - // TODO: New edge marking algorithm which tests both polyID and depth, but only checks 4 surrounding pixels. Can we keep this one? if (param.enableEdgeMarking) { - // this looks ok although it's still pretty much a hack, - // it needs to be redone with low-level accuracy at some point, - // but that should probably wait until the shape renderer is more accurate. + FragmentColor edgeMarkColor; + edgeMarkColor.color = 0; + // a good test case for edge marking is Sonic Rush: // - the edges are completely sharp/opaque on the very brief title screen intro, // - the level-start intro gets a pseudo-antialiasing effect around the silhouette, // - the character edges in-level are clearly transparent, and also show well through shield powerups. - bool up = false; - bool left = false; - bool right = false; - bool down = false; - -#define PIXOFFSET(dx,dy) ((dx)+(this->_framebufferWidth*(dy))) -#define ISEDGE(dx,dy) ((x+(dx) < this->_framebufferWidth) && (y+(dy) < this->_framebufferHeight) && polyID != this->_framebufferAttributes->opaquePolyID[i+PIXOFFSET(dx,dy)] && depth >= this->_framebufferAttributes->depth[i+PIXOFFSET(dx,dy)]) -#define DRAWEDGE(dx,dy) EdgeBlend(dstColor, this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i+PIXOFFSET(dx,dy)] >> 3]) - - if (this->edgeMarkDisabled[polyID>>3] || this->_framebufferAttributes->isTranslucentPoly[i] != 0) - goto END_EDGE_MARK; - - up = ISEDGE( 0,-1); - left = ISEDGE(-1, 0); - right = ISEDGE( 1, 0); - down = ISEDGE( 0, 1); - - if (right) DRAWEDGE( 1, 0); - else if (down) DRAWEDGE( 0, 1); - else if (left) DRAWEDGE(-1, 0); - else if (up) DRAWEDGE( 0,-1); - - -#undef PIXOFFSET -#undef ISEDGE -#undef DRAWEDGE - -END_EDGE_MARK: ; + if (!this->edgeMarkDisabled[polyID>>3] && this->_framebufferAttributes->isTranslucentPoly[i] == 0) + { + const bool isEdgeMarkingClearValues = ((polyID != this->_clearAttributes.opaquePolyID) && (depth < this->_clearAttributes.depth)); + + const bool right = (x >= this->_framebufferWidth-1) ? isEdgeMarkingClearValues : ((polyID != this->_framebufferAttributes->opaquePolyID[i+1]) && (depth >= this->_framebufferAttributes->depth[i+1])); + const bool down = (y >= this->_framebufferHeight-1) ? isEdgeMarkingClearValues : ((polyID != this->_framebufferAttributes->opaquePolyID[i+this->_framebufferWidth]) && (depth >= this->_framebufferAttributes->depth[i+this->_framebufferWidth])); + const bool left = (x < 1) ? isEdgeMarkingClearValues : ((polyID != this->_framebufferAttributes->opaquePolyID[i-1]) && (depth >= this->_framebufferAttributes->depth[i-1])); + const bool up = (y < 1) ? isEdgeMarkingClearValues : ((polyID != this->_framebufferAttributes->opaquePolyID[i-this->_framebufferWidth]) && (depth >= this->_framebufferAttributes->depth[i-this->_framebufferWidth])); + + if (right) + { + if (x >= this->_framebufferWidth - 1) + { + edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i] >> 3]; + } + else + { + edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i+1] >> 3]; + } + } + else if (down) + { + if (y >= this->_framebufferHeight - 1) + { + edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i] >> 3]; + } + else + { + edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i+this->_framebufferWidth] >> 3]; + } + } + else if (left) + { + if (x < 1) + { + edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i] >> 3]; + } + else + { + edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i-1] >> 3]; + } + } + else if (up) + { + if (y < 1) + { + edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i] >> 3]; + } + else + { + edgeMarkColor = this->edgeMarkTable[this->_framebufferAttributes->opaquePolyID[i-this->_framebufferWidth] >> 3]; + } + } + + if (right || down || left || up) + { + EdgeBlend(dstColor, edgeMarkColor); + } + } } if (param.enableFog) @@ -2476,9 +2394,6 @@ void SoftRasterizerRenderer::ClearUsingValues_Execute(const size_t startPixel, c Render3DError SoftRasterizerRenderer::ClearUsingValues(const FragmentColor &clearColor6665, const FragmentAttributes &clearAttributes) { - this->_clearColor6665 = clearColor6665; - this->_clearAttributes = clearAttributes; - const bool doMultithreadedClear = (this->_threadCount > 0); if (doMultithreadedClear) @@ -2531,6 +2446,20 @@ Render3DError SoftRasterizerRenderer::Render(const GFX3D &engine) Render3DError error = RENDER3DERROR_NOERR; this->_isPoweredOn = true; + const u32 clearColorSwapped = LE_TO_LOCAL_32(engine.renderState.clearColor); + this->_clearColor6665.color = COLOR555TO6665(clearColorSwapped & 0x7FFF, (clearColorSwapped >> 16) & 0x1F); + + this->_clearAttributes.opaquePolyID = (clearColorSwapped >> 24) & 0x3F; + //special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display + //I am not sure whether it is right, though. previously this was cleared to 0, as a guess, + //but in spiderman2 some fires with polyid 0 try to render on top of the background + this->_clearAttributes.translucentPolyID = kUnsetTranslucentPolyID; + this->_clearAttributes.depth = engine.renderState.clearDepth; + this->_clearAttributes.stencil = 0; + this->_clearAttributes.isTranslucentPoly = 0; + this->_clearAttributes.polyFacing = PolyFacing_Unwritten; + this->_clearAttributes.isFogged = BIT15(clearColorSwapped); + error = this->BeginRender(engine); if (error != RENDER3DERROR_NOERR) { diff --git a/desmume/src/rasterize.h b/desmume/src/rasterize.h index 98dc726bc..36563e001 100644 --- a/desmume/src/rasterize.h +++ b/desmume/src/rasterize.h @@ -158,9 +158,6 @@ protected: size_t _customLinesPerThread; size_t _customPixelsPerThread; - FragmentColor _clearColor6665; - FragmentAttributes _clearAttributes; - GFX3D_Clipper clipper; u8 fogTable[32768]; FragmentColor edgeMarkTable[8]; @@ -179,8 +176,6 @@ protected: // Base rendering methods virtual Render3DError BeginRender(const GFX3D &engine); virtual Render3DError RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList); - virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias); - virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly); virtual Render3DError EndRender(const u64 frameCount); virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer); diff --git a/desmume/src/render3D.cpp b/desmume/src/render3D.cpp index b07fb9229..92db9a987 100755 --- a/desmume/src/render3D.cpp +++ b/desmume/src/render3D.cpp @@ -562,22 +562,6 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State &renderState) { Render3DError error = RENDER3DERROR_NOERR; - const u32 clearColorSwapped = LE_TO_LOCAL_32(renderState.clearColor); - FragmentColor clearColor6665; - clearColor6665.color = COLOR555TO6665(clearColorSwapped & 0x7FFF, (clearColorSwapped >> 16) & 0x1F); - - FragmentAttributes clearFragment; - clearFragment.opaquePolyID = (clearColorSwapped >> 24) & 0x3F; - //special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display - //I am not sure whether it is right, though. previously this was cleared to 0, as a guess, - //but in spiderman2 some fires with polyid 0 try to render on top of the background - clearFragment.translucentPolyID = kUnsetTranslucentPolyID; - clearFragment.depth = renderState.clearDepth; - clearFragment.stencil = 0; - clearFragment.isTranslucentPoly = 0; - clearFragment.polyFacing = PolyFacing_Unwritten; - clearFragment.isFogged = BIT15(clearColorSwapped); - if (renderState.enableClearImage) { //the lion, the witch, and the wardrobe (thats book 1, suck it you new-school numberers) @@ -595,7 +579,7 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State &renderState) this->clearImageColor16Buffer[i] = clearColorBuffer[i]; this->clearImageDepthBuffer[i] = DS_DEPTH15TO24(clearDepthBuffer[i]); this->clearImageFogBuffer[i] = BIT15(clearDepthBuffer[i]); - this->clearImagePolyIDBuffer[i] = clearFragment.opaquePolyID; + this->clearImagePolyIDBuffer[i] = this->_clearAttributes.opaquePolyID; } } else @@ -605,22 +589,22 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State &renderState) if (!isClearColorBlank && !isClearDepthBlank) { - this->_ClearImageScrolledLoop(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, clearFragment.opaquePolyID, + this->_ClearImageScrolledLoop(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, this->_clearAttributes.opaquePolyID, this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); } else if (isClearColorBlank) { - this->_ClearImageScrolledLoop< true, false>(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, clearFragment.opaquePolyID, + this->_ClearImageScrolledLoop< true, false>(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, this->_clearAttributes.opaquePolyID, this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); } else if (isClearDepthBlank) { - this->_ClearImageScrolledLoop(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, clearFragment.opaquePolyID, + this->_ClearImageScrolledLoop(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, this->_clearAttributes.opaquePolyID, this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); } else { - this->_ClearImageScrolledLoop< true, true>(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, clearFragment.opaquePolyID, + this->_ClearImageScrolledLoop< true, true>(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, this->_clearAttributes.opaquePolyID, this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); } } @@ -628,12 +612,12 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State &renderState) error = this->ClearUsingImage(this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); if (error != RENDER3DERROR_NOERR) { - error = this->ClearUsingValues(clearColor6665, clearFragment); + error = this->ClearUsingValues(this->_clearColor6665, this->_clearAttributes); } } else { - error = this->ClearUsingValues(clearColor6665, clearFragment); + error = this->ClearUsingValues(this->_clearColor6665, this->_clearAttributes); } return error; @@ -671,6 +655,9 @@ Render3DError Render3D::Reset() memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer)); memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer)); + this->_clearColor6665.color = 0; + memset(&this->_clearAttributes, 0, sizeof(FragmentAttributes)); + this->_renderNeedsFinish = false; this->_renderNeedsFlushMain = false; this->_renderNeedsFlush16 = false; @@ -700,6 +687,20 @@ Render3DError Render3D::Render(const GFX3D &engine) Render3DError error = RENDER3DERROR_NOERR; this->_isPoweredOn = true; + const u32 clearColorSwapped = LE_TO_LOCAL_32(engine.renderState.clearColor); + this->_clearColor6665.color = COLOR555TO6665(clearColorSwapped & 0x7FFF, (clearColorSwapped >> 16) & 0x1F); + + this->_clearAttributes.opaquePolyID = (clearColorSwapped >> 24) & 0x3F; + //special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display + //I am not sure whether it is right, though. previously this was cleared to 0, as a guess, + //but in spiderman2 some fires with polyid 0 try to render on top of the background + this->_clearAttributes.translucentPolyID = kUnsetTranslucentPolyID; + this->_clearAttributes.depth = engine.renderState.clearDepth; + this->_clearAttributes.stencil = 0; + this->_clearAttributes.isTranslucentPoly = 0; + this->_clearAttributes.polyFacing = PolyFacing_Unwritten; + this->_clearAttributes.isFogged = BIT15(clearColorSwapped); + error = this->BeginRender(engine); if (error != RENDER3DERROR_NOERR) { @@ -772,21 +773,6 @@ Render3DError Render3D_SSE2::ClearFramebuffer(const GFX3D_State &renderState) { Render3DError error = RENDER3DERROR_NOERR; - FragmentColor clearColor6665; - clearColor6665.color = COLOR555TO6665(renderState.clearColor & 0x7FFF, (renderState.clearColor >> 16) & 0x1F); - - FragmentAttributes clearFragment; - clearFragment.opaquePolyID = (renderState.clearColor >> 24) & 0x3F; - //special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display - //I am not sure whether it is right, though. previously this was cleared to 0, as a guess, - //but in spiderman2 some fires with polyid 0 try to render on top of the background - clearFragment.translucentPolyID = kUnsetTranslucentPolyID; - clearFragment.depth = renderState.clearDepth; - clearFragment.stencil = 0; - clearFragment.isTranslucentPoly = 0; - clearFragment.polyFacing = PolyFacing_Unwritten; - clearFragment.isFogged = BIT15(renderState.clearColor); - if (renderState.enableClearImage) { //the lion, the witch, and the wardrobe (thats book 1, suck it you new-school numberers) @@ -797,7 +783,7 @@ Render3DError Render3D_SSE2::ClearFramebuffer(const GFX3D_State &renderState) const u8 xScroll = scrollBits & 0xFF; const u8 yScroll = (scrollBits >> 8) & 0xFF; - const __m128i opaquePolyID_vec128 = _mm_set1_epi8(clearFragment.opaquePolyID); + const __m128i opaquePolyID_vec128 = _mm_set1_epi8(this->_clearAttributes.opaquePolyID); const __m128i calcDepthConstants = _mm_set1_epi32(0x01FF0200); if (xScroll == 0 && yScroll == 0) @@ -811,18 +797,19 @@ Render3DError Render3D_SSE2::ClearFramebuffer(const GFX3D_State &renderState) // Write the depth values to the depth buffer using the following formula from GBATEK. // 15-bit to 24-bit depth formula from http://problemkaputt.de/gbatek.htm#ds3drearplane // D24 = (D15 * 0x0200) + (((D15 + 1) >> 15) * 0x01FF); + // + // For now, let's forget GBATEK (which could be wrong) and try using a simpified formula: + // D24 = (D15 * 0x0200) + 0x01FF; const __m128i clearDepthLo = _mm_load_si128((__m128i *)(clearDepthBuffer + i + 0)); const __m128i clearDepthHi = _mm_load_si128((__m128i *)(clearDepthBuffer + i + 8)); const __m128i clearDepthValueLo = _mm_and_si128(clearDepthLo, _mm_set1_epi16(0x7FFF)); const __m128i clearDepthValueHi = _mm_and_si128(clearDepthHi, _mm_set1_epi16(0x7FFF)); - const __m128i highestDepthBitLo = _mm_srli_epi16( _mm_adds_epu16(clearDepthValueLo, _mm_set1_epi16(1)), 15); - const __m128i highestDepthBitHi = _mm_srli_epi16( _mm_adds_epu16(clearDepthValueHi, _mm_set1_epi16(1)), 15); - __m128i calcDepth0 = _mm_unpacklo_epi16(clearDepthValueLo, highestDepthBitLo); - __m128i calcDepth1 = _mm_unpackhi_epi16(clearDepthValueLo, highestDepthBitLo); - __m128i calcDepth2 = _mm_unpacklo_epi16(clearDepthValueHi, highestDepthBitHi); - __m128i calcDepth3 = _mm_unpackhi_epi16(clearDepthValueHi, highestDepthBitHi); + __m128i calcDepth0 = _mm_unpacklo_epi16(clearDepthValueLo, _mm_set1_epi16(1)); + __m128i calcDepth1 = _mm_unpackhi_epi16(clearDepthValueLo, _mm_set1_epi16(1)); + __m128i calcDepth2 = _mm_unpacklo_epi16(clearDepthValueHi, _mm_set1_epi16(1)); + __m128i calcDepth3 = _mm_unpackhi_epi16(clearDepthValueHi, _mm_set1_epi16(1)); calcDepth0 = _mm_madd_epi16(calcDepth0, calcDepthConstants); calcDepth1 = _mm_madd_epi16(calcDepth1, calcDepthConstants); @@ -948,22 +935,22 @@ Render3DError Render3D_SSE2::ClearFramebuffer(const GFX3D_State &renderState) if (!isClearColorBlank && !isClearDepthBlank) { - this->_ClearImageScrolledLoop(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, clearFragment.opaquePolyID, + this->_ClearImageScrolledLoop(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, this->_clearAttributes.opaquePolyID, this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); } else if (isClearColorBlank) { - this->_ClearImageScrolledLoop< true, false>(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, clearFragment.opaquePolyID, + this->_ClearImageScrolledLoop< true, false>(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, this->_clearAttributes.opaquePolyID, this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); } else if (isClearDepthBlank) { - this->_ClearImageScrolledLoop(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, clearFragment.opaquePolyID, + this->_ClearImageScrolledLoop(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, this->_clearAttributes.opaquePolyID, this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); } else { - this->_ClearImageScrolledLoop< true, true>(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, clearFragment.opaquePolyID, + this->_ClearImageScrolledLoop< true, true>(xScroll, yScroll, clearColorBuffer, clearDepthBuffer, this->_clearAttributes.opaquePolyID, this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); } } @@ -971,12 +958,12 @@ Render3DError Render3D_SSE2::ClearFramebuffer(const GFX3D_State &renderState) error = this->ClearUsingImage(this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer); if (error != RENDER3DERROR_NOERR) { - error = this->ClearUsingValues(clearColor6665, clearFragment); + error = this->ClearUsingValues(this->_clearColor6665, this->_clearAttributes); } } else { - error = this->ClearUsingValues(clearColor6665, clearFragment); + error = this->ClearUsingValues(this->_clearColor6665, this->_clearAttributes); } return error; diff --git a/desmume/src/render3D.h b/desmume/src/render3D.h index f9464c95f..05319e780 100644 --- a/desmume/src/render3D.h +++ b/desmume/src/render3D.h @@ -157,6 +157,9 @@ protected: size_t _framebufferColorSizeBytes; FragmentColor *_framebufferColor; + FragmentColor _clearColor6665; + FragmentAttributes _clearAttributes; + NDSColorFormat _internalRenderingFormat; NDSColorFormat _outputFormat; bool _renderNeedsFinish;