diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index f57672231..4f282cd2e 100755 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -81,11 +81,15 @@ CACHE_ALIGN const GLfloat divide6bitBy63_LUT[64] = {0.0, 0.015873015 0.8888888888889, 0.9047619047619, 0.9206349206349, 0.9365079365079, 0.9523809523810, 0.9682539682540, 0.9841269841270, 1.0}; -const GLfloat PostprocessVtxBuffer[16] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, - 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; -const GLubyte PostprocessElementBuffer[6] = {0, 1, 2, 2, 3, 0}; +const GLfloat PostprocessVtxBuffer[16] = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f}; -const GLenum RenderDrawList[3] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT}; +const GLenum GeometryDrawBuffersList[4][3] = { + { GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_NONE }, + { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_NONE }, + { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_NONE }, + { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT } +}; bool BEGINGL() { @@ -396,11 +400,13 @@ void main()\n\ \n\ gl_FragData[0] = newFragColor;\n\ \n\ -#if ENABLE_EDGE_MARK\n\ +#if ENABLE_EDGE_MARK && ENABLE_FOG\n\ gl_FragData[1] = newPolyID;\n\ -#endif\n\ -#if ENABLE_FOG\n\ gl_FragData[2] = newFogAttributes;\n\ +#elif ENABLE_EDGE_MARK\n\ + gl_FragData[1] = newPolyID;\n\ +#elif ENABLE_FOG\n\ + gl_FragData[1] = newFogAttributes;\n\ #endif\n\ #if USE_NDS_DEPTH_CALCULATION || ENABLE_FOG\n\ // It is tempting to perform the NDS depth calculation in the vertex shader rather than in the fragment shader.\n\ @@ -1849,10 +1855,15 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const // how the POLY struct stores triangle strip vertices, which is in sets of 3 vertices // each. This redefinition is necessary since uploading more than 3 indices at a time // will cause glDrawElements() to draw the triangle strip incorrectly. - static const GLenum oglPrimitiveType[] = { GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, - GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_STRIP, GL_LINE_STRIP }; + static const GLenum oglPrimitiveType[] = { + GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_STRIP, GL_LINE_STRIP, // Normal polygons + GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_LOOP // Wireframe polygons + }; - static const GLsizei indexIncrementLUT[] = {3, 6, 3, 6, 3, 4, 3, 4}; + static const GLsizei indexIncrementLUT[] = { + 3, 6, 3, 6, 3, 4, 3, 4, // Normal polygons + 3, 4, 3, 4, 3, 4, 3, 4 // Wireframe polygons + }; // Set up the initial polygon const POLY &initialPoly = polyList->list[indexList->list[firstIndex]]; @@ -1898,10 +1909,11 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLYLIST *polyList, const // 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 = (!thePoly.isWireframe()) ? oglPrimitiveType[thePoly.vtxFormat] : GL_LINE_LOOP; + const size_t LUTIndex = (!thePoly.isWireframe()) ? thePoly.vtxFormat : (0x08 | thePoly.vtxFormat); + const GLenum polyPrimitive = oglPrimitiveType[LUTIndex]; // Increment the vertex count - vertIndexCount += indexIncrementLUT[thePoly.vtxFormat]; + vertIndexCount += indexIncrementLUT[LUTIndex]; // 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 @@ -2399,8 +2411,8 @@ OpenGLRenderer_1_2::~OpenGLRenderer_1_2() this->DestroyGeometryZeroDstAlphaProgram(); this->DestroyEdgeMarkProgram(); this->DestroyFogPrograms(); - this->DestroyFramebufferOutput6665Program(); - this->DestroyFramebufferOutput8888Program(); + this->DestroyFramebufferOutput6665Programs(); + this->DestroyFramebufferOutput8888Programs(); } @@ -2456,12 +2468,14 @@ Render3DError OpenGLRenderer_1_2::InitExtensions() this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_program"); if (this->isShaderSupported) { + GLint maxColorAttachmentsOGL = 0; GLint maxDrawBuffersOGL = 0; GLint maxShaderTexUnitsOGL = 0; + glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachmentsOGL); glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &maxDrawBuffersOGL); glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &maxShaderTexUnitsOGL); - if ( (maxDrawBuffersOGL >= 4) && (maxShaderTexUnitsOGL >= 8) ) + if ( (maxColorAttachmentsOGL >= 4) && (maxDrawBuffersOGL >= 4) && (maxShaderTexUnitsOGL >= 8) ) { this->_enableTextureSmoothing = CommonSettings.GFX3D_Renderer_TextureSmoothing; this->_emulateShadowPolygon = CommonSettings.OpenGL_Emulation_ShadowPolygon; @@ -2495,7 +2509,7 @@ Render3DError OpenGLRenderer_1_2::InitExtensions() } else { - INFO("OpenGL: Driver does not support at least 4 draw buffers and 8 texture image units.\n"); + INFO("OpenGL: Driver does not support at least 4 color attachments, 4 draw buffers, and 8 texture image units.\n"); this->isShaderSupported = false; } } @@ -2685,7 +2699,6 @@ Render3DError OpenGLRenderer_1_2::CreateVBOs() glGenBuffersARB(1, &OGLRef.vboGeometryVtxID); glGenBuffersARB(1, &OGLRef.iboGeometryIndexID); glGenBuffersARB(1, &OGLRef.vboPostprocessVtxID); - glGenBuffersARB(1, &OGLRef.iboPostprocessIndexID); glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID); glBufferDataARB(GL_ARRAY_BUFFER_ARB, VERTLIST_SIZE * sizeof(VERT), NULL, GL_STREAM_DRAW_ARB); @@ -2694,8 +2707,6 @@ Render3DError OpenGLRenderer_1_2::CreateVBOs() glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboPostprocessVtxID); glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(PostprocessVtxBuffer), PostprocessVtxBuffer, GL_STATIC_DRAW_ARB); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboPostprocessIndexID); - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(PostprocessElementBuffer), PostprocessElementBuffer, GL_STATIC_DRAW_ARB); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); @@ -2718,7 +2729,6 @@ void OpenGLRenderer_1_2::DestroyVBOs() glDeleteBuffersARB(1, &OGLRef.vboGeometryVtxID); glDeleteBuffersARB(1, &OGLRef.iboGeometryIndexID); glDeleteBuffersARB(1, &OGLRef.vboPostprocessVtxID); - glDeleteBuffersARB(1, &OGLRef.iboPostprocessIndexID); this->isVBOSupported = false; } @@ -2776,7 +2786,6 @@ Render3DError OpenGLRenderer_1_2::CreateVAOs() glBindVertexArray(OGLRef.vaoPostprocessStatesID); glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboPostprocessVtxID); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboPostprocessIndexID); glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); @@ -2889,7 +2898,6 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() // Set up FBOs glGenFramebuffersEXT(1, &OGLRef.fboClearImageID); glGenFramebuffersEXT(1, &OGLRef.fboRenderID); - glGenFramebuffersEXT(1, &OGLRef.fboPostprocessID); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboClearImageID); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texCIColorID, 0); @@ -2906,21 +2914,11 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() return OGLERROR_FBO_CREATE_ERROR; } - if (this->isShaderSupported) - { - glDrawBuffers(3, RenderDrawList); - } - else - { - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - } - - glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texGColorID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); @@ -2932,34 +2930,10 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() return OGLERROR_FBO_CREATE_ERROR; } - if (this->isShaderSupported) - { - glDrawBuffers(3, RenderDrawList); - } - else - { - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - } - - glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texGColorID, 0); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); - - if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) - { - INFO("OpenGL: Failed to created FBOs!\n"); - this->DestroyFBOs(); - - return OGLERROR_FBO_CREATE_ERROR; - } - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); INFO("OpenGL: Successfully created FBOs.\n"); return OGLERROR_NOERR; @@ -2977,7 +2951,6 @@ void OpenGLRenderer_1_2::DestroyFBOs() glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID); glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID); - glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texCIColorID); glDeleteTextures(1, &OGLRef.texCIFogAttrID); glDeleteTextures(1, &OGLRef.texCIPolyID); @@ -2989,7 +2962,6 @@ void OpenGLRenderer_1_2::DestroyFBOs() OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; - OGLRef.fboPostprocessID = 0; this->isFBOSupported = false; } @@ -3030,6 +3002,9 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO(GLsizei numSamples) return OGLERROR_FBO_CREATE_ERROR; } + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); INFO("OpenGL: Successfully created multisampled FBO.\n"); @@ -3572,7 +3547,7 @@ void OpenGLRenderer_1_2::DestroyFogPrograms() } } -Render3DError OpenGLRenderer_1_2::CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString) +Render3DError OpenGLRenderer_1_2::CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString) { Render3DError error = OGLERROR_NOERR; OGLRenderRef &OGLRef = *this->ref; @@ -3591,59 +3566,77 @@ Render3DError OpenGLRenderer_1_2::CreateFramebufferOutput6665Program(const char error = this->ShaderProgramCreate(OGLRef.vertexFramebufferOutput6665ShaderID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID, - OGLRef.programFramebufferRGBA6665OutputID, + OGLRef.programFramebufferRGBA6665OutputID[outColorIndex], vtxShaderCode.c_str(), fragShaderCString); if (error != OGLERROR_NOERR) { INFO("OpenGL: Failed to create the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n"); glUseProgram(0); - this->DestroyFramebufferOutput6665Program(); + this->DestroyFramebufferOutput6665Programs(); return error; } - glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID, OGLVertexAttributeID_Position, "inPosition"); - glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); + glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex], OGLVertexAttributeID_Position, "inPosition"); + glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex], OGLVertexAttributeID_TexCoord0, "inTexCoord0"); - glLinkProgram(OGLRef.programFramebufferRGBA6665OutputID); - if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA6665OutputID)) + glLinkProgram(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex]); + if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex])) { INFO("OpenGL: Failed to link the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n"); glUseProgram(0); - this->DestroyFramebufferOutput6665Program(); + this->DestroyFramebufferOutput6665Programs(); return OGLERROR_SHADER_CREATE_ERROR; } - glValidateProgram(OGLRef.programFramebufferRGBA6665OutputID); - glUseProgram(OGLRef.programFramebufferRGBA6665OutputID); + glValidateProgram(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex]); + glUseProgram(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex]); - OGLRef.uniformTexInFragColor_ConvertRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor"); - glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor); + const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex], "texInFragColor"); + if (outColorIndex == 0) + { + glUniform1i(uniformTexGColor, OGLTextureUnitID_FinalColor); + } + else + { + glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor); + } return OGLERROR_NOERR; } -void OpenGLRenderer_1_2::DestroyFramebufferOutput6665Program() +void OpenGLRenderer_1_2::DestroyFramebufferOutput6665Programs() { OGLRenderRef &OGLRef = *this->ref; - if (!this->isShaderSupported || (OGLRef.programFramebufferRGBA6665OutputID == 0)) + if (!this->isShaderSupported) { return; } - glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.vertexFramebufferOutput6665ShaderID); - glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID); - glDeleteProgram(OGLRef.programFramebufferRGBA6665OutputID); + if (OGLRef.programFramebufferRGBA6665OutputID[0] != 0) + { + glDetachShader(OGLRef.programFramebufferRGBA6665OutputID[0], OGLRef.vertexFramebufferOutput6665ShaderID); + glDetachShader(OGLRef.programFramebufferRGBA6665OutputID[0], OGLRef.fragmentFramebufferRGBA6665OutputShaderID); + glDeleteProgram(OGLRef.programFramebufferRGBA6665OutputID[0]); + OGLRef.programFramebufferRGBA6665OutputID[0] = 0; + } + + if (OGLRef.programFramebufferRGBA6665OutputID[1] != 0) + { + glDetachShader(OGLRef.programFramebufferRGBA6665OutputID[1], OGLRef.vertexFramebufferOutput6665ShaderID); + glDetachShader(OGLRef.programFramebufferRGBA6665OutputID[1], OGLRef.fragmentFramebufferRGBA6665OutputShaderID); + glDeleteProgram(OGLRef.programFramebufferRGBA6665OutputID[1]); + OGLRef.programFramebufferRGBA6665OutputID[1] = 0; + } + glDeleteShader(OGLRef.vertexFramebufferOutput6665ShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID); - - OGLRef.programFramebufferRGBA6665OutputID = 0; OGLRef.vertexFramebufferOutput6665ShaderID = 0; OGLRef.fragmentFramebufferRGBA6665OutputShaderID = 0; } -Render3DError OpenGLRenderer_1_2::CreateFramebufferOutput8888Program(const char *vtxShaderCString, const char *fragShaderCString) +Render3DError OpenGLRenderer_1_2::CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString) { Render3DError error = OGLERROR_NOERR; OGLRenderRef &OGLRef = *this->ref; @@ -3662,54 +3655,72 @@ Render3DError OpenGLRenderer_1_2::CreateFramebufferOutput8888Program(const char error = this->ShaderProgramCreate(OGLRef.vertexFramebufferOutput8888ShaderID, OGLRef.fragmentFramebufferRGBA8888OutputShaderID, - OGLRef.programFramebufferRGBA8888OutputID, + OGLRef.programFramebufferRGBA8888OutputID[outColorIndex], vtxShaderCode.c_str(), fragShaderCString); if (error != OGLERROR_NOERR) { INFO("OpenGL: Failed to create the FRAMEBUFFER OUTPUT RGBA8888 shader program.\n"); glUseProgram(0); - this->DestroyFramebufferOutput8888Program(); + this->DestroyFramebufferOutput8888Programs(); return error; } - glBindAttribLocation(OGLRef.programFramebufferRGBA8888OutputID, OGLVertexAttributeID_Position, "inPosition"); - glBindAttribLocation(OGLRef.programFramebufferRGBA8888OutputID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); + glBindAttribLocation(OGLRef.programFramebufferRGBA8888OutputID[outColorIndex], OGLVertexAttributeID_Position, "inPosition"); + glBindAttribLocation(OGLRef.programFramebufferRGBA8888OutputID[outColorIndex], OGLVertexAttributeID_TexCoord0, "inTexCoord0"); - glLinkProgram(OGLRef.programFramebufferRGBA8888OutputID); - if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA8888OutputID)) + glLinkProgram(OGLRef.programFramebufferRGBA8888OutputID[outColorIndex]); + if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA8888OutputID[outColorIndex])) { INFO("OpenGL: Failed to link the FRAMEBUFFER OUTPUT RGBA8888 shader program.\n"); glUseProgram(0); - this->DestroyFramebufferOutput8888Program(); + this->DestroyFramebufferOutput8888Programs(); return OGLERROR_SHADER_CREATE_ERROR; } - glValidateProgram(OGLRef.programFramebufferRGBA8888OutputID); - glUseProgram(OGLRef.programFramebufferRGBA8888OutputID); + glValidateProgram(OGLRef.programFramebufferRGBA8888OutputID[outColorIndex]); + glUseProgram(OGLRef.programFramebufferRGBA8888OutputID[outColorIndex]); - OGLRef.uniformTexInFragColor_ConvertRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor"); - glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA8888, OGLTextureUnitID_FinalColor); + const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID[outColorIndex], "texInFragColor"); + if (outColorIndex == 0) + { + glUniform1i(uniformTexGColor, OGLTextureUnitID_FinalColor); + } + else + { + glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor); + } return OGLERROR_NOERR; } -void OpenGLRenderer_1_2::DestroyFramebufferOutput8888Program() +void OpenGLRenderer_1_2::DestroyFramebufferOutput8888Programs() { OGLRenderRef &OGLRef = *this->ref; - if (!this->isShaderSupported || (OGLRef.programFramebufferRGBA8888OutputID == 0)) + if (!this->isShaderSupported) { return; } - glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.vertexFramebufferOutput8888ShaderID); - glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.fragmentFramebufferRGBA8888OutputShaderID); - glDeleteProgram(OGLRef.programFramebufferRGBA8888OutputID); + if (OGLRef.programFramebufferRGBA8888OutputID[0] != 0) + { + glDetachShader(OGLRef.programFramebufferRGBA8888OutputID[0], OGLRef.vertexFramebufferOutput8888ShaderID); + glDetachShader(OGLRef.programFramebufferRGBA8888OutputID[0], OGLRef.fragmentFramebufferRGBA8888OutputShaderID); + glDeleteProgram(OGLRef.programFramebufferRGBA8888OutputID[0]); + OGLRef.programFramebufferRGBA8888OutputID[0] = 0; + } + + if (OGLRef.programFramebufferRGBA8888OutputID[1] != 0) + { + glDetachShader(OGLRef.programFramebufferRGBA8888OutputID[1], OGLRef.vertexFramebufferOutput8888ShaderID); + glDetachShader(OGLRef.programFramebufferRGBA8888OutputID[1], OGLRef.fragmentFramebufferRGBA8888OutputShaderID); + glDeleteProgram(OGLRef.programFramebufferRGBA8888OutputID[1]); + OGLRef.programFramebufferRGBA8888OutputID[1] = 0; + } + glDeleteShader(OGLRef.vertexFramebufferOutput8888ShaderID); glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID); - - OGLRef.programFramebufferRGBA8888OutputID = 0; OGLRef.vertexFramebufferOutput8888ShaderID = 0; OGLRef.fragmentFramebufferRGBA8888OutputShaderID = 0; } @@ -3773,13 +3784,25 @@ Render3DError OpenGLRenderer_1_2::InitPostprocessingPrograms(const char *edgeMar return error; } - error = this->CreateFramebufferOutput6665Program(framebufferOutputVtxShaderCString, framebufferOutputRGBA6665FragShaderCString); + error = this->CreateFramebufferOutput6665Program(0, framebufferOutputVtxShaderCString, framebufferOutputRGBA6665FragShaderCString); if (error != OGLERROR_NOERR) { return error; } - error = this->CreateFramebufferOutput8888Program(framebufferOutputVtxShaderCString, framebufferOutputRGBA8888FragShaderCString); + error = this->CreateFramebufferOutput6665Program(1, framebufferOutputVtxShaderCString, framebufferOutputRGBA6665FragShaderCString); + if (error != OGLERROR_NOERR) + { + return error; + } + + error = this->CreateFramebufferOutput8888Program(0, framebufferOutputVtxShaderCString, framebufferOutputRGBA8888FragShaderCString); + if (error != OGLERROR_NOERR) + { + return error; + } + + error = this->CreateFramebufferOutput8888Program(1, framebufferOutputVtxShaderCString, framebufferOutputRGBA8888FragShaderCString); if (error != OGLERROR_NOERR) { return error; @@ -4002,6 +4025,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); } @@ -4016,7 +4040,6 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con glDrawBuffer(GL_NONE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); if (this->isVAOSupported) { @@ -4030,7 +4053,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); } - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); if (this->isVAOSupported) { @@ -4043,6 +4066,10 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con } // Setup for multiple pass alpha poly drawing + OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags; + this->_geometryProgramFlags.EnableEdgeMark = 0; + this->_geometryProgramFlags.EnableFog = 0; + glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE); @@ -4052,8 +4079,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con this->EnableVertexAttributes(); // Draw the alpha polys, touching fully transparent pixels only once. - static const GLenum RenderAlphaDrawList[3] = {GL_COLOR_ATTACHMENT0_EXT, GL_NONE, GL_NONE}; - glDrawBuffers(3, RenderAlphaDrawList); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glEnable(GL_DEPTH_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); @@ -4061,7 +4087,9 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLYLIST *polyList, con this->DrawPolygonsForIndexRange(polyList, indexList, polyList->opaqueCount, polyList->count - 1, indexOffset, lastPolyAttr); // Restore OpenGL states back to normal. - glDrawBuffers(3, RenderDrawList); + this->_geometryProgramFlags = oldGProgramFlags; + glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); glClear(GL_STENCIL_BUFFER_BIT); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); @@ -4090,11 +4118,6 @@ Render3DError OpenGLRenderer_1_2::DownsampleFBO() if (this->isShaderSupported) { - // Blit the color and depth buffers - glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - if (this->_enableEdgeMark) { // Blit the polygon ID buffer @@ -4111,15 +4134,20 @@ Render3DError OpenGLRenderer_1_2::DownsampleFBO() glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); } - // Reset framebuffer targets + // Blit the color and depth buffers glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - glDrawBuffers(3, RenderDrawList); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + + // Reset framebuffer targets glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); } else { // Blit the color buffer glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); @@ -4137,25 +4165,20 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels() { // Both flips and converts the framebuffer on the GPU. No additional postprocessing // should be necessary at this point. - const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID : OGLRef.programFramebufferRGBA8888OutputID; - const GLint uniformTexNumber = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.uniformTexInFragColor_ConvertRGBA6665 : OGLRef.uniformTexInFragColor_ConvertRGBA8888; - - glUseProgram(convertProgramID); - if (this->isFBOSupported) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); - if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) { - glUniform1i(uniformTexNumber, OGLTextureUnitID_GColor); - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); - glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID[1] : OGLRef.programFramebufferRGBA8888OutputID[1]; + glUseProgram(convertProgramID); + glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor; } else { - glUniform1i(uniformTexNumber, OGLTextureUnitID_FinalColor); + const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID[0] : OGLRef.programFramebufferRGBA8888OutputID[0]; + glUseProgram(convertProgramID); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; @@ -4163,7 +4186,9 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels() } else { - glUniform1i(uniformTexNumber, OGLTextureUnitID_FinalColor); + const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID[0] : OGLRef.programFramebufferRGBA8888OutputID[0]; + glUseProgram(convertProgramID); + glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FinalColor); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight); glActiveTextureARB(GL_TEXTURE0_ARB); @@ -4176,7 +4201,6 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels() glDisable(GL_CULL_FACE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); if (this->isVAOSupported) { @@ -4190,7 +4214,7 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels() glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); } - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); if (this->isVAOSupported) { @@ -4206,20 +4230,18 @@ Render3DError OpenGLRenderer_1_2::ReadBackPixels() { // Just flips the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware. // Further colorspace conversion will need to be done in a later step. - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); - if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) { - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glBlitFramebufferEXT(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); - glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); } else { glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); glBlitFramebufferEXT(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); } } @@ -4292,7 +4314,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine) // vertices here to convert them to GL_TRIANGLES, which are much easier // to work with and won't be deprecated in future OpenGL versions. indexPtr[vertIndexCount++] = vertIndex; - if (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP) + if (!thePoly.isWireframe() && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP)) { if (j == 2) { @@ -4327,7 +4349,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine) // vertices here to convert them to GL_TRIANGLES, which are much easier // to work with and won't be deprecated in future OpenGL versions. indexPtr[vertIndexCount++] = vertIndex; - if (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP) + if (!thePoly.isWireframe() && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP)) { if (j == 2) { @@ -4397,6 +4419,17 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine) glLoadIdentity(); } + if (this->isFBOSupported && this->isShaderSupported) + { + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + } + else + { + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + } + + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); @@ -4530,7 +4563,6 @@ Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const glDisable(GL_CULL_FACE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); if (this->isVAOSupported) { @@ -4557,7 +4589,7 @@ Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const glClear(GL_STENCIL_BUFFER_BIT); glUseProgram(OGLRef.programGeometryZeroDstAlphaID); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // Pass 2: Unblended edge mark colors to zero-alpha pixels glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); @@ -4567,13 +4599,13 @@ Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // Pass 3: Blended edge mark glEnable(GL_BLEND); glDisable(GL_STENCIL_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } else { @@ -4583,7 +4615,7 @@ Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glDisable(GL_STENCIL_TEST); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } if (this->isVAOSupported) @@ -4595,9 +4627,6 @@ Render3DError OpenGLRenderer_1_2::RenderEdgeMarking(const u16 *colorTable, const glDisableVertexAttribArray(OGLVertexAttributeID_Position); glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); } - - glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; return OGLERROR_NOERR; } @@ -4639,8 +4668,7 @@ Render3DError OpenGLRenderer_1_2::RenderFog(const u8 *densityTable, const u32 co divide5bitBy31_LUT[(color >> 10) & 0x0000001F], divide5bitBy31_LUT[(color >> 16) & 0x0000001F]}; - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); glUseProgram(shaderID.program); glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, (alphaOnly) ? GL_TRUE : GL_FALSE); glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]); @@ -4653,7 +4681,6 @@ Render3DError OpenGLRenderer_1_2::RenderFog(const u8 *densityTable, const u32 co glDisable(GL_CULL_FACE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); if (this->isVAOSupported) { @@ -4667,7 +4694,7 @@ Render3DError OpenGLRenderer_1_2::RenderFog(const u8 *densityTable, const u32 co glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); } - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); if (this->isVAOSupported) { @@ -4679,7 +4706,6 @@ Render3DError OpenGLRenderer_1_2::RenderFog(const u8 *densityTable, const u32 co glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); } - glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor; return OGLERROR_NOERR; @@ -4755,7 +4781,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); } else { @@ -4800,12 +4826,13 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); } else { // Blit the color and depth buffers. glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); @@ -4848,7 +4875,7 @@ Render3DError OpenGLRenderer_1_2::ClearUsingValues(const FragmentColor &clearCol glClear(GL_COLOR_BUFFER_BIT); } - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); this->_needsZeroDstAlphaPass = (clearColor6665.a == 0); } else @@ -5089,11 +5116,11 @@ Render3DError OpenGLRenderer_1_2::DrawShadowPolygon(const GLenum polyPrimitive, // check fails, then bit 7 (0x80) is cleared. Color and depth writes are disabled for this // pass. // - // 4th pass (emulator driven): Use stencil buffer bit 7 (0x70) for the shadow volume + // 4th pass (emulator driven): Use stencil buffer bit 7 (0x80) for the shadow volume // mask and write out the polygon ID and translucent fragment flag only to those fragments // within the mask. Color and depth writes are disabled for this pass. // - // 5th pass (emulator driven): Use stencil buffer bit 7 (0x70) for the shadow volume + // 5th pass (emulator driven): Use stencil buffer bit 7 (0x80) for the shadow volume // mask and draw the shadow polygon fragments only within the mask. Color writes are always // enabled and depth writes are enabled if the shadow polygon is opaque or if transparent // polygon depth writes are enabled. @@ -5148,8 +5175,7 @@ Render3DError OpenGLRenderer_1_2::DrawShadowPolygon(const GLenum polyPrimitive, glStencilMask(0x80); glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr); - // Check both the depth-equals test bit (bit 7) and shadow volume mask bit (bit 6). - // Fragments that fail this stencil test are removed from the shadow volume mask. + // Finally, do the polygon ID check. glUniform1i(OGLRef.uniformPolyDepthOffsetMode[this->_geometryProgramFlags.value], 0); glDepthFunc(GL_ALWAYS); glStencilFunc(GL_NOTEQUAL, opaquePolyID, 0x3F); @@ -5451,12 +5477,14 @@ Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h) // Recreate shaders that use the framebuffer size. glUseProgram(0); this->DestroyEdgeMarkProgram(); - this->DestroyFramebufferOutput6665Program(); - this->DestroyFramebufferOutput8888Program(); + this->DestroyFramebufferOutput6665Programs(); + this->DestroyFramebufferOutput8888Programs(); this->CreateEdgeMarkProgram(EdgeMarkVtxShader_100, EdgeMarkFragShader_100); - this->CreateFramebufferOutput6665Program(FramebufferOutputVtxShader_100, FramebufferOutputRGBA6665FragShader_100); - this->CreateFramebufferOutput8888Program(FramebufferOutputVtxShader_100, FramebufferOutputRGBA8888FragShader_100); + this->CreateFramebufferOutput6665Program(0, FramebufferOutputVtxShader_100, FramebufferOutputRGBA6665FragShader_100); + this->CreateFramebufferOutput6665Program(1, FramebufferOutputVtxShader_100, FramebufferOutputRGBA6665FragShader_100); + this->CreateFramebufferOutput8888Program(0, FramebufferOutputVtxShader_100, FramebufferOutputRGBA8888FragShader_100); + this->CreateFramebufferOutput8888Program(1, FramebufferOutputVtxShader_100, FramebufferOutputRGBA8888FragShader_100); } if (oglrender_framebufferDidResizeCallback != NULL) @@ -5571,7 +5599,7 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine) // vertices here to convert them to GL_TRIANGLES, which are much easier // to work with and won't be deprecated in future OpenGL versions. indexPtr[vertIndexCount++] = vertIndex; - if (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP) + if (!thePoly.isWireframe() && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP)) { if (j == 2) { @@ -5619,6 +5647,17 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine) glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE); + if (this->isFBOSupported) + { + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + } + else + { + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + } + + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index 0aa7c9cf4..fee0136ec 100755 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -408,6 +408,7 @@ union OGLGeometryFlags struct { +#ifndef MSB_FIRST u8 EnableWDepth:1; u8 EnableAlphaTest:1; u8 EnableTextureSampling:1; @@ -416,10 +417,35 @@ union OGLGeometryFlags u8 ToonShadingMode:1; u8 NeedsDepthEqualsTest:1; u8 :1; +#else + u8 :1; + u8 NeedsDepthEqualsTest:1; + u8 ToonShadingMode:1; + u8 EnableEdgeMark:1; + u8 EnableFog:1; + u8 EnableTextureSampling:1; + u8 EnableAlphaTest:1; + u8 EnableWDepth:1; +#endif + }; + + struct + { + u8 :3; + u8 DrawBuffersMode:2; + u8 :3; }; }; typedef OGLGeometryFlags OGLGeometryFlags; +enum OGLGeometryDrawBuffersMode +{ + OGLGeometryDrawBuffersMode_ColorOnly = 0, + OGLGeometryDrawBuffersMode_Color_Fog = 1, + OGLGeometryDrawBuffersMode_Color_EdgeMark = 2, + OGLGeometryDrawBuffersMode_Color_Fog_EdgeMark = 3 +}; + union OGLFogProgramKey { u32 key; @@ -449,7 +475,6 @@ struct OGLRenderRef GLuint vboGeometryVtxID; GLuint iboGeometryIndexID; GLuint vboPostprocessVtxID; - GLuint iboPostprocessIndexID; // PBO GLuint pboRenderDataID; @@ -479,7 +504,6 @@ struct OGLRenderRef GLuint fboClearImageID; GLuint fboRenderID; - GLuint fboPostprocessID; GLuint fboMSIntermediateRenderID; GLuint selectedRenderingFBO; @@ -504,11 +528,9 @@ struct OGLRenderRef GLuint fragmentFramebufferRGBA6665OutputShaderID; GLuint fragmentFramebufferRGBA8888OutputShaderID; GLuint programEdgeMarkID; - GLuint programFramebufferRGBA6665OutputID; - GLuint programFramebufferRGBA8888OutputID; + GLuint programFramebufferRGBA6665OutputID[2]; + GLuint programFramebufferRGBA8888OutputID[2]; - GLint uniformTexInFragColor_ConvertRGBA6665; - GLint uniformTexInFragColor_ConvertRGBA8888; GLint uniformStateEnableFogAlphaOnly; GLint uniformStateClearPolyID; GLint uniformStateClearDepth; @@ -563,7 +585,7 @@ extern GPU3DInterface gpu3Dgl; extern GPU3DInterface gpu3DglOld; extern GPU3DInterface gpu3Dgl_3_2; -extern const GLenum RenderDrawList[3]; +extern const GLenum GeometryDrawBuffersList[4][3]; extern CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32]; extern CACHE_ALIGN const GLfloat divide6bitBy63_LUT[64]; extern const GLfloat PostprocessVtxBuffer[16]; @@ -725,10 +747,10 @@ protected: virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString) = 0; virtual void DestroyFogProgram(const OGLFogProgramKey fogProgramKey) = 0; virtual void DestroyFogPrograms() = 0; - virtual Render3DError CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString) = 0; - virtual void DestroyFramebufferOutput6665Program() = 0; - virtual Render3DError CreateFramebufferOutput8888Program(const char *vtxShaderCString, const char *fragShaderCString) = 0; - virtual void DestroyFramebufferOutput8888Program() = 0; + virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString) = 0; + virtual void DestroyFramebufferOutput6665Programs() = 0; + virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString) = 0; + virtual void DestroyFramebufferOutput8888Programs() = 0; virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet) = 0; virtual Render3DError InitPostprocessingPrograms(const char *edgeMarkVtxShader, @@ -800,10 +822,10 @@ protected: virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString); virtual void DestroyFogProgram(const OGLFogProgramKey fogProgramKey); virtual void DestroyFogPrograms(); - virtual Render3DError CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString); - virtual void DestroyFramebufferOutput6665Program(); - virtual Render3DError CreateFramebufferOutput8888Program(const char *vtxShaderCString, const char *fragShaderCString); - virtual void DestroyFramebufferOutput8888Program(); + virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString); + virtual void DestroyFramebufferOutput6665Programs(); + virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString); + virtual void DestroyFramebufferOutput8888Programs(); virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet); virtual Render3DError InitPostprocessingPrograms(const char *edgeMarkVtxShader, diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 081cf61d8..4f1525b06 100755 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -1042,7 +1042,6 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() // Set up FBOs glGenFramebuffers(1, &OGLRef.fboClearImageID); glGenFramebuffers(1, &OGLRef.fboRenderID); - glGenFramebuffers(1, &OGLRef.fboPostprocessID); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboClearImageID); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texCIColorID, 0); @@ -1058,13 +1057,11 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() return OGLERROR_FBO_CREATE_ERROR; } - glDrawBuffers(3, RenderDrawList); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texGColorID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) @@ -1075,26 +1072,7 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() return OGLERROR_FBO_CREATE_ERROR; } - glDrawBuffers(3, RenderDrawList); - glReadBuffer(GL_COLOR_ATTACHMENT0); - - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texGColorID, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0); - - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { - INFO("OpenGL: Failed to create FBOs!\n"); - this->DestroyFBOs(); - - return OGLERROR_FBO_CREATE_ERROR; - } - - glDrawBuffer(GL_COLOR_ATTACHMENT0); - glReadBuffer(GL_COLOR_ATTACHMENT0); - OGLRef.selectedRenderingFBO = OGLRef.fboRenderID; - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); INFO("OpenGL: Successfully created FBOs.\n"); return OGLERROR_NOERR; @@ -1112,7 +1090,6 @@ void OpenGLRenderer_3_2::DestroyFBOs() glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &OGLRef.fboClearImageID); glDeleteFramebuffers(1, &OGLRef.fboRenderID); - glDeleteFramebuffers(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texCIColorID); glDeleteTextures(1, &OGLRef.texCIFogAttrID); glDeleteTextures(1, &OGLRef.texCIPolyID); @@ -1124,7 +1101,6 @@ void OpenGLRenderer_3_2::DestroyFBOs() OGLRef.fboClearImageID = 0; OGLRef.fboRenderID = 0; - OGLRef.fboPostprocessID = 0; this->isFBOSupported = false; } @@ -1276,7 +1252,6 @@ Render3DError OpenGLRenderer_3_2::CreateVAOs() glBindVertexArray(OGLRef.vaoPostprocessStatesID); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); glEnableVertexAttribArray(OGLVertexAttributeID_Position); glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); @@ -1378,14 +1353,23 @@ Render3DError OpenGLRenderer_3_2::CreateGeometryPrograms() glBindAttribLocation(OGLRef.programGeometryID[flagsValue], OGLVertexAttributeID_Color, "inColor"); glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 0, "outFragColor"); - if (programFlags.EnableEdgeMark) + switch (programFlags.DrawBuffersMode) { - glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outPolyID"); - } - - if (programFlags.EnableFog) - { - glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 2, "outFogAttributes"); + case OGLGeometryDrawBuffersMode_Color_Fog: + glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outFogAttributes"); + break; + + case OGLGeometryDrawBuffersMode_Color_EdgeMark: + glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outPolyID"); + break; + + case OGLGeometryDrawBuffersMode_Color_Fog_EdgeMark: + glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 1, "outPolyID"); + glBindFragDataLocation(OGLRef.programGeometryID[flagsValue], 2, "outFogAttributes"); + break; + + default: + break; } glLinkProgram(OGLRef.programGeometryID[flagsValue]); @@ -1838,7 +1822,7 @@ Render3DError OpenGLRenderer_3_2::CreateFogProgram(const OGLFogProgramKey fogPro return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_3_2::CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString) +Render3DError OpenGLRenderer_3_2::CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString) { Render3DError error = OGLERROR_NOERR; OGLRenderRef &OGLRef = *this->ref; @@ -1859,43 +1843,50 @@ Render3DError OpenGLRenderer_3_2::CreateFramebufferOutput6665Program(const char error = this->ShaderProgramCreate(OGLRef.vertexFramebufferOutput6665ShaderID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID, - OGLRef.programFramebufferRGBA6665OutputID, + OGLRef.programFramebufferRGBA6665OutputID[outColorIndex], vtxShaderCode.c_str(), fragShaderCode.c_str()); if (error != OGLERROR_NOERR) { INFO("OpenGL: Failed to create the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n"); glUseProgram(0); - this->DestroyFramebufferOutput6665Program(); + this->DestroyFramebufferOutput6665Programs(); return error; } - glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID, OGLVertexAttributeID_Position, "inPosition"); - glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); - glBindFragDataLocation(OGLRef.programFramebufferRGBA6665OutputID, 0, "outFragColor"); + glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex], OGLVertexAttributeID_Position, "inPosition"); + glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex], OGLVertexAttributeID_TexCoord0, "inTexCoord0"); + glBindFragDataLocation(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex], 0, "outFragColor"); - glLinkProgram(OGLRef.programFramebufferRGBA6665OutputID); - if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA6665OutputID)) + glLinkProgram(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex]); + if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex])) { INFO("OpenGL: Failed to link the FRAMEBUFFER OUTPUT RGBA6665 shader program.\n"); glUseProgram(0); - this->DestroyFramebufferOutput6665Program(); + this->DestroyFramebufferOutput6665Programs(); return OGLERROR_SHADER_CREATE_ERROR; } - glValidateProgram(OGLRef.programFramebufferRGBA6665OutputID); - glUseProgram(OGLRef.programFramebufferRGBA6665OutputID); + glValidateProgram(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex]); + glUseProgram(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex]); - OGLRef.uniformTexInFragColor_ConvertRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor"); - glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor); + const GLint uniformTexGColor = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID[outColorIndex], "texInFragColor"); + if (outColorIndex == 0) + { + glUniform1i(uniformTexGColor, OGLTextureUnitID_FinalColor); + } + else + { + glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor); + } return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_3_2::CreateFramebufferOutput8888Program(const char *vtxShaderCString, const char *fragShaderCString) +Render3DError OpenGLRenderer_3_2::CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString) { OGLRenderRef &OGLRef = *this->ref; - OGLRef.programFramebufferRGBA8888OutputID = 0; + OGLRef.programFramebufferRGBA8888OutputID[outColorIndex] = 0; OGLRef.vertexFramebufferOutput8888ShaderID = 0; OGLRef.fragmentFramebufferRGBA8888OutputShaderID = 0; @@ -1950,6 +1941,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); glDrawBuffer(GL_COLOR_ATTACHMENT0); glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); } @@ -1964,12 +1956,15 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con glDrawBuffer(GL_NONE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); glBindVertexArray(OGLRef.vaoPostprocessStatesID); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); // Setup for multiple pass alpha poly drawing + OGLGeometryFlags oldGProgramFlags = this->_geometryProgramFlags; + this->_geometryProgramFlags.EnableEdgeMark = 0; + this->_geometryProgramFlags.EnableFog = 0; + glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE); @@ -1979,8 +1974,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con this->EnableVertexAttributes(); // Draw the alpha polys, touching fully transparent pixels only once. - static const GLenum RenderAlphaDrawList[3] = {GL_COLOR_ATTACHMENT0, GL_NONE, GL_NONE}; - glDrawBuffers(3, RenderAlphaDrawList); + glDrawBuffer(GL_COLOR_ATTACHMENT0); glEnable(GL_DEPTH_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); @@ -1988,7 +1982,9 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLYLIST *polyList, con this->DrawPolygonsForIndexRange(polyList, indexList, polyList->opaqueCount, polyList->count - 1, indexOffset, lastPolyAttr); // Restore OpenGL states back to normal. - glDrawBuffers(3, RenderDrawList); + this->_geometryProgramFlags = oldGProgramFlags; + glUseProgram(OGLRef.programGeometryID[this->_geometryProgramFlags.value]); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); @@ -2015,11 +2011,6 @@ Render3DError OpenGLRenderer_3_2::DownsampleFBO() glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboRenderID); - // Blit the color and depth buffers - glReadBuffer(GL_COLOR_ATTACHMENT0); - glDrawBuffer(GL_COLOR_ATTACHMENT0); - glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - if (this->_enableEdgeMark) { // Blit the polygon ID buffer @@ -2036,10 +2027,14 @@ Render3DError OpenGLRenderer_3_2::DownsampleFBO() glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); } - // Reset framebuffer targets + // Blit the color and depth buffers glReadBuffer(GL_COLOR_ATTACHMENT0); - glDrawBuffers(3, RenderDrawList); + glDrawBuffer(GL_COLOR_ATTACHMENT0); + glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + + // Reset framebuffer targets glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); } return OGLERROR_NOERR; @@ -2053,22 +2048,19 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels() { // Both flips and converts the framebuffer on the GPU. No additional postprocessing // should be necessary at this point. - glUseProgram(OGLRef.programFramebufferRGBA6665OutputID); - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); - if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) { - glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_GColor); - glDrawBuffer(GL_COLOR_ATTACHMENT1); - glReadBuffer(GL_COLOR_ATTACHMENT1); - this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor; + // Use the alternate program where the output color is not at index 0. + glUseProgram(OGLRef.programFramebufferRGBA6665OutputID[1]); + glDrawBuffer(GL_COLOR_ATTACHMENT3); + glReadBuffer(GL_COLOR_ATTACHMENT3); } else { - glUniform1i(OGLRef.uniformTexInFragColor_ConvertRGBA6665, OGLTextureUnitID_FinalColor); + // Use the program where the output color is from index 0. + glUseProgram(OGLRef.programFramebufferRGBA6665OutputID[0]); glDrawBuffer(GL_COLOR_ATTACHMENT0); glReadBuffer(GL_COLOR_ATTACHMENT0); - this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; } glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); @@ -2078,9 +2070,8 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels() glDisable(GL_CULL_FACE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); glBindVertexArray(OGLRef.vaoPostprocessStatesID); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); if (this->_mappedFramebuffer != NULL) @@ -2094,20 +2085,18 @@ Render3DError OpenGLRenderer_3_2::ReadBackPixels() else { // Just flips the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware. - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboPostprocessID); - if (this->_lastTextureDrawTarget == OGLTextureUnitID_GColor) { - glDrawBuffer(GL_COLOR_ATTACHMENT1); + glDrawBuffer(GL_COLOR_ATTACHMENT3); + glReadBuffer(GL_COLOR_ATTACHMENT0); glBlitFramebuffer(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboPostprocessID); - glReadBuffer(GL_COLOR_ATTACHMENT1); + glReadBuffer(GL_COLOR_ATTACHMENT3); } else { glDrawBuffer(GL_COLOR_ATTACHMENT0); + glReadBuffer(GL_COLOR_ATTACHMENT3); glBlitFramebuffer(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboPostprocessID); glReadBuffer(GL_COLOR_ATTACHMENT0); } @@ -2213,7 +2202,7 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine) // vertices here to convert them to GL_TRIANGLES, which are much easier // to work with and won't be deprecated in future OpenGL versions. indexPtr[vertIndexCount++] = vertIndex; - if (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP) + if (!thePoly.isWireframe() && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP)) { if (j == 2) { @@ -2277,6 +2266,9 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D &engine) glUniform1i(OGLRef.uniformTexDrawOpaque[this->_geometryProgramFlags.value], GL_FALSE); glUniform1i(OGLRef.uniformPolyDrawShadow[this->_geometryProgramFlags.value], GL_FALSE); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); @@ -2295,7 +2287,6 @@ Render3DError OpenGLRenderer_3_2::RenderEdgeMarking(const u16 *colorTable, const glDisable(GL_CULL_FACE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); glBindVertexArray(OGLRef.vaoPostprocessStatesID); if (this->_emulateSpecialZeroAlphaBlending) @@ -2311,34 +2302,31 @@ Render3DError OpenGLRenderer_3_2::RenderEdgeMarking(const u16 *colorTable, const glClearBufferfi(GL_DEPTH_STENCIL, 0, 0.0f, 0); glUseProgram(OGLRef.programGeometryZeroDstAlphaID); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // Pass 2: Unblended edge mark colors to zero-alpha pixels glDrawBuffer(GL_COLOR_ATTACHMENT0); glUseProgram(OGLRef.programEdgeMarkID); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // Pass 3: Blended edge mark glEnable(GL_BLEND); glDisable(GL_STENCIL_TEST); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } else { glUseProgram(OGLRef.programEdgeMarkID); glDrawBuffer(GL_COLOR_ATTACHMENT0); glDisable(GL_STENCIL_TEST); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } glBindVertexArray(0); - glReadBuffer(GL_COLOR_ATTACHMENT0); - this->_lastTextureDrawTarget = OGLTextureUnitID_GColor; - return OGLERROR_NOERR; } @@ -2363,10 +2351,8 @@ Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 co OGLFogShaderID shaderID = this->_fogProgramMap[fogProgramKey.key]; - glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); - glDrawBuffer(GL_COLOR_ATTACHMENT1); + glDrawBuffer(GL_COLOR_ATTACHMENT3); glUseProgram(shaderID.program); - glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); @@ -2374,14 +2360,10 @@ Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 co glDisable(GL_CULL_FACE); glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); glBindVertexArray(OGLRef.vaoPostprocessStatesID); - - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); - + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindVertexArray(0); - glReadBuffer(GL_COLOR_ATTACHMENT1); this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor; return OGLERROR_NOERR; @@ -2436,7 +2418,7 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf glBlitFramebuffer(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; if (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID) @@ -2466,7 +2448,7 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf glBlitFramebuffer(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(3, GeometryDrawBuffersList[this->_geometryProgramFlags.DrawBuffersMode]); } return OGLERROR_NOERR; @@ -2477,8 +2459,6 @@ Render3DError OpenGLRenderer_3_2::ClearUsingValues(const FragmentColor &clearCol OGLRenderRef &OGLRef = *this->ref; OGLRef.selectedRenderingFBO = (this->_enableMultisampledRendering) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glDrawBuffers(3, RenderDrawList); const GLfloat oglColor[4] = {divide6bitBy63_LUT[clearColor6665.r], divide6bitBy63_LUT[clearColor6665.g], divide6bitBy63_LUT[clearColor6665.b], divide5bitBy31_LUT[clearColor6665.a]}; glClearBufferfv(GL_COLOR, 0, oglColor); // texGColorID @@ -2690,11 +2670,12 @@ Render3DError OpenGLRenderer_3_2::SetFramebufferSize(size_t w, size_t h) // Recreate shaders that use the framebuffer size. glUseProgram(0); this->DestroyEdgeMarkProgram(); - this->DestroyFramebufferOutput6665Program(); + this->DestroyFramebufferOutput6665Programs(); this->DestroyMSGeometryZeroDstAlphaProgram(); this->CreateEdgeMarkProgram(EdgeMarkVtxShader_150, EdgeMarkFragShader_150); - this->CreateFramebufferOutput6665Program(FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150); + this->CreateFramebufferOutput6665Program(0, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150); + this->CreateFramebufferOutput6665Program(1, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150); if (this->isSampleShadingSupported) { diff --git a/desmume/src/OGLRender_3_2.h b/desmume/src/OGLRender_3_2.h index ab9804996..63114474a 100644 --- a/desmume/src/OGLRender_3_2.h +++ b/desmume/src/OGLRender_3_2.h @@ -79,8 +79,8 @@ protected: virtual void DestroyMSGeometryZeroDstAlphaProgram(); virtual Render3DError CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString); virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString); - virtual Render3DError CreateFramebufferOutput6665Program(const char *vtxShaderCString, const char *fragShaderCString); - virtual Render3DError CreateFramebufferOutput8888Program(const char *vtxShaderCString, const char *fragShaderCString); + virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString); + virtual Render3DError CreateFramebufferOutput8888Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString); virtual void GetExtensionSet(std::set *oglExtensionSet); virtual Render3DError EnableVertexAttributes();