diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 83ed66c8e..1e982cd7c 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -54,7 +54,7 @@ const GLfloat PostprocessVtxBuffer[16] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1. 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 GLenum RenderDrawList[3] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT}; +const GLenum RenderDrawList[4] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT}; static bool BEGINGL() { @@ -114,6 +114,7 @@ OGLEXT(PFNGLUNIFORM1FPROC, glUniform1f) // Core in v2.0 OGLEXT(PFNGLUNIFORM1FVPROC, glUniform1fv) // Core in v2.0 OGLEXT(PFNGLUNIFORM2FPROC, glUniform2f) // Core in v2.0 OGLEXT(PFNGLUNIFORM4FPROC, glUniform4f) // Core in v2.0 +OGLEXT(PFNGLUNIFORM4FVPROC, glUniform4fv) // Core in v2.0 OGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0 OGLEXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) // Core in v2.0 OGLEXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) // Core in v2.0 @@ -194,6 +195,7 @@ static void OGLLoadEntryPoints_Legacy() INITOGLEXT(PFNGLUNIFORM1FVPROC, glUniform1fv) // Core in v2.0 INITOGLEXT(PFNGLUNIFORM2FPROC, glUniform2f) // Core in v2.0 INITOGLEXT(PFNGLUNIFORM4FPROC, glUniform4f) // Core in v2.0 + INITOGLEXT(PFNGLUNIFORM4FVPROC, glUniform4fv) // Core in v2.0 INITOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0 INITOGLEXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) // Core in v2.0 INITOGLEXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) // Core in v2.0 @@ -326,17 +328,103 @@ static const char *fragmentShader_100 = {"\ float newFragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp((vtxPosition.z/vertW) * 0.5 + 0.5, 0.0, 1.0); \n\ \n\ gl_FragData[0] = newFragColor;\n\ - gl_FragData[2] = vec4( float(polyEnableFog), float(stateEnableFogAlphaOnly), 0.0, 1.0);\n\ - if (newFragColor.a >= 1.0 || polySetNewDepthForTranslucent)\n\ - {\n\ - gl_FragData[1] = vec4( packVec3FromFloat(newFragDepth), 1.0);\n\ - }\n\ + gl_FragData[3] = vec4( float(polyEnableFog), float(stateEnableFogAlphaOnly), 0.0, 1.0);\n\ + if (newFragColor.a > 0.999) gl_FragData[2] = vec4(float(polyID)/63.0, float(stateEnableAntialiasing), 0.0, 1.0);\n\ + if (newFragColor.a > 0.999 || polySetNewDepthForTranslucent) gl_FragData[1] = vec4( packVec3FromFloat(newFragDepth), 1.0);\n\ gl_FragDepth = newFragDepth;\n\ } \n\ "}; -// Vertex shader for post-processing, GLSL 1.00 -static const char *PostprocessVertShader_100 = {"\ +// Vertex shader for applying edge marking, GLSL 1.00 +static const char *EdgeMarkVtxShader_100 = {"\ + attribute vec2 inPosition;\n\ + attribute vec2 inTexCoord0;\n\ + uniform vec2 framebufferSize;\n\ + varying vec2 texCoord[5];\n\ + \n\ + void main()\n\ + {\n\ + vec2 texInvScale = vec2(1.0/framebufferSize.x, 1.0/framebufferSize.y);\n\ + \n\ + texCoord[0] = inTexCoord0; // Center\n\ + texCoord[1] = inTexCoord0 + (vec2( 1.0, 0.0) * texInvScale); // Right\n\ + texCoord[2] = inTexCoord0 + (vec2( 0.0, 1.0) * texInvScale); // Down\n\ + texCoord[3] = inTexCoord0 + (vec2(-1.0, 0.0) * texInvScale); // Left\n\ + texCoord[4] = inTexCoord0 + (vec2( 0.0,-1.0) * texInvScale); // Up\n\ + \n\ + gl_Position = vec4(inPosition, 0.0, 1.0);\n\ + }\n\ +"}; + +// Fragment shader for applying edge marking, GLSL 1.00 +static const char *EdgeMarkFragShader_100 = {"\ + varying vec2 texCoord[5];\n\ + \n\ + uniform sampler2D texInFragColor;\n\ + uniform sampler2D texInFragDepth;\n\ + uniform sampler2D texInPolyID;\n\ + uniform vec4 stateEdgeColor[8];\n\ + \n\ + float unpackFloatFromVec3(const vec3 value)\n\ + {\n\ + const vec3 unpackRatio = vec3(256.0, 65536.0, 16777216.0);\n\ + return (dot(value, unpackRatio) / 16777215.0);\n\ + }\n\ + \n\ + void main()\n\ + {\n\ + vec4 inFragColor = texture2D(texInFragColor, texCoord[0]);\n\ + float inFragDepth = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[0]).rgb);\n\ + \n\ + vec4 inPolyIDAttributes[5];\n\ + inPolyIDAttributes[0] = texture2D(texInPolyID, texCoord[0]);\n\ + inPolyIDAttributes[1] = texture2D(texInPolyID, texCoord[1]);\n\ + inPolyIDAttributes[2] = texture2D(texInPolyID, texCoord[2]);\n\ + inPolyIDAttributes[3] = texture2D(texInPolyID, texCoord[3]);\n\ + inPolyIDAttributes[4] = texture2D(texInPolyID, texCoord[4]);\n\ + \n\ + int polyID[5];\n\ + polyID[0] = int((inPolyIDAttributes[0].r * 63.0) + 0.5);\n\ + polyID[1] = int((inPolyIDAttributes[1].r * 63.0) + 0.5);\n\ + polyID[2] = int((inPolyIDAttributes[2].r * 63.0) + 0.5);\n\ + polyID[3] = int((inPolyIDAttributes[3].r * 63.0) + 0.5);\n\ + polyID[4] = int((inPolyIDAttributes[4].r * 63.0) + 0.5);\n\ + \n\ + bool antialias[5];\n\ + antialias[0] = bool(inPolyIDAttributes[0].g);\n\ + antialias[1] = bool(inPolyIDAttributes[1].g);\n\ + antialias[2] = bool(inPolyIDAttributes[2].g);\n\ + antialias[3] = bool(inPolyIDAttributes[3].g);\n\ + antialias[4] = bool(inPolyIDAttributes[4].g);\n\ + \n\ + float depth[5];\n\ + depth[0] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[0]).rgb);\n\ + depth[1] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[1]).rgb);\n\ + depth[2] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[2]).rgb);\n\ + depth[3] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[3]).rgb);\n\ + depth[4] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[4]).rgb);\n\ + \n\ + vec4 edgeColor = stateEdgeColor[polyID[0]/8];\n\ + bool doEdgeMark = false;\n\ + bool doAntialias = false;\n\ + \n\ + for (int i = 1; i < 5; i++)\n\ + {\n\ + if (polyID[0] != polyID[i] && depth[0] >= depth[i])\n\ + {\n\ + doEdgeMark = true;\n\ + edgeColor = stateEdgeColor[polyID[i]/8];\n\ + doAntialias = antialias[i];\n\ + break;\n\ + }\n\ + }\n\ + \n\ + gl_FragData[0] = (doEdgeMark) ? ((doAntialias) ? mix(edgeColor, inFragColor, 0.4) : edgeColor) : inFragColor;\n\ + }\n\ +"}; + +// Vertex shader for applying fog, GLSL 1.00 +static const char *FogVtxShader_100 = {"\ attribute vec2 inPosition;\n\ attribute vec2 inTexCoord0;\n\ varying vec2 texCoord;\n\ @@ -353,7 +441,7 @@ static const char *FogFragShader_100 = {"\ varying vec2 texCoord;\n\ \n\ uniform sampler2D texInFragColor;\n\ - uniform sampler2D texInFragDepthOnly;\n\ + uniform sampler2D texInFragDepth;\n\ uniform sampler2D texInFogAttributes;\n\ uniform vec4 stateFogColor;\n\ uniform float stateFogDensity[32];\n\ @@ -369,7 +457,7 @@ static const char *FogFragShader_100 = {"\ void main()\n\ {\n\ vec4 inFragColor = texture2D(texInFragColor, texCoord);\n\ - float inFragDepth = unpackFloatFromVec3(texture2D(texInFragDepthOnly, texCoord).rgb);\n\ + float inFragDepth = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord).rgb);\n\ vec4 inFogAttributes = texture2D(texInFogAttributes, texCoord);\n\ \n\ bool polyEnableFog = bool(inFogAttributes.r);\n\ @@ -886,7 +974,7 @@ OpenGLRenderer_1_2::~OpenGLRenderer_1_2() ref->color4fBuffer = NULL; DestroyGeometryProgram(); - DestroyPostprocessingProgram(); + DestroyPostprocessingPrograms(); DestroyVAOs(); DestroyVBOs(); DestroyPBOs(); @@ -941,9 +1029,11 @@ Render3DError OpenGLRenderer_1_2::InitExtensions() this->isShaderSupported = false; } - std::string postprocessVtxShaderString = std::string(PostprocessVertShader_100); - std::string postprocessFogFragShaderString = std::string(FogFragShader_100); - error = this->InitPostprocessingProgram(postprocessVtxShaderString, postprocessFogFragShaderString); + std::string edgeMarkVtxShaderString = std::string(EdgeMarkVtxShader_100); + std::string edgeMarkFragShaderString = std::string(EdgeMarkFragShader_100); + std::string fogVtxShaderString = std::string(FogVtxShader_100); + std::string fogFragShaderString = std::string(FogFragShader_100); + error = this->InitPostprocessingPrograms(edgeMarkVtxShaderString, edgeMarkFragShaderString, fogVtxShaderString, fogFragShaderString); if (error != OGLERROR_NOERR) { this->DestroyGeometryProgram(); @@ -1293,9 +1383,11 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() // Set up FBO render targets glGenTextures(1, &OGLRef.texGColorID); glGenTextures(1, &OGLRef.texGDepthID); + glGenTextures(1, &OGLRef.texGPolyID); glGenTextures(1, &OGLRef.texGFogAttrID); glGenTextures(1, &OGLRef.texGDepthStencilID); - glGenTextures(1, &OGLRef.texPostprocessID); + glGenTextures(1, &OGLRef.texPostprocessEdgeMarkID); + glGenTextures(1, &OGLRef.texPostprocessFogID); glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -1319,6 +1411,13 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGPolyID); + 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, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGFogAttrID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -1326,7 +1425,14 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessID); + glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessEdgeMarkID); + 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, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + + glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); 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, GL_CLAMP_TO_EDGE); @@ -1342,7 +1448,8 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() 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.texGDepthID, 0); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 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); @@ -1354,19 +1461,23 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID); glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texGColorID); - glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texGDepthID); + glDeleteTextures(1, &OGLRef.texGPolyID); glDeleteTextures(1, &OGLRef.texGFogAttrID); + glDeleteTextures(1, &OGLRef.texGDepthStencilID); + glDeleteTextures(1, &OGLRef.texPostprocessEdgeMarkID); + glDeleteTextures(1, &OGLRef.texPostprocessFogID); this->isFBOSupported = false; return OGLERROR_FBO_CREATE_ERROR; } - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(4, RenderDrawList); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texPostprocessID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texPostprocessEdgeMarkID, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texPostprocessFogID, 0); if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { @@ -1377,9 +1488,11 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs() glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texGColorID); glDeleteTextures(1, &OGLRef.texGDepthID); + glDeleteTextures(1, &OGLRef.texGPolyID); glDeleteTextures(1, &OGLRef.texGFogAttrID); glDeleteTextures(1, &OGLRef.texGDepthStencilID); - glDeleteTextures(1, &OGLRef.texPostprocessID); + glDeleteTextures(1, &OGLRef.texPostprocessEdgeMarkID); + glDeleteTextures(1, &OGLRef.texPostprocessFogID); this->isFBOSupported = false; return OGLERROR_FBO_CREATE_ERROR; @@ -1408,10 +1521,11 @@ void OpenGLRenderer_1_2::DestroyFBOs() glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID); glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texGColorID); - glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texGDepthID); + glDeleteTextures(1, &OGLRef.texGPolyID); glDeleteTextures(1, &OGLRef.texGFogAttrID); - glDeleteTextures(1, &OGLRef.texPostprocessID); + glDeleteTextures(1, &OGLRef.texGDepthStencilID); + glDeleteTextures(1, &OGLRef.texPostprocessEdgeMarkID); OGLRef.fboRenderID = 0; OGLRef.fboPostprocessID = 0; @@ -1442,6 +1556,7 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO() // Set up FBO render targets glGenRenderbuffersEXT(1, &OGLRef.rboMSGColorID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGDepthID); + glGenRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID); glGenRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); @@ -1449,6 +1564,8 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO() glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); @@ -1460,7 +1577,8 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO() glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID); @@ -1472,6 +1590,7 @@ Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO() glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGColorID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthID); + glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); @@ -1497,6 +1616,7 @@ void OpenGLRenderer_1_2::DestroyMultisampledFBO() glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGColorID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthID); + glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGPolyID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID); glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID); @@ -1568,17 +1688,22 @@ Render3DError OpenGLRenderer_1_2::InitTables() return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::InitPostprocessingProgram(const std::string &vtxShader, const std::string &fragShader) +Render3DError OpenGLRenderer_1_2::InitEdgeMarkProgramBindings() { return OGLERROR_FEATURE_UNSUPPORTED; } -Render3DError OpenGLRenderer_1_2::InitPostprocessingProgramBindings() +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; } -Render3DError OpenGLRenderer_1_2::DestroyPostprocessingProgram() +Render3DError OpenGLRenderer_1_2::InitFogProgramBindings() +{ + return OGLERROR_FEATURE_UNSUPPORTED; +} + +Render3DError OpenGLRenderer_1_2::DestroyPostprocessingPrograms() { return OGLERROR_FEATURE_UNSUPPORTED; } @@ -1624,11 +1749,13 @@ Render3DError OpenGLRenderer_1_2::UploadClearImage(const u16 *__restrict colorBu OGLRenderRef &OGLRef = *this->ref; static GLuint depth[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; + static GLuint polyID[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; static GLuint fogAttributes[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; for (size_t i = 0; i < GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT; i++) { depth[i] = clearImageDepthStencilBuffer[i] >> 8; + polyID[i] = (depthStencilBuffer[i] & 0x0000003F) | 0xFF000000; fogAttributes[i] = (fogBuffer[i]) ? 0xFF0000FF : 0xFF000000; } @@ -1642,6 +1769,10 @@ Render3DError OpenGLRenderer_1_2::UploadClearImage(const u16 *__restrict colorBu glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, depth); + glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GPolyID); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGPolyID); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, polyID); + glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FogAttr); glBindTexture(GL_TEXTURE_2D, OGLRef.texGFogAttrID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, fogAttributes); @@ -1897,14 +2028,19 @@ Render3DError OpenGLRenderer_1_2::DownsampleFBO() glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); - // Blit the fog buffer + // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + // Blit the fog buffer + glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); + glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + // Reset framebuffer targets glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(4, RenderDrawList); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID); } @@ -2103,6 +2239,7 @@ Render3DError OpenGLRenderer_1_2::EndRender(const u64 frameCount) TexCache_EvictFrame(); this->ReadBackPixels(); + this->didRenderEdgeMark = false; return OGLERROR_NOERR; } @@ -2149,45 +2286,54 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); - // Blit the fog buffer + // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + // Blit the fog buffer + glReadBuffer(GL_COLOR_ATTACHMENT3_EXT); + glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); + glBlitFramebufferEXT(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + // Reset framebuffer targets glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(4, RenderDrawList); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID); } return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_1_2::ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil, const bool enableFog) const +Render3DError OpenGLRenderer_1_2::ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const { if (this->isShaderSupported && this->isFBOSupported) { glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // texGColorID glClearColor(divide5bitBy31_LUT[r], divide5bitBy31_LUT[g], divide5bitBy31_LUT[b], divide5bitBy31_LUT[a]); glClearDepth((GLclampd)clearDepth / (GLclampd)0x00FFFFFF); - glClearStencil(clearStencil); + glClearStencil(clearPolyID); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); // texGDepthID glClearColor((GLfloat)(clearDepth & 0x000000FF)/255.0f, (GLfloat)((clearDepth >> 8) & 0x000000FF)/255.0f, (GLfloat)((clearDepth >> 16) & 0x000000FF)/255.0f, 1.0); glClear(GL_COLOR_BUFFER_BIT); - glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); // texGFogAttrID + glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); // texGPolyID + glClearColor((GLfloat)clearPolyID/63.0f, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); // texGFogAttrID glClearColor((enableFog) ? 1.0 : 0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(4, RenderDrawList); } else { glClearColor(divide5bitBy31_LUT[r], divide5bitBy31_LUT[g], divide5bitBy31_LUT[b], divide5bitBy31_LUT[a]); glClearDepth((GLclampd)clearDepth / (GLclampd)0x00FFFFFF); - glClearStencil(clearStencil); + glClearStencil(clearPolyID); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } @@ -2388,6 +2534,7 @@ Render3DError OpenGLRenderer_1_2::Reset() this->gpuScreen3DHasNewData[0] = false; this->gpuScreen3DHasNewData[1] = false; + didRenderEdgeMark = false; glFinish(); @@ -2486,11 +2633,13 @@ Render3DError OpenGLRenderer_1_3::UploadClearImage(const u16 *__restrict colorBu OGLRenderRef &OGLRef = *this->ref; static GLuint depth[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; + static GLuint polyID[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; static GLuint fogAttributes[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT]; for (size_t i = 0; i < GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT; i++) { depth[i] = (depthStencilBuffer[i] >> 8) | 0xFF000000; + polyID[i] = (depthStencilBuffer[i] & 0x0000003F) | 0xFF000000; fogAttributes[i] = (fogBuffer[i]) ? 0xFF0000FF : 0xFF000000; } @@ -2504,6 +2653,10 @@ Render3DError OpenGLRenderer_1_3::UploadClearImage(const u16 *__restrict colorBu glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, depth); + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGPolyID); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, polyID); + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr); glBindTexture(GL_TEXTURE_2D, OGLRef.texGFogAttrID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, fogAttributes); @@ -2827,9 +2980,11 @@ Render3DError OpenGLRenderer_2_0::InitExtensions() return error; } - std::string postprocessVtxShaderString = std::string(PostprocessVertShader_100); - std::string postprocessFogFragShaderString = std::string(FogFragShader_100); - error = this->InitPostprocessingProgram(postprocessVtxShaderString, postprocessFogFragShaderString); + std::string edgeMarkVtxShaderString = std::string(EdgeMarkVtxShader_100); + std::string edgeMarkFragShaderString = std::string(EdgeMarkFragShader_100); + std::string fogVtxShaderString = std::string(FogVtxShader_100); + std::string fogFragShaderString = std::string(FogFragShader_100); + error = this->InitPostprocessingPrograms(edgeMarkVtxShaderString, edgeMarkFragShaderString, fogVtxShaderString, fogFragShaderString); if (error != OGLERROR_NOERR) { this->DestroyGeometryProgram(); @@ -2918,42 +3073,136 @@ Render3DError OpenGLRenderer_2_0::InitFinalRenderStates(const std::setref; + glBindAttribLocation(OGLRef.programEdgeMarkID, OGLVertexAttributeID_Position, "inPosition"); + glBindAttribLocation(OGLRef.programEdgeMarkID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); + + 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; OGLRenderRef &OGLRef = *this->ref; - OGLRef.vertexPostprocessShaderID = glCreateShader(GL_VERTEX_SHADER); - if(!OGLRef.vertexPostprocessShaderID) + OGLRef.vertexEdgeMarkShaderID = glCreateShader(GL_VERTEX_SHADER); + if(!OGLRef.vertexEdgeMarkShaderID) { - INFO("OpenGL: Failed to create the postprocess vertex shader.\n"); + INFO("OpenGL: Failed to create the edge mark vertex shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } - const char *vtxShaderCStr = vtxShader.c_str(); - glShaderSource(OGLRef.vertexPostprocessShaderID, 1, (const GLchar **)&vtxShaderCStr, NULL); - glCompileShader(OGLRef.vertexPostprocessShaderID); - if (!this->ValidateShaderCompile(OGLRef.vertexPostprocessShaderID)) + const char *edgeMarkVtxShaderCStr = edgeMarkVtxShader.c_str(); + glShaderSource(OGLRef.vertexEdgeMarkShaderID, 1, (const GLchar **)&edgeMarkVtxShaderCStr, NULL); + glCompileShader(OGLRef.vertexEdgeMarkShaderID); + if (!this->ValidateShaderCompile(OGLRef.vertexEdgeMarkShaderID)) { - glDeleteShader(OGLRef.vertexPostprocessShaderID); - INFO("OpenGL: Failed to compile the postprocess vertex shader.\n"); + glDeleteShader(OGLRef.vertexEdgeMarkShaderID); + INFO("OpenGL: Failed to compile the edge mark vertex shader.\n"); + return OGLERROR_SHADER_CREATE_ERROR; + } + + OGLRef.fragmentEdgeMarkShaderID = glCreateShader(GL_FRAGMENT_SHADER); + if(!OGLRef.fragmentEdgeMarkShaderID) + { + glDeleteShader(OGLRef.vertexEdgeMarkShaderID); + INFO("OpenGL: Failed to create the edge mark fragment shader.\n"); + return OGLERROR_SHADER_CREATE_ERROR; + } + + const char *edgeMarkFragShaderCStr = edgeMarkFragShader.c_str(); + glShaderSource(OGLRef.fragmentEdgeMarkShaderID, 1, (const GLchar **)&edgeMarkFragShaderCStr, NULL); + glCompileShader(OGLRef.fragmentEdgeMarkShaderID); + if (!this->ValidateShaderCompile(OGLRef.fragmentEdgeMarkShaderID)) + { + glDeleteShader(OGLRef.vertexEdgeMarkShaderID); + glDeleteShader(OGLRef.fragmentEdgeMarkShaderID); + INFO("OpenGL: Failed to compile the edge mark fragment shader.\n"); + return OGLERROR_SHADER_CREATE_ERROR; + } + + OGLRef.programEdgeMarkID = glCreateProgram(); + if(!OGLRef.programEdgeMarkID) + { + glDeleteShader(OGLRef.vertexEdgeMarkShaderID); + glDeleteShader(OGLRef.fragmentEdgeMarkShaderID); + INFO("OpenGL: Failed to create the edge mark shader program.\n"); + return OGLERROR_SHADER_CREATE_ERROR; + } + + glAttachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID); + glAttachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID); + + error = this->InitEdgeMarkProgramBindings(); + if (error != OGLERROR_NOERR) + { + glDetachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID); + glDetachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID); + glDeleteProgram(OGLRef.programEdgeMarkID); + glDeleteShader(OGLRef.vertexEdgeMarkShaderID); + glDeleteShader(OGLRef.fragmentEdgeMarkShaderID); + INFO("OpenGL: Failed to make the edge mark shader bindings.\n"); + return error; + } + + glLinkProgram(OGLRef.programEdgeMarkID); + if (!this->ValidateShaderProgramLink(OGLRef.programEdgeMarkID)) + { + glDetachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID); + glDetachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID); + glDeleteProgram(OGLRef.programEdgeMarkID); + glDeleteShader(OGLRef.vertexEdgeMarkShaderID); + glDeleteShader(OGLRef.fragmentEdgeMarkShaderID); + INFO("OpenGL: Failed to link the edge mark shader program.\n"); + return OGLERROR_SHADER_CREATE_ERROR; + } + + 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"); + + // ------------------------------------------ + + OGLRef.vertexFogShaderID = glCreateShader(GL_VERTEX_SHADER); + if(!OGLRef.vertexFogShaderID) + { + INFO("OpenGL: Failed to create the fog vertex shader.\n"); + return OGLERROR_SHADER_CREATE_ERROR; + } + + const char *fogVtxShaderCStr = fogVtxShader.c_str(); + glShaderSource(OGLRef.vertexFogShaderID, 1, (const GLchar **)&fogVtxShaderCStr, NULL); + glCompileShader(OGLRef.vertexFogShaderID); + if (!this->ValidateShaderCompile(OGLRef.vertexFogShaderID)) + { + glDeleteShader(OGLRef.vertexFogShaderID); + INFO("OpenGL: Failed to compile the fog vertex shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } OGLRef.fragmentFogShaderID = glCreateShader(GL_FRAGMENT_SHADER); if(!OGLRef.fragmentFogShaderID) { - glDeleteShader(OGLRef.vertexPostprocessShaderID); + glDeleteShader(OGLRef.vertexFogShaderID); INFO("OpenGL: Failed to create the fog fragment shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; } - const char *fragShaderCStr = fragShader.c_str(); - glShaderSource(OGLRef.fragmentFogShaderID, 1, (const GLchar **)&fragShaderCStr, NULL); + const char *fogFragShaderCStr = fogFragShader.c_str(); + glShaderSource(OGLRef.fragmentFogShaderID, 1, (const GLchar **)&fogFragShaderCStr, NULL); glCompileShader(OGLRef.fragmentFogShaderID); if (!this->ValidateShaderCompile(OGLRef.fragmentFogShaderID)) { - glDeleteShader(OGLRef.vertexPostprocessShaderID); + glDeleteShader(OGLRef.vertexFogShaderID); glDeleteShader(OGLRef.fragmentFogShaderID); INFO("OpenGL: Failed to compile the fog fragment shader.\n"); return OGLERROR_SHADER_CREATE_ERROR; @@ -2962,22 +3211,22 @@ Render3DError OpenGLRenderer_2_0::InitPostprocessingProgram(const std::string &v OGLRef.programFogID = glCreateProgram(); if(!OGLRef.programFogID) { - glDeleteShader(OGLRef.vertexPostprocessShaderID); + glDeleteShader(OGLRef.vertexFogShaderID); glDeleteShader(OGLRef.fragmentFogShaderID); INFO("OpenGL: Failed to create the fog shader program.\n"); return OGLERROR_SHADER_CREATE_ERROR; } - glAttachShader(OGLRef.programFogID, OGLRef.vertexPostprocessShaderID); + glAttachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID); glAttachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID); - error = this->InitPostprocessingProgramBindings(); + error = this->InitFogProgramBindings(); if (error != OGLERROR_NOERR) { - glDetachShader(OGLRef.programFogID, OGLRef.vertexPostprocessShaderID); + glDetachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID); glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID); glDeleteProgram(OGLRef.programFogID); - glDeleteShader(OGLRef.vertexPostprocessShaderID); + glDeleteShader(OGLRef.vertexFogShaderID); glDeleteShader(OGLRef.fragmentFogShaderID); INFO("OpenGL: Failed to make the fog shader bindings.\n"); return error; @@ -2986,10 +3235,10 @@ Render3DError OpenGLRenderer_2_0::InitPostprocessingProgram(const std::string &v glLinkProgram(OGLRef.programFogID); if (!this->ValidateShaderProgramLink(OGLRef.programFogID)) { - glDetachShader(OGLRef.programFogID, OGLRef.vertexPostprocessShaderID); + glDetachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID); glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID); glDeleteProgram(OGLRef.programFogID); - glDeleteShader(OGLRef.vertexPostprocessShaderID); + glDeleteShader(OGLRef.vertexFogShaderID); glDeleteShader(OGLRef.fragmentFogShaderID); INFO("OpenGL: Failed to link the fog shader program.\n"); return OGLERROR_SHADER_CREATE_ERROR; @@ -2999,9 +3248,9 @@ Render3DError OpenGLRenderer_2_0::InitPostprocessingProgram(const std::string &v glUseProgram(OGLRef.programFogID); // Set up shader uniforms - OGLRef.uniformTexGColor = glGetUniformLocation(OGLRef.programFogID, "texInFragColor"); - OGLRef.uniformTexGDepth = glGetUniformLocation(OGLRef.programFogID, "texInFragDepthOnly"); - OGLRef.uniformTexGFog = glGetUniformLocation(OGLRef.programFogID, "texInFogAttributes"); + OGLRef.uniformTexGColor_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFragColor"); + OGLRef.uniformTexGDepth_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFragDepth"); + OGLRef.uniformTexGFog_Fog = glGetUniformLocation(OGLRef.programFogID, "texInFogAttributes"); OGLRef.uniformStateFogColor = glGetUniformLocation(OGLRef.programFogID, "stateFogColor"); OGLRef.uniformStateFogDensity = glGetUniformLocation(OGLRef.programFogID, "stateFogDensity"); @@ -3014,7 +3263,7 @@ Render3DError OpenGLRenderer_2_0::InitPostprocessingProgram(const std::string &v return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_2_0::InitPostprocessingProgramBindings() +Render3DError OpenGLRenderer_2_0::InitFogProgramBindings() { OGLRenderRef &OGLRef = *this->ref; glBindAttribLocation(OGLRef.programFogID, OGLVertexAttributeID_Position, "inPosition"); @@ -3023,16 +3272,23 @@ Render3DError OpenGLRenderer_2_0::InitPostprocessingProgramBindings() return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_2_0::DestroyPostprocessingProgram() +Render3DError OpenGLRenderer_2_0::DestroyPostprocessingPrograms() { OGLRenderRef &OGLRef = *this->ref; glUseProgram(0); - glDetachShader(OGLRef.programFogID, OGLRef.vertexPostprocessShaderID); + glDetachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID); + glDetachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID); + glDetachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID); glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID); + + glDeleteProgram(OGLRef.programEdgeMarkID); glDeleteProgram(OGLRef.programFogID); + + glDeleteShader(OGLRef.vertexEdgeMarkShaderID); + glDeleteShader(OGLRef.fragmentEdgeMarkShaderID); + glDeleteShader(OGLRef.vertexFogShaderID); glDeleteShader(OGLRef.fragmentFogShaderID); - glDeleteShader(OGLRef.vertexPostprocessShaderID); return OGLERROR_NOERR; } @@ -3162,6 +3418,100 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State *renderState) return OGLERROR_NOERR; } +Render3DError OpenGLRenderer_2_0::RenderEdgeMarking(const u16 *colorTable) +{ + OGLRenderRef &OGLRef = *this->ref; + + const GLfloat oglColor[4*8] = {divide5bitBy31_LUT[(colorTable[0] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[0] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[0] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[1] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[1] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[1] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[2] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[2] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[2] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[3] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[3] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[3] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[4] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[4] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[4] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[5] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[5] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[5] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[6] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[6] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[6] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[7] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[7] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[7] >> 10) & 0x001F], + 1.0f}; + + glBindFramebuffer(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glUseProgram(OGLRef.programEdgeMarkID); + glUniform1i(OGLRef.uniformTexGColor_EdgeMark, OGLTextureUnitID_GColor); + 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); + glDisable(GL_STENCIL_TEST); + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); + + glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); + + if (this->isVAOSupported) + { + glBindVertexArray(OGLRef.vaoPostprocessStatesID); + } + else + { + glEnableVertexAttribArray(OGLVertexAttributeID_Position); + glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0); + glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0); + glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8)); + } + + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID); + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGPolyID); + glActiveTexture(GL_TEXTURE0); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glBindTexture(GL_TEXTURE_2D, 0); + + if (this->isVAOSupported) + { + glBindVertexArray(0); + } + else + { + glDisableVertexAttribArray(OGLVertexAttributeID_Position); + glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0); + } + + this->didRenderEdgeMark = true; + + return RENDER3DERROR_NOERR; +} + Render3DError OpenGLRenderer_2_0::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift) { OGLRenderRef &OGLRef = *this->ref; @@ -3186,10 +3536,12 @@ Render3DError OpenGLRenderer_2_0::RenderFog(const u8 *densityTable, const u32 co const GLfloat oglFogStep = (GLfloat)(0x0400 >> shift) / 32767.0f; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID); + glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); + glReadBuffer(GL_COLOR_ATTACHMENT1_EXT); glUseProgram(OGLRef.programFogID); - glUniform1i(OGLRef.uniformTexGColor, OGLTextureUnitID_GColor); - glUniform1i(OGLRef.uniformTexGDepth, OGLTextureUnitID_GDepth); - glUniform1i(OGLRef.uniformTexGFog, OGLTextureUnitID_FogAttr); + glUniform1i(OGLRef.uniformTexGColor_Fog, OGLTextureUnitID_GColor); + glUniform1i(OGLRef.uniformTexGDepth_Fog, OGLTextureUnitID_GDepth); + glUniform1i(OGLRef.uniformTexGFog_Fog, OGLTextureUnitID_FogAttr); glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]); glUniform1f(OGLRef.uniformStateFogOffset, oglOffset); glUniform1f(OGLRef.uniformStateFogStep, oglFogStep); @@ -3217,7 +3569,7 @@ Render3DError OpenGLRenderer_2_0::RenderFog(const u8 *densityTable, const u32 co } glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor); - glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); + glBindTexture(GL_TEXTURE_2D, (this->didRenderEdgeMark) ? OGLRef.texPostprocessEdgeMarkID : OGLRef.texGColorID); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr); diff --git a/desmume/src/OGLRender.h b/desmume/src/OGLRender.h index de94d8234..a808dacd6 100644 --- a/desmume/src/OGLRender.h +++ b/desmume/src/OGLRender.h @@ -133,6 +133,7 @@ EXTERNOGLEXT(PFNGLUNIFORM1FPROC, glUniform1f) // Core in v2.0 EXTERNOGLEXT(PFNGLUNIFORM1FVPROC, glUniform1fv) // Core in v2.0 EXTERNOGLEXT(PFNGLUNIFORM2FPROC, glUniform2f) // Core in v2.0 EXTERNOGLEXT(PFNGLUNIFORM4FPROC, glUniform4f) // Core in v2.0 +EXTERNOGLEXT(PFNGLUNIFORM4FVPROC, glUniform4fv) // Core in v2.0 EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0 // Generic vertex attributes @@ -216,6 +217,7 @@ EXTERNOGLEXT(PFNGLUNIFORM1FPROC, glUniform1f) // Core in v2.0 EXTERNOGLEXT(PFNGLUNIFORM1FVPROC, glUniform1fv) // Core in v2.0 EXTERNOGLEXT(PFNGLUNIFORM2FPROC, glUniform2f) // Core in v2.0 EXTERNOGLEXT(PFNGLUNIFORM4FPROC, glUniform4f) // Core in v2.0 +EXTERNOGLEXT(PFNGLUNIFORM4FVPROC, glUniform4fv) // Core in v2.0 EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0 // Generic vertex attributes @@ -279,6 +281,7 @@ enum OGLTextureUnitID OGLTextureUnitID_ToonTable = 1, OGLTextureUnitID_GColor, OGLTextureUnitID_GDepth, + OGLTextureUnitID_GPolyID, OGLTextureUnitID_FogAttr }; @@ -317,15 +320,18 @@ struct OGLRenderRef // FBO GLuint texGColorID; - GLuint texGDepthStencilID; GLuint texGDepthID; GLuint texGFogAttrID; - GLuint texPostprocessID; + GLuint texGPolyID; + GLuint texGDepthStencilID; + GLuint texPostprocessEdgeMarkID; + GLuint texPostprocessFogID; GLuint rboMSGColorID; - GLuint rboMSGDepthStencilID; GLuint rboMSGDepthID; + GLuint rboMSGPolyID; GLuint rboMSGFogAttrID; + GLuint rboMSGDepthStencilID; GLuint rboMSPostprocessID; GLuint fboRenderID; @@ -338,7 +344,8 @@ struct OGLRenderRef GLuint fragmentGeometryShaderID; GLuint programGeometryID; - GLuint vertexPostprocessShaderID; + GLuint vertexEdgeMarkShaderID; + GLuint vertexFogShaderID; GLuint fragmentEdgeMarkShaderID; GLuint fragmentFogShaderID; GLuint programEdgeMarkID; @@ -346,10 +353,14 @@ struct OGLRenderRef GLuint uniformTexRenderObject; GLuint uniformTexToonTable; - GLuint uniformTexGColor; - GLuint uniformTexGDepth; - GLuint uniformTexGFog; + GLuint uniformTexGColor_EdgeMark; + GLuint uniformTexGDepth_EdgeMark; + GLuint uniformTexGPolyID_EdgeMark; + GLuint uniformTexGColor_Fog; + GLuint uniformTexGDepth_Fog; + GLuint uniformTexGFog_Fog; + GLint uniformFramebufferSize; GLint uniformStateToonShadingMode; GLint uniformStateEnableAlphaTest; GLint uniformStateEnableAntialiasing; @@ -357,6 +368,7 @@ struct OGLRenderRef GLint uniformStateEnableFogAlphaOnly; GLint uniformStateUseWDepth; GLint uniformStateAlphaTestRef; + GLint uniformStateEdgeColor; GLint uniformStateFogColor; GLint uniformStateFogDensity; GLint uniformStateFogOffset; @@ -397,7 +409,7 @@ extern GPU3DInterface gpu3Dgl; extern GPU3DInterface gpu3DglOld; extern GPU3DInterface gpu3Dgl_3_2; -extern const GLenum RenderDrawList[3]; +extern const GLenum RenderDrawList[4]; extern CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32]; extern const GLfloat PostprocessVtxBuffer[16];; extern const GLubyte PostprocessElementBuffer[6]; @@ -452,6 +464,7 @@ protected: CACHE_ALIGN u32 GPU_screen3D[2][GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT * sizeof(u32)]; bool gpuScreen3DHasNewData[2]; + bool didRenderEdgeMark; size_t doubleBufferIndex; // OpenGL-specific methods @@ -470,9 +483,10 @@ protected: virtual Render3DError InitTextures() = 0; virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet) = 0; virtual Render3DError InitTables() = 0; - virtual Render3DError InitPostprocessingProgram(const std::string &vtxShader, const std::string &fragShader) = 0; - virtual Render3DError InitPostprocessingProgramBindings() = 0; - virtual Render3DError DestroyPostprocessingProgram() = 0; + virtual Render3DError InitEdgeMarkProgramBindings() = 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 DestroyPostprocessingPrograms() = 0; virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram) = 0; virtual Render3DError InitGeometryProgramBindings() = 0; @@ -527,9 +541,10 @@ protected: virtual Render3DError LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram); virtual Render3DError InitGeometryProgramBindings(); virtual void DestroyGeometryProgram(); - virtual Render3DError InitPostprocessingProgram(const std::string &vtxShader, const std::string &fragShader); - virtual Render3DError InitPostprocessingProgramBindings(); - virtual Render3DError DestroyPostprocessingProgram(); + virtual Render3DError InitEdgeMarkProgramBindings(); + virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader); + virtual Render3DError InitFogProgramBindings(); + virtual Render3DError DestroyPostprocessingPrograms(); virtual Render3DError CreateToonTable(); virtual Render3DError DestroyToonTable(); @@ -553,7 +568,7 @@ protected: virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer); virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer, const bool *__restrict fogBuffer); - virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil, const bool enableFog) const; + virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const; virtual Render3DError SetupPolygon(const POLY *thePoly); virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing); @@ -607,15 +622,17 @@ class OpenGLRenderer_2_0 : public OpenGLRenderer_1_5 protected: virtual Render3DError InitExtensions(); virtual Render3DError InitFinalRenderStates(const std::set *oglExtensionSet); - virtual Render3DError InitPostprocessingProgram(const std::string &vtxShader, const std::string &fragShader); - virtual Render3DError InitPostprocessingProgramBindings(); - virtual Render3DError DestroyPostprocessingProgram(); + virtual Render3DError InitEdgeMarkProgramBindings(); + virtual Render3DError InitPostprocessingPrograms(const std::string &edgeMarkVtxShader, const std::string &edgeMarkFragShader, const std::string &fogVtxShader, const std::string &fogFragShader); + virtual Render3DError InitFogProgramBindings(); + virtual Render3DError DestroyPostprocessingPrograms(); virtual Render3DError SetupVertices(const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, GLushort *outIndexBuffer, size_t *outIndexCount); virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount); virtual Render3DError DisableVertexAttributes(); virtual Render3DError BeginRender(const GFX3D_State *renderState); + virtual Render3DError RenderEdgeMarking(const u16 *colorTable); virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift); virtual Render3DError SetupPolygon(const POLY *thePoly); diff --git a/desmume/src/OGLRender_3_2.cpp b/desmume/src/OGLRender_3_2.cpp index 02db86948..558b33d19 100644 --- a/desmume/src/OGLRender_3_2.cpp +++ b/desmume/src/OGLRender_3_2.cpp @@ -126,8 +126,9 @@ static const char *GeometryFragShader_150 = {"\ uniform bool polyEnableTexture; \n\ uniform bool polyEnableFog;\n\ \n\ - out vec4 outFragColor; \n\ + out vec4 outFragColor;\n\ out vec4 outFragDepth;\n\ + out vec4 outPolyID;\n\ out vec4 outFogAttributes;\n\ \n\ vec3 packVec3FromFloat(const float value)\n\ @@ -170,25 +171,117 @@ static const char *GeometryFragShader_150 = {"\ \n\ outFragColor = newFragColor;\n\ outFogAttributes = vec4( float(polyEnableFog), float(stateEnableFogAlphaOnly), 0.0, 1.0);\n\ - if (newFragColor.a >= 1.0 || polySetNewDepthForTranslucent)\n\ - {\n\ - outFragDepth = vec4( packVec3FromFloat(newFragDepth), 1.0);\n\ - }\n\ + if (newFragColor.a > 0.999) outPolyID = vec4(float(polyID)/63.0, float(stateEnableAntialiasing), 0.0, 1.0);\n\ + if (newFragColor.a > 0.999 || polySetNewDepthForTranslucent) outFragDepth = vec4( packVec3FromFloat(newFragDepth), 1.0);\n\ gl_FragDepth = newFragDepth;\n\ } \n\ "}; -// Vertex shader for post-processing, GLSL 1.50 -static const char *PostprocessVtxShader_150 = {"\ +// Vertex shader for applying edge marking, GLSL 1.50 +static const char *EdgeMarkVtxShader_150 = {"\ + #version 150\n\ + \n\ + in vec2 inPosition;\n\ + in vec2 inTexCoord0;\n\ + uniform vec2 framebufferSize;\n\ + out vec2 texCoord[5];\n\ + \n\ + void main()\n\ + {\n\ + vec2 texInvScale = vec2(1.0/framebufferSize.x, 1.0/framebufferSize.y);\n\ + \n\ + texCoord[0] = inTexCoord0; // Center\n\ + texCoord[1] = inTexCoord0 + (vec2( 1.0, 0.0) * texInvScale); // Right\n\ + texCoord[2] = inTexCoord0 + (vec2( 0.0, 1.0) * texInvScale); // Down\n\ + texCoord[3] = inTexCoord0 + (vec2(-1.0, 0.0) * texInvScale); // Left\n\ + texCoord[4] = inTexCoord0 + (vec2( 0.0,-1.0) * texInvScale); // Up\n\ + \n\ + gl_Position = vec4(inPosition, 0.0, 1.0);\n\ + }\n\ +"}; + +// Fragment shader for applying edge marking, GLSL 1.50 +static const char *EdgeMarkFragShader_150 = {"\ + #version 150\n\ + \n\ + in vec2 texCoord[5];\n\ + \n\ + uniform sampler2D texInFragColor;\n\ + uniform sampler2D texInFragDepth;\n\ + uniform sampler2D texInPolyID;\n\ + uniform vec4 stateEdgeColor[8];\n\ + \n\ + out vec4 outFragColor;\n\ + \n\ + float unpackFloatFromVec3(const vec3 value)\n\ + {\n\ + const vec3 unpackRatio = vec3(256.0, 65536.0, 16777216.0);\n\ + return (dot(value, unpackRatio) / 16777215.0);\n\ + }\n\ + \n\ + void main()\n\ + {\n\ + vec4 inFragColor = texture(texInFragColor, texCoord[0]);\n\ + float inFragDepth = unpackFloatFromVec3(texture(texInFragDepth, texCoord[0]).rgb);\n\ + \n\ + vec4 inPolyIDAttributes[5];\n\ + inPolyIDAttributes[0] = texture(texInPolyID, texCoord[0]);\n\ + inPolyIDAttributes[1] = texture(texInPolyID, texCoord[1]);\n\ + inPolyIDAttributes[2] = texture(texInPolyID, texCoord[2]);\n\ + inPolyIDAttributes[3] = texture(texInPolyID, texCoord[3]);\n\ + inPolyIDAttributes[4] = texture(texInPolyID, texCoord[4]);\n\ + \n\ + int polyID[5];\n\ + polyID[0] = int((inPolyIDAttributes[0].r * 63.0) + 0.5);\n\ + polyID[1] = int((inPolyIDAttributes[1].r * 63.0) + 0.5);\n\ + polyID[2] = int((inPolyIDAttributes[2].r * 63.0) + 0.5);\n\ + polyID[3] = int((inPolyIDAttributes[3].r * 63.0) + 0.5);\n\ + polyID[4] = int((inPolyIDAttributes[4].r * 63.0) + 0.5);\n\ + \n\ + bool antialias[5];\n\ + antialias[0] = bool(inPolyIDAttributes[0].g);\n\ + antialias[1] = bool(inPolyIDAttributes[1].g);\n\ + antialias[2] = bool(inPolyIDAttributes[2].g);\n\ + antialias[3] = bool(inPolyIDAttributes[3].g);\n\ + antialias[4] = bool(inPolyIDAttributes[4].g);\n\ + \n\ + float depth[5];\n\ + depth[0] = unpackFloatFromVec3(texture(texInFragDepth, texCoord[0]).rgb);\n\ + depth[1] = unpackFloatFromVec3(texture(texInFragDepth, texCoord[1]).rgb);\n\ + depth[2] = unpackFloatFromVec3(texture(texInFragDepth, texCoord[2]).rgb);\n\ + depth[3] = unpackFloatFromVec3(texture(texInFragDepth, texCoord[3]).rgb);\n\ + depth[4] = unpackFloatFromVec3(texture(texInFragDepth, texCoord[4]).rgb);\n\ + \n\ + vec4 edgeColor = stateEdgeColor[polyID[0]/8];\n\ + bool doEdgeMark = false;\n\ + bool doAntialias = false;\n\ + \n\ + for (int i = 1; i < 5; i++)\n\ + {\n\ + if (polyID[0] != polyID[i] && depth[0] >= depth[i])\n\ + {\n\ + doEdgeMark = true;\n\ + edgeColor = stateEdgeColor[polyID[i]/8];\n\ + doAntialias = antialias[i];\n\ + break;\n\ + }\n\ + }\n\ + \n\ + outFragColor = (doEdgeMark) ? ((doAntialias) ? mix(edgeColor, inFragColor, 0.4) : edgeColor) : inFragColor;\n\ + }\n\ +"}; + +// Vertex shader for applying fog, GLSL 1.50 +static const char *FogVtxShader_150 = {"\ #version 150\n\ \n\ in vec2 inPosition;\n\ in vec2 inTexCoord0;\n\ out vec2 texCoord;\n\ \n\ - void main() \n\ - { \n\ - texCoord = inTexCoord0; \n\ + void main()\n\ + {\n\ + texCoord = inTexCoord0;\n\ gl_Position = vec4(inPosition, 0.0, 1.0);\n\ }\n\ "}; @@ -200,7 +293,7 @@ static const char *FogFragShader_150 = {"\ in vec2 texCoord;\n\ \n\ uniform sampler2D texInFragColor;\n\ - uniform sampler2D texInFragDepthOnly;\n\ + uniform sampler2D texInFragDepth;\n\ uniform sampler2D texInFogAttributes;\n\ uniform vec4 stateFogColor;\n\ uniform float stateFogDensity[32];\n\ @@ -218,7 +311,7 @@ static const char *FogFragShader_150 = {"\ void main()\n\ {\n\ vec4 inFragColor = texture(texInFragColor, texCoord);\n\ - float inFragDepth = unpackFloatFromVec3(texture(texInFragDepthOnly, texCoord).rgb);\n\ + float inFragDepth = unpackFloatFromVec3(texture(texInFragDepth, texCoord).rgb);\n\ vec4 inFogAttributes = texture(texInFogAttributes, texCoord);\n\ \n\ bool polyEnableFog = bool(inFogAttributes.r);\n\ @@ -300,9 +393,11 @@ Render3DError OpenGLRenderer_3_2::InitExtensions() return error; } - std::string postprocessVtxShaderString = std::string(PostprocessVtxShader_150); - std::string postprocessFogFragShaderString = std::string(FogFragShader_150); - error = this->InitPostprocessingProgram(postprocessVtxShaderString, postprocessFogFragShaderString); + std::string edgeMarkVtxShaderString = std::string(EdgeMarkVtxShader_150); + std::string edgeMarkFragShaderString = std::string(EdgeMarkFragShader_150); + std::string fogVtxShaderString = std::string(FogVtxShader_150); + std::string fogFragShaderString = std::string(FogFragShader_150); + error = this->InitPostprocessingPrograms(edgeMarkVtxShaderString, edgeMarkFragShaderString, fogVtxShaderString, fogFragShaderString); if (error != OGLERROR_NOERR) { this->DestroyGeometryProgram(); @@ -348,7 +443,17 @@ Render3DError OpenGLRenderer_3_2::InitExtensions() return OGLERROR_NOERR; } -Render3DError OpenGLRenderer_3_2::InitPostprocessingProgramBindings() +Render3DError OpenGLRenderer_3_2::InitEdgeMarkProgramBindings() +{ + OGLRenderRef &OGLRef = *this->ref; + glBindAttribLocation(OGLRef.programEdgeMarkID, OGLVertexAttributeID_Position, "inPosition"); + glBindAttribLocation(OGLRef.programEdgeMarkID, OGLVertexAttributeID_TexCoord0, "inTexCoord0"); + glBindFragDataLocation(OGLRef.programEdgeMarkID, 0, "outFragColor"); + + return OGLERROR_NOERR; +} + +Render3DError OpenGLRenderer_3_2::InitFogProgramBindings() { OGLRenderRef &OGLRef = *this->ref; glBindAttribLocation(OGLRef.programFogID, OGLVertexAttributeID_Position, "inPosition"); @@ -364,10 +469,12 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() // Set up FBO render targets glGenTextures(1, &OGLRef.texGColorID); - glGenTextures(1, &OGLRef.texGDepthStencilID); glGenTextures(1, &OGLRef.texGDepthID); + glGenTextures(1, &OGLRef.texGPolyID); glGenTextures(1, &OGLRef.texGFogAttrID); - glGenTextures(1, &OGLRef.texPostprocessID); + glGenTextures(1, &OGLRef.texGDepthStencilID); + glGenTextures(1, &OGLRef.texPostprocessEdgeMarkID); + glGenTextures(1, &OGLRef.texPostprocessFogID); glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -391,6 +498,13 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGPolyID); + 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, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGFogAttrID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -398,7 +512,14 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); - glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessID); + glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessEdgeMarkID); + 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, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); + + glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID); 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, GL_CLAMP_TO_EDGE); @@ -414,7 +535,8 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() 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.texGDepthID, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, OGLRef.texGPolyID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) @@ -425,10 +547,12 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glDeleteFramebuffers(1, &OGLRef.fboRenderID); glDeleteFramebuffers(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texGColorID); - glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texGDepthID); + glDeleteTextures(1, &OGLRef.texGPolyID); glDeleteTextures(1, &OGLRef.texGFogAttrID); - glDeleteTextures(1, &OGLRef.texPostprocessID); + glDeleteTextures(1, &OGLRef.texGDepthStencilID); + glDeleteTextures(1, &OGLRef.texPostprocessEdgeMarkID); + glDeleteTextures(1, &OGLRef.texPostprocessFogID); OGLRef.fboRenderID = 0; OGLRef.fboPostprocessID = 0; @@ -436,11 +560,12 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() return OGLERROR_FBO_CREATE_ERROR; } - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(4, RenderDrawList); glReadBuffer(GL_COLOR_ATTACHMENT0); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texPostprocessID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texPostprocessEdgeMarkID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, OGLRef.texPostprocessFogID, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { @@ -450,10 +575,12 @@ Render3DError OpenGLRenderer_3_2::CreateFBOs() glDeleteFramebuffers(1, &OGLRef.fboRenderID); glDeleteFramebuffers(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texGColorID); - glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texGDepthID); + glDeleteTextures(1, &OGLRef.texGPolyID); glDeleteTextures(1, &OGLRef.texGFogAttrID); - glDeleteTextures(1, &OGLRef.texPostprocessID); + glDeleteTextures(1, &OGLRef.texGDepthStencilID); + glDeleteTextures(1, &OGLRef.texPostprocessEdgeMarkID); + glDeleteTextures(1, &OGLRef.texPostprocessFogID); OGLRef.fboRenderID = 0; OGLRef.fboPostprocessID = 0; @@ -484,10 +611,12 @@ void OpenGLRenderer_3_2::DestroyFBOs() glDeleteFramebuffers(1, &OGLRef.fboRenderID); glDeleteFramebuffers(1, &OGLRef.fboPostprocessID); glDeleteTextures(1, &OGLRef.texGColorID); - glDeleteTextures(1, &OGLRef.texGDepthStencilID); glDeleteTextures(1, &OGLRef.texGDepthID); + glDeleteTextures(1, &OGLRef.texGPolyID); glDeleteTextures(1, &OGLRef.texGFogAttrID); - glDeleteTextures(1, &OGLRef.texPostprocessID); + glDeleteTextures(1, &OGLRef.texGDepthStencilID); + glDeleteTextures(1, &OGLRef.texPostprocessEdgeMarkID); + glDeleteTextures(1, &OGLRef.texPostprocessFogID); OGLRef.fboRenderID = 0; OGLRef.fboPostprocessID = 0; @@ -518,6 +647,7 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO() // Set up FBO render targets glGenRenderbuffers(1, &OGLRef.rboMSGColorID); glGenRenderbuffers(1, &OGLRef.rboMSGDepthID); + glGenRenderbuffers(1, &OGLRef.rboMSGPolyID); glGenRenderbuffers(1, &OGLRef.rboMSGFogAttrID); glGenRenderbuffers(1, &OGLRef.rboMSGDepthStencilID); @@ -525,6 +655,8 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO() glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGDepthID); glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); + glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGPolyID); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGFogAttrID); glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID); @@ -536,7 +668,8 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO() glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboMSGColorID); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, OGLRef.rboMSGDepthID); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, OGLRef.rboMSGFogAttrID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, OGLRef.rboMSGPolyID); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_RENDERBUFFER, OGLRef.rboMSGFogAttrID); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) @@ -547,6 +680,7 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO() glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID); glDeleteRenderbuffers(1, &OGLRef.rboMSGColorID); glDeleteRenderbuffers(1, &OGLRef.rboMSGDepthID); + glDeleteRenderbuffers(1, &OGLRef.rboMSGPolyID); glDeleteRenderbuffers(1, &OGLRef.rboMSGFogAttrID); glDeleteRenderbuffers(1, &OGLRef.rboMSGDepthStencilID); @@ -574,6 +708,7 @@ void OpenGLRenderer_3_2::DestroyMultisampledFBO() glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID); glDeleteRenderbuffers(1, &OGLRef.rboMSGColorID); glDeleteRenderbuffers(1, &OGLRef.rboMSGDepthID); + glDeleteRenderbuffers(1, &OGLRef.rboMSGPolyID); glDeleteRenderbuffers(1, &OGLRef.rboMSGFogAttrID); glDeleteRenderbuffers(1, &OGLRef.rboMSGDepthStencilID); @@ -652,7 +787,8 @@ Render3DError OpenGLRenderer_3_2::InitGeometryProgramBindings() glBindAttribLocation(OGLRef.programGeometryID, OGLVertexAttributeID_Color, "inColor"); glBindFragDataLocation(OGLRef.programGeometryID, 0, "outFragColor"); glBindFragDataLocation(OGLRef.programGeometryID, 1, "outFragDepth"); - glBindFragDataLocation(OGLRef.programGeometryID, 2, "outFogAttributes"); + glBindFragDataLocation(OGLRef.programGeometryID, 2, "outPolyID"); + glBindFragDataLocation(OGLRef.programGeometryID, 3, "outFogAttributes"); return OGLERROR_NOERR; } @@ -695,7 +831,7 @@ Render3DError OpenGLRenderer_3_2::SelectRenderingFramebuffer() OGLRef.selectedRenderingFBO = (CommonSettings.GFX3D_Renderer_Multisample) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID; glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO); - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(4, RenderDrawList); return OGLERROR_NOERR; } @@ -719,20 +855,100 @@ Render3DError OpenGLRenderer_3_2::DownsampleFBO() glDrawBuffer(GL_COLOR_ATTACHMENT1); glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); - // Blit the fog buffer + // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2); glDrawBuffer(GL_COLOR_ATTACHMENT2); glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + // Blit the fog buffer + glReadBuffer(GL_COLOR_ATTACHMENT3); + glDrawBuffer(GL_COLOR_ATTACHMENT3); + glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + // Reset framebuffer targets glReadBuffer(GL_COLOR_ATTACHMENT0); - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(4, RenderDrawList); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID); } return OGLERROR_NOERR; } +Render3DError OpenGLRenderer_3_2::RenderEdgeMarking(const u16 *colorTable) +{ + OGLRenderRef &OGLRef = *this->ref; + + const GLfloat oglColor[4*8] = {divide5bitBy31_LUT[(colorTable[0] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[0] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[0] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[1] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[1] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[1] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[2] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[2] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[2] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[3] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[3] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[3] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[4] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[4] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[4] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[5] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[5] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[5] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[6] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[6] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[6] >> 10) & 0x001F], + 1.0f, + divide5bitBy31_LUT[(colorTable[7] ) & 0x001F], + divide5bitBy31_LUT[(colorTable[7] >> 5) & 0x001F], + divide5bitBy31_LUT[(colorTable[7] >> 10) & 0x001F], + 1.0f}; + + glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); + glDrawBuffer(GL_COLOR_ATTACHMENT0); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glUseProgram(OGLRef.programEdgeMarkID); + glUniform1i(OGLRef.uniformTexGColor_EdgeMark, OGLTextureUnitID_GColor); + 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); + glDisable(GL_STENCIL_TEST); + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); + + glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID); + glBindVertexArray(OGLRef.vaoPostprocessStatesID); + + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID); + glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID); + glBindTexture(GL_TEXTURE_2D, OGLRef.texGPolyID); + glActiveTexture(GL_TEXTURE0); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0); + glBindTexture(GL_TEXTURE_2D, 0); + + glBindVertexArray(0); + + this->didRenderEdgeMark = true; + + return RENDER3DERROR_NOERR; +} + Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift) { OGLRenderRef &OGLRef = *this->ref; @@ -752,10 +968,12 @@ Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 co const GLfloat oglFogStep = (GLfloat)(0x0400 >> shift) / 32767.0f; glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboPostprocessID); + glDrawBuffer(GL_COLOR_ATTACHMENT1); + glReadBuffer(GL_COLOR_ATTACHMENT1); glUseProgram(OGLRef.programFogID); - glUniform1i(OGLRef.uniformTexGColor, OGLTextureUnitID_GColor); - glUniform1i(OGLRef.uniformTexGDepth, OGLTextureUnitID_GDepth); - glUniform1i(OGLRef.uniformTexGFog, OGLTextureUnitID_FogAttr); + glUniform1i(OGLRef.uniformTexGColor_Fog, OGLTextureUnitID_GColor); + glUniform1i(OGLRef.uniformTexGDepth_Fog, OGLTextureUnitID_GDepth); + glUniform1i(OGLRef.uniformTexGFog_Fog, OGLTextureUnitID_FogAttr); glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]); glUniform1f(OGLRef.uniformStateFogOffset, oglOffset); glUniform1f(OGLRef.uniformStateFogStep, oglFogStep); @@ -772,7 +990,7 @@ Render3DError OpenGLRenderer_3_2::RenderFog(const u8 *densityTable, const u32 co glBindVertexArray(OGLRef.vaoPostprocessStatesID); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor); - glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID); + glBindTexture(GL_TEXTURE_2D, (this->didRenderEdgeMark) ? OGLRef.texPostprocessEdgeMarkID : OGLRef.texGColorID); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth); glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID); glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr); @@ -808,14 +1026,19 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf glDrawBuffer(GL_COLOR_ATTACHMENT1); glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); - // Blit the fog buffer + // Blit the polygon ID buffer glReadBuffer(GL_COLOR_ATTACHMENT2); glDrawBuffer(GL_COLOR_ATTACHMENT2); glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + // Blit the fog buffer + glReadBuffer(GL_COLOR_ATTACHMENT3); + glDrawBuffer(GL_COLOR_ATTACHMENT3); + glBlitFramebuffer(0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, 0, 0, GFX3D_FRAMEBUFFER_WIDTH, GFX3D_FRAMEBUFFER_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + // Reset framebuffer targets glReadBuffer(GL_COLOR_ATTACHMENT0); - glDrawBuffers(3, RenderDrawList); + glDrawBuffers(4, RenderDrawList); glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID); } diff --git a/desmume/src/OGLRender_3_2.h b/desmume/src/OGLRender_3_2.h index 25f633ffc..6ed2f62ec 100644 --- a/desmume/src/OGLRender_3_2.h +++ b/desmume/src/OGLRender_3_2.h @@ -61,7 +61,8 @@ class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1 { protected: virtual Render3DError InitExtensions(); - virtual Render3DError InitPostprocessingProgramBindings(); + virtual Render3DError InitEdgeMarkProgramBindings(); + virtual Render3DError InitFogProgramBindings(); virtual Render3DError CreateFBOs(); virtual void DestroyFBOs(); virtual Render3DError CreateMultisampledFBO(); @@ -77,6 +78,7 @@ protected: virtual Render3DError DisableVertexAttributes(); virtual Render3DError SelectRenderingFramebuffer(); virtual Render3DError DownsampleFBO(); + virtual Render3DError RenderEdgeMarking(const u16 *colorTable); virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift); virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer, const bool *__restrict fogBuffer); diff --git a/desmume/src/render3D.cpp b/desmume/src/render3D.cpp index 1ae745b3a..094618b71 100644 --- a/desmume/src/render3D.cpp +++ b/desmume/src/render3D.cpp @@ -126,6 +126,11 @@ Render3DError Render3D::RenderGeometry(const GFX3D_State *renderState, const VER return RENDER3DERROR_NOERR; } +Render3DError Render3D::RenderEdgeMarking(const u16 *colorTable) +{ + return RENDER3DERROR_NOERR; +} + Render3DError Render3D::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift) { return RENDER3DERROR_NOERR; @@ -209,7 +214,7 @@ Render3DError Render3D::ClearUsingImage(const u16 *__restrict colorBuffer, const return RENDER3DERROR_NOERR; } -Render3DError Render3D::ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil, const bool enableFog) const +Render3DError Render3D::ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const { return RENDER3DERROR_NOERR; } @@ -252,6 +257,11 @@ Render3DError Render3D::Render(const GFX3D_State *renderState, const VERTLIST *v this->RenderGeometry(renderState, vertList, polyList, indexList); + if (renderState->enableEdgeMarking) + { + this->RenderEdgeMarking((const u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0330)); + } + if (renderState->enableFog) { this->RenderFog(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0360, renderState->fogColor, renderState->fogOffset, renderState->fogShift); diff --git a/desmume/src/render3D.h b/desmume/src/render3D.h index b4176aba5..3cdac14ab 100644 --- a/desmume/src/render3D.h +++ b/desmume/src/render3D.h @@ -90,6 +90,7 @@ protected: virtual Render3DError BeginRender(const GFX3D_State *renderState); virtual Render3DError RenderGeometry(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList); + virtual Render3DError RenderEdgeMarking(const u16 *colorTable); virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift); virtual Render3DError EndRender(const u64 frameCount); @@ -97,7 +98,7 @@ protected: virtual Render3DError ClearFramebuffer(const GFX3D_State *renderState); virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthStencilBuffer, const bool *__restrict fogBuffer); - virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil, const bool enableFog) const; + virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const; virtual Render3DError SetupPolygon(const POLY *thePoly); virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing);