diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 56b12ee31..33d4d0fb2 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -579,7 +579,7 @@ static void OGLGetDriverVersion(const char *oglVersionString, } } -static void texDeleteCallback(TexCacheItem *item) +void texDeleteCallback(TexCacheItem *item) { _OGLRenderer->DeleteTexture(item); } @@ -1196,6 +1196,36 @@ Render3DError OpenGLRenderer_1_2::InitGeometryProgramBindings() return OGLERROR_NOERR; } +Render3DError OpenGLRenderer_1_2::InitGeometryProgramShaderLocations() +{ + OGLRenderRef &OGLRef = *this->ref; + + // Set up shader uniforms + OGLRef.uniformTexRenderObject = glGetUniformLocation(OGLRef.programGeometryID, "texRenderObject"); + OGLRef.uniformTexToonTable = glGetUniformLocation(OGLRef.programGeometryID, "texToonTable"); + glUniform1i(OGLRef.uniformTexRenderObject, 0); + glUniform1i(OGLRef.uniformTexToonTable, OGLTextureUnitID_ToonTable); + + OGLRef.uniformStateToonShadingMode = glGetUniformLocation(OGLRef.programGeometryID, "stateToonShadingMode"); + OGLRef.uniformStateEnableAlphaTest = glGetUniformLocation(OGLRef.programGeometryID, "stateEnableAlphaTest"); + OGLRef.uniformStateEnableAntialiasing = glGetUniformLocation(OGLRef.programGeometryID, "stateEnableAntialiasing"); + OGLRef.uniformStateEnableEdgeMarking = glGetUniformLocation(OGLRef.programGeometryID, "stateEnableEdgeMarking"); + OGLRef.uniformStateUseWDepth = glGetUniformLocation(OGLRef.programGeometryID, "stateUseWDepth"); + OGLRef.uniformStateAlphaTestRef = glGetUniformLocation(OGLRef.programGeometryID, "stateAlphaTestRef"); + + OGLRef.uniformPolyTexScale = glGetUniformLocation(OGLRef.programGeometryID, "polyTexScale"); + OGLRef.uniformPolyMode = glGetUniformLocation(OGLRef.programGeometryID, "polyMode"); + OGLRef.uniformPolyEnableDepthWrite = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableDepthWrite"); + OGLRef.uniformPolySetNewDepthForTranslucent = glGetUniformLocation(OGLRef.programGeometryID, "polySetNewDepthForTranslucent"); + OGLRef.uniformPolyAlpha = glGetUniformLocation(OGLRef.programGeometryID, "polyAlpha"); + OGLRef.uniformPolyID = glGetUniformLocation(OGLRef.programGeometryID, "polyID"); + + OGLRef.uniformPolyEnableTexture = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableTexture"); + OGLRef.uniformPolyEnableFog = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableFog"); + + return OGLERROR_NOERR; +} + Render3DError OpenGLRenderer_1_2::InitGeometryProgram(const std::string &vertexShaderProgram, const std::string &fragmentShaderProgram) { OGLRenderRef &OGLRef = *this->ref; @@ -1265,26 +1295,7 @@ Render3DError OpenGLRenderer_1_2::InitGeometryProgram(const std::string &vertexS glValidateProgram(OGLRef.programGeometryID); glUseProgram(OGLRef.programGeometryID); - // Set up shader uniforms - OGLRef.uniformTexRenderObject = glGetUniformLocation(OGLRef.programGeometryID, "texRenderObject"); - OGLRef.uniformTexToonTable = glGetUniformLocation(OGLRef.programGeometryID, "texToonTable"); - - OGLRef.uniformStateToonShadingMode = glGetUniformLocation(OGLRef.programGeometryID, "stateToonShadingMode"); - OGLRef.uniformStateEnableAlphaTest = glGetUniformLocation(OGLRef.programGeometryID, "stateEnableAlphaTest"); - OGLRef.uniformStateEnableAntialiasing = glGetUniformLocation(OGLRef.programGeometryID, "stateEnableAntialiasing"); - OGLRef.uniformStateEnableEdgeMarking = glGetUniformLocation(OGLRef.programGeometryID, "stateEnableEdgeMarking"); - OGLRef.uniformStateUseWDepth = glGetUniformLocation(OGLRef.programGeometryID, "stateUseWDepth"); - OGLRef.uniformStateAlphaTestRef = glGetUniformLocation(OGLRef.programGeometryID, "stateAlphaTestRef"); - - OGLRef.uniformPolyTexScale = glGetUniformLocation(OGLRef.programGeometryID, "polyTexScale"); - OGLRef.uniformPolyMode = glGetUniformLocation(OGLRef.programGeometryID, "polyMode"); - OGLRef.uniformPolyEnableDepthWrite = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableDepthWrite"); - OGLRef.uniformPolySetNewDepthForTranslucent = glGetUniformLocation(OGLRef.programGeometryID, "polySetNewDepthForTranslucent"); - OGLRef.uniformPolyAlpha = glGetUniformLocation(OGLRef.programGeometryID, "polyAlpha"); - OGLRef.uniformPolyID = glGetUniformLocation(OGLRef.programGeometryID, "polyID"); - - OGLRef.uniformPolyEnableTexture = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableTexture"); - OGLRef.uniformPolyEnableFog = glGetUniformLocation(OGLRef.programGeometryID, "polyEnableFog"); + this->InitGeometryProgramShaderLocations(); INFO("OpenGL: Successfully created shaders.\n"); @@ -1669,6 +1680,11 @@ Render3DError OpenGLRenderer_1_2::InitEdgeMarkProgramBindings() return OGLERROR_FEATURE_UNSUPPORTED; } +Render3DError OpenGLRenderer_1_2::InitEdgeMarkProgramShaderLocations() +{ + return OGLERROR_FEATURE_UNSUPPORTED; +} + Render3DError OpenGLRenderer_1_2::InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader) { return OGLERROR_FEATURE_UNSUPPORTED; @@ -1679,6 +1695,11 @@ Render3DError OpenGLRenderer_1_2::InitFogProgramBindings() return OGLERROR_FEATURE_UNSUPPORTED; } +Render3DError OpenGLRenderer_1_2::InitFogProgramShaderLocations() +{ + return OGLERROR_FEATURE_UNSUPPORTED; +} + Render3DError OpenGLRenderer_1_2::DestroyPostprocessingPrograms() { return OGLERROR_FEATURE_UNSUPPORTED; @@ -2066,8 +2087,6 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine) glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE); glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]); - glUniform1i(OGLRef.uniformTexRenderObject, 0); - glUniform1i(OGLRef.uniformTexToonTable, OGLTextureUnitID_ToonTable); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); @@ -2123,11 +2142,11 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, this->SetupVertices(vertList, polyList, indexList, OGLRef.vertIndexBuffer, &vertIndexBufferCount); this->EnableVertexAttributes(vertList, OGLRef.vertIndexBuffer, vertIndexBufferCount); - const POLY *firstPoly = &polyList->list[indexList->list[0]]; - u32 lastPolyAttr = firstPoly->polyAttr; - u32 lastTexParams = firstPoly->texParam; - u32 lastTexPalette = firstPoly->texPalette; - u32 lastViewport = firstPoly->viewport; + const POLY &firstPoly = polyList->list[indexList->list[0]]; + u32 lastPolyAttr = firstPoly.polyAttr; + u32 lastTexParams = firstPoly.texParam; + u32 lastTexPalette = firstPoly.texPalette; + u32 lastViewport = firstPoly.viewport; this->SetupPolygon(firstPoly); this->SetupTexture(firstPoly, renderState.enableTexturing); @@ -2137,30 +2156,31 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, GLushort *indexBufferPtr = (this->isVBOSupported) ? 0 : OGLRef.vertIndexBuffer; // Enumerate through all polygons and render - for(size_t i = 0; i < polyCount; i++) + for (size_t i = 0; i < polyCount; i++) { - const POLY *poly = &polyList->list[indexList->list[i]]; + const POLY &thePoly = polyList->list[indexList->list[i]]; + this->SetPolygonIndex(i); // Set up the polygon if it changed - if(lastPolyAttr != poly->polyAttr) + if (lastPolyAttr != thePoly.polyAttr) { - lastPolyAttr = poly->polyAttr; - this->SetupPolygon(poly); + lastPolyAttr = thePoly.polyAttr; + this->SetupPolygon(thePoly); } // Set up the texture if it changed - if(lastTexParams != poly->texParam || lastTexPalette != poly->texPalette) + if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette) { - lastTexParams = poly->texParam; - lastTexPalette = poly->texPalette; - this->SetupTexture(poly, renderState.enableTexturing); + lastTexParams = thePoly.texParam; + lastTexPalette = thePoly.texPalette; + this->SetupTexture(thePoly, renderState.enableTexturing); } // Set up the viewport if it changed - if(lastViewport != poly->viewport) + if (lastViewport != thePoly.viewport) { - lastViewport = poly->viewport; - this->SetupViewport(poly->viewport); + lastViewport = thePoly.viewport; + this->SetupViewport(thePoly.viewport); } // In wireframe mode, redefine all primitives as GL_LINE_LOOP rather than @@ -2168,10 +2188,10 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, // drawing more accurate this way, but it also allows GFX3D_QUADS and // GFX3D_QUAD_STRIP primitives to properly draw as wireframe without the // extra diagonal line. - const GLenum polyPrimitive = (!poly->isWireframe()) ? oglPrimitiveType[poly->vtxFormat] : GL_LINE_LOOP; + const GLenum polyPrimitive = (!thePoly.isWireframe()) ? oglPrimitiveType[thePoly.vtxFormat] : GL_LINE_LOOP; // Increment the vertex count - vertIndexCount += indexIncrementLUT[poly->vtxFormat]; + vertIndexCount += indexIncrementLUT[thePoly.vtxFormat]; // Look ahead to the next polygon to see if we can simply buffer the indices // instead of uploading them now. We can buffer if all polygon states remain @@ -2314,10 +2334,15 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const FragmentColor &clearCol return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY *thePoly) +void OpenGLRenderer_1_2::SetPolygonIndex(const size_t index) +{ + this->_currentPolyIndex = index; +} + +Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly) { OGLRenderRef &OGLRef = *this->ref; - const PolygonAttributes attr = thePoly->getAttributes(); + const PolygonAttributes attr = thePoly.getAttributes(); // Set up polygon attributes if (this->isShaderSupported) @@ -2414,13 +2439,13 @@ Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY *thePoly) return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY *thePoly, bool enableTexturing) +Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableTexturing) { OGLRenderRef &OGLRef = *this->ref; - const PolygonTexParams params = thePoly->getTexParams(); + const PolygonTexParams params = thePoly.getTexParams(); // Check if we need to use textures - if (thePoly->texParam == 0 || params.texFormat == TEXMODE_NONE || !enableTexturing) + if (thePoly.texParam == 0 || params.texFormat == TEXMODE_NONE || !enableTexturing) { if (this->isShaderSupported) { @@ -2445,14 +2470,14 @@ Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY *thePoly, bool enableT } // texCacheUnit.TexCache_SetTexture(format, texpal); - TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly->texParam, thePoly->texPalette); + TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette); if(newTexture != this->currTexture) { this->currTexture = newTexture; //has the ogl renderer initialized the texture? if(!this->currTexture->deleteCallback) { - this->currTexture->deleteCallback = texDeleteCallback; + this->currTexture->deleteCallback = &texDeleteCallback; if(OGLRef.freeTextureIDs.empty()) { @@ -2517,27 +2542,7 @@ Render3DError OpenGLRenderer_1_2::Reset() memset(this->GPU_screen3D[i], 0, sizeof(this->GPU_screen3D[i])); } - if(this->isShaderSupported) - { - glUseProgram(OGLRef.programGeometryID); - glUniform1i(OGLRef.uniformStateToonShadingMode, 0); - glUniform1i(OGLRef.uniformStateEnableAlphaTest, GL_TRUE); - glUniform1i(OGLRef.uniformStateEnableAntialiasing, GL_FALSE); - glUniform1i(OGLRef.uniformStateEnableEdgeMarking, GL_TRUE); - glUniform1i(OGLRef.uniformStateUseWDepth, GL_FALSE); - glUniform1f(OGLRef.uniformStateAlphaTestRef, 0.0f); - - glUniform2f(OGLRef.uniformPolyTexScale, 1.0f, 1.0f); - glUniform1i(OGLRef.uniformPolyMode, 0); - glUniform1i(OGLRef.uniformPolyEnableDepthWrite, GL_TRUE); - glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, GL_TRUE); - glUniform1f(OGLRef.uniformPolyAlpha, 1.0f); - glUniform1i(OGLRef.uniformPolyID, 0); - - glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE); - glUniform1i(OGLRef.uniformPolyEnableFog, GL_FALSE); - } - else + if(!this->isShaderSupported) { glEnable(GL_NORMALIZE); glEnable(GL_TEXTURE_1D); @@ -2552,6 +2557,7 @@ Render3DError OpenGLRenderer_1_2::Reset() memset(OGLRef.vertIndexBuffer, 0, OGLRENDER_VERT_INDEX_BUFFER_COUNT * sizeof(GLushort)); this->currTexture = NULL; this->doubleBufferIndex = 0; + this->_currentPolyIndex = 0; return OGLERROR_NOERR; } @@ -3050,6 +3056,21 @@ Render3DError OpenGLRenderer_2_0::InitEdgeMarkProgramBindings() return OGLERROR_NOERR; } +Render3DError OpenGLRenderer_2_0::InitEdgeMarkProgramShaderLocations() +{ + OGLRenderRef &OGLRef = *this->ref; + + OGLRef.uniformTexGDepth_EdgeMark = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth"); + OGLRef.uniformTexGPolyID_EdgeMark = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID"); + glUniform1i(OGLRef.uniformTexGDepth_EdgeMark, OGLTextureUnitID_GDepth); + glUniform1i(OGLRef.uniformTexGPolyID_EdgeMark, OGLTextureUnitID_GPolyID); + + OGLRef.uniformFramebufferSize = glGetUniformLocation(OGLRef.programEdgeMarkID, "framebufferSize"); + OGLRef.uniformStateEdgeColor = glGetUniformLocation(OGLRef.programEdgeMarkID, "stateEdgeColor"); + + return OGLERROR_NOERR; +} + Render3DError OpenGLRenderer_2_0::InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader) { Render3DError error = OGLERROR_NOERR; @@ -3130,13 +3151,7 @@ Render3DError OpenGLRenderer_2_0::InitPostprocessingPrograms(const std::string & glValidateProgram(OGLRef.programEdgeMarkID); glUseProgram(OGLRef.programEdgeMarkID); - // Set up shader uniforms - OGLRef.uniformTexGColor_EdgeMark = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragColor"); - OGLRef.uniformTexGDepth_EdgeMark = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth"); - OGLRef.uniformTexGPolyID_EdgeMark = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID"); - - OGLRef.uniformFramebufferSize = glGetUniformLocation(OGLRef.programEdgeMarkID, "framebufferSize"); - OGLRef.uniformStateEdgeColor = glGetUniformLocation(OGLRef.programEdgeMarkID, "stateEdgeColor"); + this->InitEdgeMarkProgramShaderLocations(); // ------------------------------------------ @@ -3215,16 +3230,7 @@ Render3DError OpenGLRenderer_2_0::InitPostprocessingPrograms(const std::string & glValidateProgram(OGLRef.programFogID); glUseProgram(OGLRef.programFogID); - // Set up shader uniforms - OGLRef.uniformTexGColor_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFragColor"); - OGLRef.uniformTexGDepth_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFragDepth"); - OGLRef.uniformTexGFog_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFogAttributes"); - - OGLRef.uniformStateEnableFogAlphaOnly = glGetUniformLocation(OGLRef.programFogID, "stateEnableFogAlphaOnly"); - OGLRef.uniformStateFogColor = glGetUniformLocation(OGLRef.programFogID, "stateFogColor"); - OGLRef.uniformStateFogDensity = glGetUniformLocation(OGLRef.programFogID, "stateFogDensity"); - OGLRef.uniformStateFogOffset = glGetUniformLocation(OGLRef.programFogID, "stateFogOffset"); - OGLRef.uniformStateFogStep = glGetUniformLocation(OGLRef.programFogID, "stateFogStep"); + this->InitFogProgramShaderLocations(); glUseProgram(OGLRef.programGeometryID); INFO("OpenGL: Successfully created postprocess shaders.\n"); @@ -3241,6 +3247,26 @@ Render3DError OpenGLRenderer_2_0::InitFogProgramBindings() return OGLERROR_NOERR; } +Render3DError OpenGLRenderer_2_0::InitFogProgramShaderLocations() +{ + OGLRenderRef &OGLRef = *this->ref; + + OGLRef.uniformTexGColor_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFragColor"); + OGLRef.uniformTexGDepth_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFragDepth"); + OGLRef.uniformTexGFog_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFogAttributes"); + glUniform1i(OGLRef.uniformTexGColor_Fog, OGLTextureUnitID_GColor); + glUniform1i(OGLRef.uniformTexGDepth_Fog, OGLTextureUnitID_GDepth); + glUniform1i(OGLRef.uniformTexGFog_Fog, OGLTextureUnitID_FogAttr); + + OGLRef.uniformStateEnableFogAlphaOnly = glGetUniformLocation(OGLRef.programFogID, "stateEnableFogAlphaOnly"); + OGLRef.uniformStateFogColor = glGetUniformLocation(OGLRef.programFogID, "stateFogColor"); + OGLRef.uniformStateFogDensity = glGetUniformLocation(OGLRef.programFogID, "stateFogDensity"); + OGLRef.uniformStateFogOffset = glGetUniformLocation(OGLRef.programFogID, "stateFogOffset"); + OGLRef.uniformStateFogStep = glGetUniformLocation(OGLRef.programFogID, "stateFogStep"); + + return OGLERROR_NOERR; +} + Render3DError OpenGLRenderer_2_0::DestroyPostprocessingPrograms() { OGLRenderRef &OGLRef = *this->ref; @@ -3366,8 +3392,6 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine) glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE); glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE); glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]); - glUniform1i(OGLRef.uniformTexRenderObject, 0); - glUniform1i(OGLRef.uniformTexToonTable, OGLTextureUnitID_ToonTable); glEnable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); @@ -3427,8 +3451,6 @@ Render3DError OpenGLRenderer_2_0::RenderEdgeMarking(const u16 *colorTable, const glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glUseProgram(OGLRef.programEdgeMarkID); - glUniform1i(OGLRef.uniformTexGDepth_EdgeMark, OGLTextureUnitID_GDepth); - glUniform1i(OGLRef.uniformTexGPolyID_EdgeMark, OGLTextureUnitID_GPolyID); glUniform2f(OGLRef.uniformFramebufferSize, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor); @@ -3498,9 +3520,6 @@ Render3DError OpenGLRenderer_2_0::RenderFog(const u8 *densityTable, const u32 co glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); glUseProgram(OGLRef.programFogID); - glUniform1i(OGLRef.uniformTexGColor_Fog, OGLTextureUnitID_GColor); - glUniform1i(OGLRef.uniformTexGDepth_Fog, OGLTextureUnitID_GDepth); - glUniform1i(OGLRef.uniformTexGFog_Fog, OGLTextureUnitID_FogAttr); glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, (alphaOnly) ? GL_TRUE : GL_FALSE); glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]); glUniform1f(OGLRef.uniformStateFogOffset, oglOffset); @@ -3550,10 +3569,10 @@ Render3DError OpenGLRenderer_2_0::RenderFog(const u8 *densityTable, const u32 co return OGLERROR_NOERR; } -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 polygon attributes glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode); @@ -3637,13 +3656,13 @@ Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY *thePoly) return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY *thePoly, bool enableTexturing) +Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableTexturing) { OGLRenderRef &OGLRef = *this->ref; - const PolygonTexParams params = thePoly->getTexParams(); + const PolygonTexParams params = thePoly.getTexParams(); // Check if we need to use textures - if (thePoly->texParam == 0 || params.texFormat == TEXMODE_NONE || !enableTexturing) + if (thePoly.texParam == 0 || params.texFormat == TEXMODE_NONE || !enableTexturing) { glUniform1i(OGLRef.uniformPolyEnableTexture, GL_FALSE); return OGLERROR_NOERR; @@ -3652,14 +3671,14 @@ Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY *thePoly, bool enableT glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE); // texCacheUnit.TexCache_SetTexture(format, texpal); - TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly->texParam, thePoly->texPalette); + TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette); if(newTexture != this->currTexture) { this->currTexture = newTexture; //has the ogl renderer initialized the texture? if(!this->currTexture->deleteCallback) { - this->currTexture->deleteCallback = texDeleteCallback; + this->currTexture->deleteCallback = &texDeleteCallback; if(OGLRef.freeTextureIDs.empty()) { diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index 0b785ad63..92be910fe 100644 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -243,6 +243,9 @@ EXTERNOGLEXT(PFNGLBUFFERSUBDATAPROC, glBufferSubData) // Core in v1.5 EXTERNOGLEXT(PFNGLMAPBUFFERPROC, glMapBuffer) // Core in v1.5 EXTERNOGLEXT(PFNGLUNMAPBUFFERPROC, glUnmapBuffer) // Core in v1.5 +// Buffer Objects +EXTERNOGLEXT(PFNGLMAPBUFFERRANGEPROC, glMapBufferRange) // Core in v3.0 + // FBO EXTERNOGLEXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) // Core in v3.0 EXTERNOGLEXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) // Core in v3.0 @@ -260,6 +263,15 @@ EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) // Core in v3. EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample) // Core in v3.0 EXTERNOGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Core in v3.0 +// UBO +EXTERNOGLEXT(PFNGLGETUNIFORMBLOCKINDEXPROC, glGetUniformBlockIndex) // Core in v3.1 +EXTERNOGLEXT(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding) // Core in v3.1 +EXTERNOGLEXT(PFNGLBINDBUFFERBASEPROC, glBindBufferBase) // Core in v3.0 +EXTERNOGLEXT(PFNGLGETACTIVEUNIFORMBLOCKIVPROC, glGetActiveUniformBlockiv) // Core in v3.1 + +// TBO +EXTERNOGLEXT(PFNGLTEXBUFFERPROC, glTexBuffer) // Core in v3.1 + #endif // OGLRENDER_3_2_H // Define the minimum required OpenGL version for the driver to support @@ -285,7 +297,12 @@ enum OGLTextureUnitID OGLTextureUnitID_GDepth, OGLTextureUnitID_GPolyID, OGLTextureUnitID_FogAttr, - OGLTextureUnitID_TranslucentFogAttr + OGLTextureUnitID_PolyStates +}; + +enum OGLBindingPointID +{ + OGLBindingPointID_RenderStates = 0 }; enum OGLErrorCode @@ -307,6 +324,58 @@ enum OGLErrorCode OGLERROR_FBO_CREATE_ERROR }; +union GLvec2 +{ + struct { GLfloat x, y; }; + GLfloat v[2]; +}; + +union GLvec4 +{ + struct { GLfloat r, g, b, a; }; + struct { GLfloat x, y, z, w; }; + GLfloat v[4]; +}; + +struct OGLRenderStates +{ + GLvec2 framebufferSize; + GLint toonShadingMode; + GLuint enableAlphaTest; + GLuint enableAntialiasing; + GLuint enableEdgeMarking; + GLuint enableFogAlphaOnly; + GLuint useWDepth; + GLfloat alphaTestRef; + GLfloat fogOffset; + GLfloat fogStep; + GLfloat pad_0; // 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]; +}; + +struct OGLPolyStates +{ + union + { + struct { GLubyte enableTexture, enableFog, enableDepthWrite, setNewDepthForTranslucent; }; + GLubyte flags[4]; + }; + + union + { + struct { GLubyte polyAlpha, polyMode, polyID, valuesPad[1]; }; + GLubyte values[4]; + }; + + union + { + struct { GLubyte texSizeS, texSizeT, texParamPad[2]; }; + GLubyte texParam[4]; + }; +}; + struct OGLRenderRef { // OpenGL Feature Support @@ -321,6 +390,11 @@ struct OGLRenderRef // PBO GLuint pboRenderDataID[2]; + // UBO / TBO + GLuint uboRenderStatesID; + GLuint tboPolyStatesID; + GLuint texPolyStatesID; + // FBO GLuint texGColorID; GLuint texGDepthID; @@ -353,9 +427,13 @@ struct OGLRenderRef GLuint programEdgeMarkID; GLuint programFogID; + GLuint uniformBlockRenderStatesGeometry; + GLuint uniformBlockRenderStatesEdgeMark; + GLuint uniformBlockRenderStatesFog; + GLuint uniformTexBufferPolyStates; + GLuint uniformTexRenderObject; GLuint uniformTexToonTable; - GLuint uniformTexGColor_EdgeMark; GLuint uniformTexGDepth_EdgeMark; GLuint uniformTexGPolyID_EdgeMark; GLuint uniformTexGColor_Fog; @@ -386,6 +464,8 @@ struct OGLRenderRef GLint uniformPolyEnableTexture; GLint uniformPolyEnableFog; + GLint uniformPolyStateIndex; + GLuint texToonTableID; // VAO @@ -417,6 +497,8 @@ extern CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32]; extern const GLfloat PostprocessVtxBuffer[16];; extern const GLubyte PostprocessElementBuffer[6]; +extern void texDeleteCallback(TexCacheItem *item); + //This is called by OGLRender whenever it initializes. //Platforms, please be sure to set this up. //return true if you successfully init. @@ -468,6 +550,7 @@ protected: CACHE_ALIGN u32 GPU_screen3D[2][GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT * sizeof(u32)]; bool gpuScreen3DHasNewData[2]; size_t doubleBufferIndex; + size_t _currentPolyIndex; // OpenGL-specific methods virtual Render3DError CreateVBOs() = 0; @@ -486,12 +569,15 @@ protected: virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet) = 0; virtual Render3DError InitTables() = 0; virtual Render3DError InitEdgeMarkProgramBindings() = 0; + virtual Render3DError InitEdgeMarkProgramShaderLocations() = 0; virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader) = 0; virtual Render3DError InitFogProgramBindings() = 0; + virtual Render3DError InitFogProgramShaderLocations() = 0; virtual Render3DError DestroyPostprocessingPrograms() = 0; virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram) = 0; virtual Render3DError InitGeometryProgramBindings() = 0; + virtual Render3DError InitGeometryProgramShaderLocations() = 0; virtual Render3DError CreateToonTable() = 0; virtual Render3DError DestroyToonTable() = 0; virtual Render3DError UploadToonTable(const u16 *toonTableBuffer) = 0; @@ -506,6 +592,8 @@ protected: virtual Render3DError DownsampleFBO() = 0; virtual Render3DError ReadBackPixels() = 0; + virtual void SetPolygonIndex(const size_t index) = 0; + public: OpenGLRenderer(); virtual ~OpenGLRenderer() {}; @@ -542,10 +630,13 @@ protected: virtual Render3DError InitGeometryProgram(const std::string &vertexShaderProgram, const std::string &fragmentShaderProgram); virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram); virtual Render3DError InitGeometryProgramBindings(); + virtual Render3DError InitGeometryProgramShaderLocations(); virtual void DestroyGeometryProgram(); virtual Render3DError InitEdgeMarkProgramBindings(); + virtual Render3DError InitEdgeMarkProgramShaderLocations(); virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader); virtual Render3DError InitFogProgramBindings(); + virtual Render3DError InitFogProgramShaderLocations(); virtual Render3DError DestroyPostprocessingPrograms(); virtual Render3DError CreateToonTable(); @@ -570,8 +661,9 @@ protected: virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const bool *__restrict fogBuffer, const u8 *__restrict polyIDBuffer); virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const; - virtual Render3DError SetupPolygon(const POLY *thePoly); - virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing); + virtual void SetPolygonIndex(const size_t index); + virtual Render3DError SetupPolygon(const POLY &thePoly); + virtual Render3DError SetupTexture(const POLY &thePoly, bool enableTexturing); virtual Render3DError SetupViewport(const u32 viewportValue); public: @@ -624,8 +716,10 @@ protected: virtual Render3DError InitExtensions(); virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet); virtual Render3DError InitEdgeMarkProgramBindings(); + virtual Render3DError InitEdgeMarkProgramShaderLocations(); virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader); virtual Render3DError InitFogProgramBindings(); + virtual Render3DError InitFogProgramShaderLocations(); virtual Render3DError DestroyPostprocessingPrograms(); virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount); @@ -636,8 +730,8 @@ protected: 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 SetupPolygon(const POLY *thePoly); - virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing); + virtual Render3DError SetupPolygon(const POLY &thePoly); + virtual Render3DError SetupTexture(const POLY &thePoly, bool enableTexturing); }; class OpenGLRenderer_2_1 : public OpenGLRenderer_2_0 diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index e18341c7e..5235fe721 100644 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -37,6 +37,9 @@ OGLEXT(PFNGLCLEARBUFFERFIPROC, glClearBufferfi) // Core in v3.0 // Shaders OGLEXT(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation) // Core in v3.0 +// Buffer Objects +OGLEXT(PFNGLMAPBUFFERRANGEPROC, glMapBufferRange) // Core in v3.0 + // FBO OGLEXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) // Core in v3.0 OGLEXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) // Core in v3.0 @@ -51,6 +54,15 @@ OGLEXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) // Core in v3.0 OGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample) // Core in v3.0 OGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Core in v3.0 +// UBO +OGLEXT(PFNGLGETUNIFORMBLOCKINDEXPROC, glGetUniformBlockIndex) // Core in v3.1 +OGLEXT(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding) // Core in v3.1 +OGLEXT(PFNGLBINDBUFFERBASEPROC, glBindBufferBase) // Core in v3.0 +OGLEXT(PFNGLGETACTIVEUNIFORMBLOCKIVPROC, glGetActiveUniformBlockiv) // Core in v3.1 + +// TBO +OGLEXT(PFNGLTEXBUFFERPROC, glTexBuffer) // Core in v3.1 + void OGLLoadEntryPoints_3_2() { // Basic Functions @@ -61,6 +73,9 @@ void OGLLoadEntryPoints_3_2() // Shaders INITOGLEXT(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation) + // Buffer Objects + INITOGLEXT(PFNGLMAPBUFFERRANGEPROC, glMapBufferRange) + // FBO INITOGLEXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) // Promote to core version INITOGLEXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) // Promote to core version @@ -74,6 +89,15 @@ void OGLLoadEntryPoints_3_2() INITOGLEXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) // Promote to core version INITOGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample) // Promote to core version INITOGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Promote to core version + + // UBO + OGLEXT(PFNGLGETUNIFORMBLOCKINDEXPROC, glGetUniformBlockIndex) + OGLEXT(PFNGLUNIFORMBLOCKBINDINGPROC, glUniformBlockBinding) + OGLEXT(PFNGLBINDBUFFERBASEPROC, glBindBufferBase) + OGLEXT(PFNGLGETACTIVEUNIFORMBLOCKIVPROC, glGetActiveUniformBlockiv) + + // TBO + OGLEXT(PFNGLTEXBUFFERPROC, glTexBuffer) } // Vertex shader for geometry, GLSL 1.50 @@ -84,15 +108,35 @@ static const char *GeometryVtxShader_150 = {"\ in vec2 inTexCoord0; \n\ in vec3 inColor; \n\ \n\ - uniform float polyAlpha; \n\ - uniform vec2 polyTexScale; \n\ + uniform usamplerBuffer PolyStates;\n\ + uniform int polyIndex;\n\ \n\ out vec4 vtxPosition; \n\ out vec2 vtxTexCoord; \n\ out vec4 vtxColor; \n\ + flat out uint polyEnableTexture;\n\ + flat out uint polyEnableFog;\n\ + flat out uint polyEnableDepthWrite;\n\ + flat out uint polySetNewDepthForTranslucent;\n\ + flat out uint polyMode;\n\ + flat out uint polyID;\n\ \n\ void main() \n\ { \n\ + uvec4 polyStateFlags = texelFetch(PolyStates, (polyIndex*3)+0);\n\ + uvec4 polyStateValues = texelFetch(PolyStates, (polyIndex*3)+1);\n\ + uvec4 polyStateTexParams = texelFetch(PolyStates, (polyIndex*3)+2);\n\ + \n\ + float polyAlpha = float(polyStateValues[0]) / 31.0;\n\ + vec2 polyTexScale = vec2(1.0 / float(8 << polyStateTexParams[0]), 1.0 / float(8 << polyStateTexParams[1]));\n\ + \n\ + polyEnableTexture = polyStateFlags[0];\n\ + polyEnableFog = polyStateFlags[1];\n\ + polyEnableDepthWrite = polyStateFlags[2];\n\ + polySetNewDepthForTranslucent = polyStateFlags[3];\n\ + polyMode = polyStateValues[1];\n\ + polyID = polyStateValues[2];\n\ + \n\ mat2 texScaleMtx = mat2( vec2(polyTexScale.x, 0.0), \n\ vec2( 0.0, polyTexScale.y)); \n\ \n\ @@ -111,24 +155,35 @@ static const char *GeometryFragShader_150 = {"\ in vec4 vtxPosition; \n\ in vec2 vtxTexCoord; \n\ in vec4 vtxColor; \n\ + flat in uint polyEnableTexture;\n\ + flat in uint polyEnableFog;\n\ + flat in uint polyEnableDepthWrite;\n\ + flat in uint polySetNewDepthForTranslucent;\n\ + flat in uint polyMode;\n\ + flat in uint polyID;\n\ + \n\ + layout (std140) uniform RenderStates\n\ + {\n\ + vec2 framebufferSize;\n\ + int toonShadingMode;\n\ + bool enableAlphaTest;\n\ + bool enableAntialiasing;\n\ + bool enableEdgeMarking;\n\ + bool enableFogAlphaOnly;\n\ + bool useWDepth;\n\ + float alphaTestRef;\n\ + float fogOffset;\n\ + float fogStep;\n\ + float pad_0;\n\ + vec4 fogColor;\n\ + float fogDensity[32];\n\ + vec4 edgeColor[8];\n\ + } state;\n\ \n\ uniform sampler2D texRenderObject; \n\ uniform sampler1D texToonTable; \n\ - \n\ - uniform int stateToonShadingMode; \n\ - uniform bool stateEnableAlphaTest; \n\ - uniform bool stateEnableAntialiasing;\n\ - uniform bool stateEnableEdgeMarking;\n\ - uniform bool stateUseWDepth; \n\ - uniform float stateAlphaTestRef; \n\ - \n\ - uniform int polyMode; \n\ - uniform bool polyEnableDepthWrite;\n\ - uniform bool polySetNewDepthForTranslucent;\n\ - uniform int polyID; \n\ - \n\ - uniform bool polyEnableTexture; \n\ - uniform bool polyEnableFog;\n\ + uniform usamplerBuffer PolyStates;\n\ + uniform int polyIndex;\n\ \n\ out vec4 outFragColor;\n\ out vec4 outFragDepth;\n\ @@ -144,39 +199,39 @@ static const char *GeometryFragShader_150 = {"\ \n\ void main() \n\ { \n\ - vec4 mainTexColor = (polyEnableTexture) ? texture(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0); \n\ + vec4 mainTexColor = bool(polyEnableTexture) ? texture(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0);\n\ vec4 newFragColor = mainTexColor * vtxColor; \n\ \n\ - if(polyMode == 1) \n\ + if (polyMode == 1u) \n\ { \n\ - newFragColor.rgb = (polyEnableTexture) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb; \n\ + newFragColor.rgb = bool(polyEnableTexture) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb;\n\ newFragColor.a = vtxColor.a; \n\ } \n\ - else if(polyMode == 2) \n\ + else if (polyMode == 2u) \n\ { \n\ vec3 toonColor = vec3(texture(texToonTable, vtxColor.r).rgb); \n\ - newFragColor.rgb = (stateToonShadingMode == 0) ? mainTexColor.rgb * toonColor.rgb : min((mainTexColor.rgb * vtxColor.rgb) + toonColor.rgb, 1.0); \n\ + newFragColor.rgb = (state.toonShadingMode == 0) ? mainTexColor.rgb * toonColor.rgb : min((mainTexColor.rgb * vtxColor.rgb) + toonColor.rgb, 1.0); \n\ } \n\ - else if(polyMode == 3) \n\ + else if (polyMode == 3u) \n\ { \n\ - if (polyID != 0) \n\ + if (polyID != 0u) \n\ { \n\ newFragColor = vtxColor; \n\ } \n\ } \n\ \n\ - if (newFragColor.a == 0.0 || (stateEnableAlphaTest && newFragColor.a < stateAlphaTestRef)) \n\ + if (newFragColor.a == 0.0 || (state.enableAlphaTest && newFragColor.a < state.alphaTestRef)) \n\ { \n\ discard; \n\ } \n\ \n\ float vertW = (vtxPosition.w == 0.0) ? 0.00000001 : vtxPosition.w; \n\ - float newFragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp((vtxPosition.z/vertW) * 0.5 + 0.5, 0.0, 1.0); \n\ + float newFragDepth = (state.useWDepth) ? vtxPosition.w/4096.0 : clamp((vtxPosition.z/vertW) * 0.5 + 0.5, 0.0, 1.0); \n\ \n\ outFragColor = newFragColor;\n\ - outFragDepth = vec4( packVec3FromFloat(newFragDepth), float(polyEnableDepthWrite && (newFragColor.a > 0.999 || polySetNewDepthForTranslucent)));\n\ + outFragDepth = vec4( packVec3FromFloat(newFragDepth), float(bool(polyEnableDepthWrite) && (newFragColor.a > 0.999 || bool(polySetNewDepthForTranslucent))));\n\ outPolyID = vec4(float(polyID)/63.0, 0.0, 0.0, float(newFragColor.a > 0.999));\n\ - outFogAttributes = vec4( float(polyEnableFog), 0.0, 0.0, float(newFragColor.a > 0.999 || !polyEnableFog));\n\ + outFogAttributes = vec4( float(polyEnableFog), 0.0, 0.0, float(newFragColor.a > 0.999 || !bool(polyEnableFog)));\n\ gl_FragDepth = newFragDepth;\n\ } \n\ "}; @@ -187,12 +242,29 @@ static const char *EdgeMarkVtxShader_150 = {"\ \n\ in vec2 inPosition;\n\ in vec2 inTexCoord0;\n\ - uniform vec2 framebufferSize;\n\ + layout (std140) uniform RenderStates\n\ + {\n\ + vec2 framebufferSize;\n\ + int toonShadingMode;\n\ + bool enableAlphaTest;\n\ + bool enableAntialiasing;\n\ + bool enableEdgeMarking;\n\ + bool enableFogAlphaOnly;\n\ + bool useWDepth;\n\ + float alphaTestRef;\n\ + float fogOffset;\n\ + float fogStep;\n\ + float pad_0;\n\ + vec4 fogColor;\n\ + float fogDensity[32];\n\ + vec4 edgeColor[8];\n\ + } state;\n\ + \n\ out vec2 texCoord[5];\n\ \n\ void main()\n\ {\n\ - vec2 texInvScale = vec2(1.0/framebufferSize.x, 1.0/framebufferSize.y);\n\ + vec2 texInvScale = vec2(1.0/state.framebufferSize.x, 1.0/state.framebufferSize.y);\n\ \n\ texCoord[0] = inTexCoord0; // Center\n\ texCoord[1] = inTexCoord0 + (vec2( 1.0, 0.0) * texInvScale); // Right\n\ @@ -210,9 +282,26 @@ static const char *EdgeMarkFragShader_150 = {"\ \n\ in vec2 texCoord[5];\n\ \n\ + layout (std140) uniform RenderStates\n\ + {\n\ + vec2 framebufferSize;\n\ + int toonShadingMode;\n\ + bool enableAlphaTest;\n\ + bool enableAntialiasing;\n\ + bool enableEdgeMarking;\n\ + bool enableFogAlphaOnly;\n\ + bool useWDepth;\n\ + float alphaTestRef;\n\ + float fogOffset;\n\ + float fogStep;\n\ + float pad_0;\n\ + vec4 fogColor;\n\ + float fogDensity[32];\n\ + vec4 edgeColor[8];\n\ + } state;\n\ + \n\ uniform sampler2D texInFragDepth;\n\ uniform sampler2D texInPolyID;\n\ - uniform vec4 stateEdgeColor[8];\n\ \n\ out vec4 outFragColor;\n\ \n\ @@ -245,18 +334,18 @@ static const char *EdgeMarkFragShader_150 = {"\ depth[3] = unpackFloatFromVec3(texture(texInFragDepth, texCoord[3]).rgb);\n\ depth[4] = unpackFloatFromVec3(texture(texInFragDepth, texCoord[4]).rgb);\n\ \n\ - vec4 edgeColor = vec4(0.0, 0.0, 0.0, 0.0);\n\ + vec4 newEdgeColor = vec4(0.0, 0.0, 0.0, 0.0);\n\ \n\ for (int i = 1; i < 5; i++)\n\ {\n\ if (polyID[0] != polyID[i] && depth[0] >= depth[i])\n\ {\n\ - edgeColor = stateEdgeColor[polyID[i]/8];\n\ + newEdgeColor = state.edgeColor[polyID[i]/8];\n\ break;\n\ }\n\ }\n\ \n\ - outFragColor = edgeColor;\n\ + outFragColor = newEdgeColor;\n\ }\n\ "}; @@ -281,14 +370,27 @@ static const char *FogFragShader_150 = {"\ \n\ in vec2 texCoord;\n\ \n\ + layout (std140) uniform RenderStates\n\ + {\n\ + vec2 framebufferSize;\n\ + int toonShadingMode;\n\ + bool enableAlphaTest;\n\ + bool enableAntialiasing;\n\ + bool enableEdgeMarking;\n\ + bool enableFogAlphaOnly;\n\ + bool useWDepth;\n\ + float alphaTestRef;\n\ + float fogOffset;\n\ + float fogStep;\n\ + float pad_0;\n\ + vec4 fogColor;\n\ + float fogDensity[32];\n\ + vec4 edgeColor[8];\n\ + } state;\n\ + \n\ uniform sampler2D texInFragColor;\n\ uniform sampler2D texInFragDepth;\n\ uniform sampler2D texInFogAttributes;\n\ - uniform bool stateEnableFogAlphaOnly;\n\ - uniform vec4 stateFogColor;\n\ - uniform float stateFogDensity[32];\n\ - uniform float stateFogOffset;\n\ - uniform float stateFogStep;\n\ \n\ out vec4 outFragColor;\n\ \n\ @@ -310,29 +412,29 @@ static const char *FogFragShader_150 = {"\ float inFragDepth = unpackFloatFromVec3(texture(texInFragDepth, texCoord).rgb);\n\ float fogMixWeight = 0.0;\n\ \n\ - if (inFragDepth <= min(stateFogOffset + stateFogStep, 1.0))\n\ + if (inFragDepth <= min(state.fogOffset + state.fogStep, 1.0))\n\ {\n\ - fogMixWeight = stateFogDensity[0];\n\ + fogMixWeight = state.fogDensity[0];\n\ }\n\ - else if (inFragDepth >= min(stateFogOffset + (stateFogStep*32.0), 1.0))\n\ + else if (inFragDepth >= min(state.fogOffset + (state.fogStep*32.0), 1.0))\n\ {\n\ - fogMixWeight = stateFogDensity[31];\n\ + fogMixWeight = state.fogDensity[31];\n\ }\n\ else\n\ {\n\ for (int i = 1; i < 32; i++)\n\ {\n\ - float currentFogStep = min(stateFogOffset + (stateFogStep * float(i+1)), 1.0);\n\ + float currentFogStep = min(state.fogOffset + (state.fogStep * float(i+1)), 1.0);\n\ if (inFragDepth <= currentFogStep)\n\ {\n\ - float previousFogStep = min(stateFogOffset + (stateFogStep * float(i)), 1.0);\n\ - fogMixWeight = mix(stateFogDensity[i-1], stateFogDensity[i], (inFragDepth - previousFogStep) / (currentFogStep - previousFogStep));\n\ + float previousFogStep = min(state.fogOffset + (state.fogStep * float(i)), 1.0);\n\ + fogMixWeight = mix(state.fogDensity[i-1], state.fogDensity[i], (inFragDepth - previousFogStep) / (currentFogStep - previousFogStep));\n\ break;\n\ }\n\ }\n\ }\n\ \n\ - newFoggedColor = mix(inFragColor, (stateEnableFogAlphaOnly) ? vec4(inFragColor.rgb, stateFogColor.a) : stateFogColor, fogMixWeight);\n\ + newFoggedColor = mix(inFragColor, (state.enableFogAlphaOnly) ? vec4(inFragColor.rgb, state.fogColor.a) : state.fogColor, fogMixWeight);\n\ }\n\ \n\ outFragColor = newFoggedColor;\n\ @@ -447,6 +549,21 @@ Render3DError OpenGLRenderer_3_2::InitEdgeMarkProgramBindings() return OGLERROR_NOERR; } +Render3DError OpenGLRenderer_3_2::InitEdgeMarkProgramShaderLocations() +{ + OGLRenderRef &OGLRef = *this->ref; + + OGLRef.uniformBlockRenderStatesEdgeMark = glGetUniformBlockIndex(OGLRef.programEdgeMarkID, "RenderStates"); + glUniformBlockBinding(OGLRef.programEdgeMarkID, OGLRef.uniformBlockRenderStatesEdgeMark, OGLBindingPointID_RenderStates); + + OGLRef.uniformTexGDepth_EdgeMark = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth"); + OGLRef.uniformTexGPolyID_EdgeMark = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID"); + glUniform1i(OGLRef.uniformTexGDepth_EdgeMark, OGLTextureUnitID_GDepth); + glUniform1i(OGLRef.uniformTexGPolyID_EdgeMark, OGLTextureUnitID_GPolyID); + + return OGLERROR_NOERR; +} + Render3DError OpenGLRenderer_3_2::InitFogProgramBindings() { OGLRenderRef &OGLRef = *this->ref; @@ -457,6 +574,23 @@ Render3DError OpenGLRenderer_3_2::InitFogProgramBindings() return OGLERROR_NOERR; } +Render3DError OpenGLRenderer_3_2::InitFogProgramShaderLocations() +{ + OGLRenderRef &OGLRef = *this->ref; + + OGLRef.uniformBlockRenderStatesFog = glGetUniformBlockIndex(OGLRef.programFogID, "RenderStates"); + glUniformBlockBinding(OGLRef.programFogID, OGLRef.uniformBlockRenderStatesFog, OGLBindingPointID_RenderStates); + + OGLRef.uniformTexGColor_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFragColor"); + OGLRef.uniformTexGDepth_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFragDepth"); + OGLRef.uniformTexGFog_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFogAttributes"); + glUniform1i(OGLRef.uniformTexGColor_Fog, OGLTextureUnitID_GColor); + glUniform1i(OGLRef.uniformTexGDepth_Fog, OGLTextureUnitID_GDepth); + glUniform1i(OGLRef.uniformTexGFog_Fog, OGLTextureUnitID_FogAttr); + + return OGLERROR_NOERR; +} + Render3DError OpenGLRenderer_3_2::CreateFBOs() { OGLRenderRef &OGLRef = *this->ref; @@ -775,6 +909,75 @@ Render3DError OpenGLRenderer_3_2::InitGeometryProgramBindings() return OGLERROR_NOERR; } +Render3DError OpenGLRenderer_3_2::InitGeometryProgramShaderLocations() +{ + OGLRenderRef &OGLRef = *this->ref; + + // Set up render states UBO + OGLRef.uniformBlockRenderStatesGeometry = glGetUniformBlockIndex(OGLRef.programGeometryID, "RenderStates"); + glUniformBlockBinding(OGLRef.programGeometryID, OGLRef.uniformBlockRenderStatesGeometry, OGLBindingPointID_RenderStates); + + GLint uboSize = 0; + glGetActiveUniformBlockiv(OGLRef.programGeometryID, OGLRef.uniformBlockRenderStatesGeometry, GL_UNIFORM_BLOCK_DATA_SIZE, &uboSize); + assert(uboSize == sizeof(OGLRenderStates)); + + glGenBuffers(1, &OGLRef.uboRenderStatesID); + glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboRenderStatesID); + glBufferData(GL_UNIFORM_BUFFER, sizeof(OGLRenderStates), NULL, GL_DYNAMIC_DRAW); + glBindBufferBase(GL_UNIFORM_BUFFER, OGLBindingPointID_RenderStates, OGLRef.uboRenderStatesID); + + // Set up poly states TBO + glGenBuffers(1, &OGLRef.tboPolyStatesID); + glBindBuffer(GL_TEXTURE_BUFFER, OGLRef.tboPolyStatesID); + glBufferData(GL_TEXTURE_BUFFER, POLYLIST_SIZE * sizeof(OGLPolyStates), NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_TEXTURE_BUFFER, 0); + + glGenTextures(1, &OGLRef.texPolyStatesID); + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_PolyStates); + glBindTexture(GL_TEXTURE_BUFFER, OGLRef.texPolyStatesID); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA8UI, OGLRef.tboPolyStatesID); + glActiveTexture(GL_TEXTURE0); + + OGLRef.uniformTexRenderObject = glGetUniformLocation(OGLRef.programGeometryID, "texRenderObject"); + OGLRef.uniformTexToonTable = glGetUniformLocation(OGLRef.programGeometryID, "texToonTable"); + OGLRef.uniformTexBufferPolyStates = glGetUniformLocation(OGLRef.programGeometryID, "PolyStates"); + glUniform1i(OGLRef.uniformTexRenderObject, 0); + glUniform1i(OGLRef.uniformTexToonTable, OGLTextureUnitID_ToonTable); + glUniform1i(OGLRef.uniformTexBufferPolyStates, OGLTextureUnitID_PolyStates); + + OGLRef.uniformPolyStateIndex = glGetUniformLocation(OGLRef.programGeometryID, "polyIndex"); + + return OGLERROR_NOERR; +} + +void OpenGLRenderer_3_2::DestroyGeometryProgram() +{ + if(!this->isShaderSupported) + { + return; + } + + OGLRenderRef &OGLRef = *this->ref; + + glUseProgram(0); + + glBindBuffer(GL_UNIFORM_BUFFER, 0); + glBindBuffer(GL_TEXTURE_BUFFER, 0); + glDeleteBuffers(1, &OGLRef.uboRenderStatesID); + glDeleteBuffers(1, &OGLRef.tboPolyStatesID); + + glDetachShader(OGLRef.programGeometryID, OGLRef.vertexGeometryShaderID); + glDetachShader(OGLRef.programGeometryID, OGLRef.fragmentGeometryShaderID); + + glDeleteProgram(OGLRef.programGeometryID); + glDeleteShader(OGLRef.vertexGeometryShaderID); + glDeleteShader(OGLRef.fragmentGeometryShaderID); + + this->DestroyToonTable(); + + this->isShaderSupported = false; +} + void OpenGLRenderer_3_2::GetExtensionSet(std::set *oglExtensionSet) { GLint extensionCount = 0; @@ -856,51 +1059,140 @@ Render3DError OpenGLRenderer_3_2::DownsampleFBO() return OGLERROR_NOERR; } +Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine) +{ + OGLRenderRef &OGLRef = *this->ref; + this->doubleBufferIndex = (this->doubleBufferIndex + 1) & 0x01; + + // Since glReadPixels() is called at the end of every render, we know that rendering + // must be synchronized at that time. Therefore, GL_MAP_UNSYNCHRONIZED_BIT should be + // safe to use. + + glBindBuffer(GL_UNIFORM_BUFFER, OGLRef.uboRenderStatesID); + OGLRenderStates *state = (OGLRenderStates *)glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(OGLRenderStates), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + + state->framebufferSize.x = GFX3D_FRAMEBUFFER_WIDTH; + state->framebufferSize.y = GFX3D_FRAMEBUFFER_HEIGHT; + state->toonShadingMode = engine.renderState.shading; + state->enableAlphaTest = (engine.renderState.enableAlphaTest) ? GL_TRUE : GL_FALSE; + state->enableAntialiasing = (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE; + state->enableEdgeMarking = (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE; + state->enableFogAlphaOnly = (engine.renderState.enableFogAlphaOnly) ? GL_TRUE : GL_FALSE; + state->useWDepth = (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE; + 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]; + state->fogColor.b = divide5bitBy31_LUT[(engine.renderState.fogColor >> 10) & 0x0000001F]; + state->fogColor.a = divide5bitBy31_LUT[(engine.renderState.fogColor >> 16) & 0x0000001F]; + state->fogOffset = (GLfloat)engine.renderState.fogOffset / 32767.0f; + state->fogStep = (GLfloat)(0x0400 >> engine.renderState.fogShift) / 32767.0f; + + for (size_t i = 0; i < 32; i++) + { + state->fogDensity[i].r = (engine.renderState.fogDensityTable[i] == 127) ? 1.0f : (GLfloat)engine.renderState.fogDensityTable[i] / 128.0f; + state->fogDensity[i].g = 0.0f; + state->fogDensity[i].b = 0.0f; + state->fogDensity[i].a = 0.0f; + } + + const GLfloat edgeColorAlpha = (engine.renderState.enableAntialiasing) ? (16.0f/31.0f) : 1.0f; + state->edgeColor[0].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[0] ) & 0x001F]; + state->edgeColor[0].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[0] >> 5) & 0x001F]; + state->edgeColor[0].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[0] >> 10) & 0x001F]; + state->edgeColor[0].a = edgeColorAlpha; + + state->edgeColor[1].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[1] ) & 0x001F]; + state->edgeColor[1].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[1] >> 5) & 0x001F]; + state->edgeColor[1].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[1] >> 10) & 0x001F]; + state->edgeColor[1].a = edgeColorAlpha; + + state->edgeColor[2].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[2] ) & 0x001F]; + state->edgeColor[2].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[2] >> 5) & 0x001F]; + state->edgeColor[2].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[2] >> 10) & 0x001F]; + state->edgeColor[2].a = edgeColorAlpha; + + state->edgeColor[3].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[3] ) & 0x001F]; + state->edgeColor[3].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[3] >> 5) & 0x001F]; + state->edgeColor[3].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[3] >> 10) & 0x001F]; + state->edgeColor[3].a = edgeColorAlpha; + + state->edgeColor[4].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[4] ) & 0x001F]; + state->edgeColor[4].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[4] >> 5) & 0x001F]; + state->edgeColor[4].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[4] >> 10) & 0x001F]; + state->edgeColor[4].a = edgeColorAlpha; + + state->edgeColor[5].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[5] ) & 0x001F]; + state->edgeColor[5].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[5] >> 5) & 0x001F]; + state->edgeColor[5].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[5] >> 10) & 0x001F]; + state->edgeColor[5].a = edgeColorAlpha; + + state->edgeColor[6].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[6] ) & 0x001F]; + state->edgeColor[6].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[6] >> 5) & 0x001F]; + state->edgeColor[6].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[6] >> 10) & 0x001F]; + state->edgeColor[6].a = edgeColorAlpha; + + state->edgeColor[7].r = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[7] ) & 0x001F]; + state->edgeColor[7].g = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[7] >> 5) & 0x001F]; + state->edgeColor[7].b = divide5bitBy31_LUT[(engine.renderState.edgeMarkColorTable[7] >> 10) & 0x001F]; + state->edgeColor[7].a = edgeColorAlpha; + + glUnmapBuffer(GL_UNIFORM_BUFFER); + + // Do per-poly setup + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_PolyStates); + glBindTexture(GL_TEXTURE_BUFFER, OGLRef.texPolyStatesID); + glBindBuffer(GL_TEXTURE_BUFFER, OGLRef.tboPolyStatesID); + + OGLPolyStates *polyStates = (OGLPolyStates *)glMapBufferRange(GL_TEXTURE_BUFFER, 0, engine.polylist->count * sizeof(OGLPolyStates), GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + + for (size_t i = 0; i < engine.polylist->count; i++) + { + const POLY *thePoly = &engine.polylist->list[engine.indexlist.list[i]]; + PolygonAttributes polyAttr = thePoly->getAttributes(); + PolygonTexParams texParams = thePoly->getTexParams(); + + polyStates[i].enableTexture = (thePoly->texParam != 0 && texParams.texFormat != TEXMODE_NONE && engine.renderState.enableTexturing) ? GL_TRUE : GL_FALSE; + polyStates[i].enableFog = (polyAttr.enableRenderFog) ? GL_TRUE : GL_FALSE; + polyStates[i].enableDepthWrite = ((!polyAttr.isTranslucent || polyAttr.enableAlphaDepthWrite) && !(polyAttr.polygonMode == 3 && polyAttr.polygonID == 0)) ? 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].polyMode = polyAttr.polygonMode; + polyStates[i].polyID = polyAttr.polygonID; + polyStates[i].texSizeS = texParams.sizeS; + polyStates[i].texSizeT = texParams.sizeT; + } + + glUnmapBuffer(GL_TEXTURE_BUFFER); + + // Set up remaining framebuffer states + this->SelectRenderingFramebuffer(); + glUseProgram(OGLRef.programGeometryID); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_STENCIL_TEST); + + if(engine.renderState.enableAlphaBlending) + { + glEnable(GL_BLEND); + } + else + { + glDisable(GL_BLEND); + } + + glDepthMask(GL_TRUE); + + return OGLERROR_NOERR; +} + Render3DError OpenGLRenderer_3_2::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias) { OGLRenderRef &OGLRef = *this->ref; - const GLfloat alpha = (useAntialias) ? (16.0f/31.0f) : 1.0f; - const GLfloat oglColor[4*8] = {divide5bitBy31_LUT[(colorTable[0] ) & 0x001F], - divide5bitBy31_LUT[(colorTable[0] >> 5) & 0x001F], - divide5bitBy31_LUT[(colorTable[0] >> 10) & 0x001F], - alpha, - divide5bitBy31_LUT[(colorTable[1] ) & 0x001F], - divide5bitBy31_LUT[(colorTable[1] >> 5) & 0x001F], - divide5bitBy31_LUT[(colorTable[1] >> 10) & 0x001F], - alpha, - divide5bitBy31_LUT[(colorTable[2] ) & 0x001F], - divide5bitBy31_LUT[(colorTable[2] >> 5) & 0x001F], - divide5bitBy31_LUT[(colorTable[2] >> 10) & 0x001F], - alpha, - divide5bitBy31_LUT[(colorTable[3] ) & 0x001F], - divide5bitBy31_LUT[(colorTable[3] >> 5) & 0x001F], - divide5bitBy31_LUT[(colorTable[3] >> 10) & 0x001F], - alpha, - divide5bitBy31_LUT[(colorTable[4] ) & 0x001F], - divide5bitBy31_LUT[(colorTable[4] >> 5) & 0x001F], - divide5bitBy31_LUT[(colorTable[4] >> 10) & 0x001F], - alpha, - divide5bitBy31_LUT[(colorTable[5] ) & 0x001F], - divide5bitBy31_LUT[(colorTable[5] >> 5) & 0x001F], - divide5bitBy31_LUT[(colorTable[5] >> 10) & 0x001F], - alpha, - divide5bitBy31_LUT[(colorTable[6] ) & 0x001F], - divide5bitBy31_LUT[(colorTable[6] >> 5) & 0x001F], - divide5bitBy31_LUT[(colorTable[6] >> 10) & 0x001F], - alpha, - divide5bitBy31_LUT[(colorTable[7] ) & 0x001F], - divide5bitBy31_LUT[(colorTable[7] >> 5) & 0x001F], - divide5bitBy31_LUT[(colorTable[7] >> 10) & 0x001F], - alpha}; - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); glDrawBuffer(GL_COLOR_ATTACHMENT0); glUseProgram(OGLRef.programEdgeMarkID); - glUniform1i(OGLRef.uniformTexGDepth_EdgeMark, OGLTextureUnitID_GDepth); - glUniform1i(OGLRef.uniformTexGPolyID_EdgeMark, OGLTextureUnitID_GPolyID); - glUniform2f(OGLRef.uniformFramebufferSize, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); - glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor); glViewport(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); glDisable(GL_DEPTH_TEST); @@ -927,31 +1219,9 @@ Render3DError OpenGLRenderer_3_2::RenderEdgeMarking(const u16 *colorTable, const Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly) { OGLRenderRef &OGLRef = *this->ref; - static GLfloat oglDensityTable[32]; - - for (size_t i = 0; i < 32; i++) - { - oglDensityTable[i] = (densityTable[i] == 127) ? 1.0f : (GLfloat)densityTable[i] / 128.0f; - } - - const GLfloat oglColor[4] = {divide5bitBy31_LUT[(color ) & 0x0000001F], - divide5bitBy31_LUT[(color >> 5) & 0x0000001F], - divide5bitBy31_LUT[(color >> 10) & 0x0000001F], - divide5bitBy31_LUT[(color >> 16) & 0x0000001F]}; - - const GLfloat oglOffset = (GLfloat)offset / 32767.0f; - const GLfloat oglFogStep = (GLfloat)(0x0400 >> shift) / 32767.0f; glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); glUseProgram(OGLRef.programFogID); - glUniform1i(OGLRef.uniformTexGColor_Fog, OGLTextureUnitID_GColor); - glUniform1i(OGLRef.uniformTexGDepth_Fog, OGLTextureUnitID_GDepth); - glUniform1i(OGLRef.uniformTexGFog_Fog, OGLTextureUnitID_FogAttr); - glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, (alphaOnly) ? GL_TRUE : GL_FALSE); - glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]); - glUniform1f(OGLRef.uniformStateFogOffset, oglOffset); - glUniform1f(OGLRef.uniformStateFogStep, oglFogStep); - glUniform1fv(OGLRef.uniformStateFogDensity, 32, oglDensityTable); glViewport(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); glDisable(GL_DEPTH_TEST); @@ -1032,3 +1302,138 @@ Render3DError OpenGLRenderer_3_2::ClearUsingValues(const FragmentColor &clearCol return OGLERROR_NOERR; } + +void OpenGLRenderer_3_2::SetPolygonIndex(const size_t index) +{ + this->_currentPolyIndex = index; + glUniform1i(this->ref->uniformPolyStateIndex, index); +} + + +Render3DError OpenGLRenderer_3_2::SetupPolygon(const POLY &thePoly) +{ + //OGLRenderRef &OGLRef = *this->ref; + const PolygonAttributes attr = thePoly.getAttributes(); + + // Set up depth test mode + static const GLenum oglDepthFunc[2] = {GL_LESS, GL_EQUAL}; + glDepthFunc(oglDepthFunc[attr.enableDepthTest]); + + // Set up culling mode + static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0}; + GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode]; + + if (cullingMode == 0) + { + glDisable(GL_CULL_FACE); + } + else + { + glEnable(GL_CULL_FACE); + glCullFace(cullingMode); + } + + // Set up depth write + GLboolean enableDepthWrite = GL_TRUE; + + // Handle shadow polys. Do this after checking for depth write, since shadow polys + // can change this too. + if(attr.polygonMode == 3) + { + glEnable(GL_STENCIL_TEST); + if(attr.polygonID == 0) + { + //when the polyID is zero, we are writing the shadow mask. + //set stencilbuf = 1 where the shadow volume is obstructed by geometry. + //do not write color or depth information. + glStencilFunc(GL_ALWAYS, 65, 255); + glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + enableDepthWrite = GL_FALSE; + } + else + { + //when the polyid is nonzero, we are drawing the shadow poly. + //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, 65, 255); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + enableDepthWrite = GL_TRUE; + } + } + else + { + glEnable(GL_STENCIL_TEST); + if(attr.isTranslucent) + { + glStencilFunc(GL_NOTEQUAL, attr.polygonID, 255); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, 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); + + return OGLERROR_NOERR; +} + +Render3DError OpenGLRenderer_3_2::SetupTexture(const POLY &thePoly, bool enableTexturing) +{ + OGLRenderRef &OGLRef = *this->ref; + const PolygonTexParams params = thePoly.getTexParams(); + + // Check if we need to use textures + if (thePoly.texParam == 0 || params.texFormat == TEXMODE_NONE || !enableTexturing) + { + return OGLERROR_NOERR; + } + + TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette); + if(newTexture != this->currTexture) + { + this->currTexture = newTexture; + //has the ogl renderer initialized the texture? + if(!this->currTexture->deleteCallback) + { + this->currTexture->deleteCallback = &texDeleteCallback; + + if(OGLRef.freeTextureIDs.empty()) + { + this->ExpandFreeTextures(); + } + + this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front(); + OGLRef.freeTextureIDs.pop(); + + glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE)); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, + this->currTexture->sizeX, this->currTexture->sizeY, 0, + GL_RGBA, GL_UNSIGNED_BYTE, this->currTexture->decoded); + } + else + { + //otherwise, just bind it + glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid); + } + } + + return OGLERROR_NOERR; +} diff --git a/desmume/src/OGLRender_3_2.h b/desmume/src/OGLRender_3_2.h index a3cbd556f..e4ac9f8aa 100644 --- a/desmume/src/OGLRender_3_2.h +++ b/desmume/src/OGLRender_3_2.h @@ -62,7 +62,9 @@ class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1 protected: virtual Render3DError InitExtensions(); virtual Render3DError InitEdgeMarkProgramBindings(); + virtual Render3DError InitEdgeMarkProgramShaderLocations(); virtual Render3DError InitFogProgramBindings(); + virtual Render3DError InitFogProgramShaderLocations(); virtual Render3DError CreateFBOs(); virtual void DestroyFBOs(); virtual Render3DError CreateMultisampledFBO(); @@ -72,18 +74,25 @@ protected: virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram); virtual Render3DError InitGeometryProgramBindings(); + virtual Render3DError InitGeometryProgramShaderLocations(); + virtual void DestroyGeometryProgram(); virtual void GetExtensionSet(std::set *oglExtensionSet); virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount); virtual Render3DError DisableVertexAttributes(); virtual Render3DError SelectRenderingFramebuffer(); virtual Render3DError DownsampleFBO(); + virtual Render3DError BeginRender(const GFX3D &engine); 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 ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const bool *__restrict fogBuffer, const u8 *__restrict polyIDBuffer); virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const; + virtual void SetPolygonIndex(const size_t index); + virtual Render3DError SetupPolygon(const POLY &thePoly); + virtual Render3DError SetupTexture(const POLY &thePoly, bool enableTexturing); + public: ~OpenGLRenderer_3_2(); }; diff --git a/desmume/src/render3D.cpp b/desmume/src/render3D.cpp index fba4cbae2..d5e5c496b 100644 --- a/desmume/src/render3D.cpp +++ b/desmume/src/render3D.cpp @@ -230,12 +230,12 @@ Render3DError Render3D::ClearUsingValues(const FragmentColor &clearColor, const return RENDER3DERROR_NOERR; } -Render3DError Render3D::SetupPolygon(const POLY *thePoly) +Render3DError Render3D::SetupPolygon(const POLY &thePoly) { return RENDER3DERROR_NOERR; } -Render3DError Render3D::SetupTexture(const POLY *thePoly, bool enableTexturing) +Render3DError Render3D::SetupTexture(const POLY &thePoly, bool enableTexturing) { return RENDER3DERROR_NOERR; } diff --git a/desmume/src/render3D.h b/desmume/src/render3D.h index d1df39b26..b0108aa8f 100644 --- a/desmume/src/render3D.h +++ b/desmume/src/render3D.h @@ -126,8 +126,8 @@ protected: virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const bool *__restrict fogBuffer, const u8 *__restrict polyIDBuffer); virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const; - virtual Render3DError SetupPolygon(const POLY *thePoly); - virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing); + virtual Render3DError SetupPolygon(const POLY &thePoly); + virtual Render3DError SetupTexture(const POLY &thePoly, bool enableTexturing); virtual Render3DError SetupViewport(const u32 viewportValue); public: