Skip to content

Commit

Permalink
OpenGL Renderer: Greatly simplify the fog rendering pass.
Browse files Browse the repository at this point in the history
- There is no more need to switch to the working texture as the destination for the fog output. This change will be essential for future commits.
- The dual-source blending method has been obsoleted and removed.
- FBOs are no longer required for the fog feature, easing requirements for ancient GPUs.
- Ancient GPUs may see a small performance benefit due to shader simplification.
  • Loading branch information
rogerman committed Jul 18, 2024
1 parent 70fef83 commit 0c7cb99
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 134 deletions.
75 changes: 43 additions & 32 deletions desmume/src/OGLRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -646,20 +646,17 @@ void main() \n\
static const char *FogFragShader_100 = {"\
varying vec2 texCoord;\n\
\n\
uniform sampler2D texInFragColor;\n\
uniform sampler2D texInFragDepth;\n\
uniform sampler2D texInFogAttributes;\n\
uniform sampler1D texFogDensityTable;\n\
uniform bool stateEnableFogAlphaOnly;\n\
uniform vec4 stateFogColor;\n\
\n\
void main()\n\
{\n\
vec4 inFragColor = texture2D(texInFragColor, texCoord);\n\
float inFragDepth = texture2D(texInFragDepth, texCoord).r;\n\
vec4 inFogAttributes = texture2D(texInFogAttributes, texCoord);\n\
bool polyEnableFog = (inFogAttributes.r > 0.999);\n\
vec4 newFoggedColor = inFragColor;\n\
vec4 outFogWeight = vec4(0.0);\n\
\n\
float fogMixWeight = 0.0;\n\
if (FOG_STEP == 0)\n\
Expand All @@ -673,10 +670,10 @@ void main()\n\
\n\
if (polyEnableFog)\n\
{\n\
newFoggedColor = mix(inFragColor, (stateEnableFogAlphaOnly) ? vec4(inFragColor.rgb, stateFogColor.a) : stateFogColor, fogMixWeight);\n\
outFogWeight = (stateEnableFogAlphaOnly) ? vec4(vec3(0.0), fogMixWeight) : vec4(fogMixWeight);\n\
}\n\
\n\
gl_FragColor = newFoggedColor;\n\
gl_FragColor = outFogWeight;\n\
}\n\
"};

Expand Down Expand Up @@ -2753,7 +2750,7 @@ Render3DError OpenGLRenderer_1_2::InitExtensions()
this->willFlipAndConvertFramebufferOnGPU = this->isShaderSupported && this->isVBOSupported;
this->willFlipOnlyFramebufferOnGPU = this->willFlipAndConvertFramebufferOnGPU || this->_isFBOBlitSupported;
this->_deviceInfo.isEdgeMarkSupported = this->isShaderSupported && this->isVBOSupported && this->isFBOSupported;
this->_deviceInfo.isFogSupported = this->isShaderSupported && this->isVBOSupported && this->isFBOSupported;
this->_deviceInfo.isFogSupported = this->isShaderSupported && this->isVBOSupported;
this->_deviceInfo.isTextureSmoothingSupported = this->isShaderSupported;

this->_isDepthLEqualPolygonFacingSupported = this->isShaderSupported && this->isVBOSupported && this->isFBOSupported;
Expand Down Expand Up @@ -3584,7 +3581,6 @@ Render3DError OpenGLRenderer_1_2::CreateFogProgram(const OGLFogProgramKey fogPro
glUniform1i(uniformTexFogDensityTable, OGLTextureUnitID_LookupTable);

OGLRef.uniformStateEnableFogAlphaOnly = glGetUniformLocation(shaderID.program, "stateEnableFogAlphaOnly");
OGLRef.uniformStateFogColor = glGetUniformLocation(shaderID.program, "stateFogColor");

return OGLERROR_NOERR;
}
Expand Down Expand Up @@ -4698,32 +4694,30 @@ Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer()
return OGLERROR_NOERR;
}

if ( !(this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) &&
!(this->_enableFog && this->_deviceInfo.isFogSupported) )
{
return OGLERROR_NOERR;
}

OGLRenderRef &OGLRef = *this->ref;

if ( (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported) ||
(this->_enableFog && this->_deviceInfo.isFogSupported) )
// Set up the postprocessing states
glViewport(0, 0, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight);
glDisable(GL_DEPTH_TEST);

glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);

if (this->isVAOSupported)
{
// Set up the postprocessing states
glViewport(0, 0, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight);
glDisable(GL_DEPTH_TEST);

glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);

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));
}
glBindVertexArray(OGLRef.vaoPostprocessStatesID);
}
else
{
return OGLERROR_NOERR;
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));
}

if (this->_enableEdgeMark && this->_deviceInfo.isEdgeMarkSupported)
Expand Down Expand Up @@ -4795,16 +4789,28 @@ Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer()

OGLFogShaderID shaderID = this->_fogProgramMap[this->_fogProgramKey.key];

glDrawBuffer(OGL_WORKING_ATTACHMENT_ID);
if (this->isFBOSupported)
{
glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID);
}

glUseProgram(shaderID.program);
glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, this->_pendingRenderStates.enableFogAlphaOnly);
glUniform4fv(OGLRef.uniformStateFogColor, 1, (const GLfloat *)&this->_pendingRenderStates.fogColor);

glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_CONSTANT_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
glBlendColor( this->_pendingRenderStates.fogColor.r,
this->_pendingRenderStates.fogColor.g,
this->_pendingRenderStates.fogColor.b,
this->_pendingRenderStates.fogColor.a );

glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_BLEND);
glEnable(GL_BLEND);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

this->_lastTextureDrawTarget = OGLTextureUnitID_FinalColor;
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA);
glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);
}

if (this->isVAOSupported)
Expand All @@ -4826,6 +4832,11 @@ Render3DError OpenGLRenderer_1_2::EndRender()
texCache.Evict();

this->ReadBackPixels();
GLenum oglerror = glGetError();
if (oglerror != GL_NO_ERROR)
{
INFO("OpenGL: error = %i\n", (int)oglerror);
}

ENDGL();

Expand Down
57 changes: 55 additions & 2 deletions desmume/src/OGLRender.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "types.h"

// OPENGL PLATFORM-SPECIFIC INCLUDES
#if defined(__ANGLE__) || defined(__ANDROID__)
#if defined(__ANGLE__) || defined(__ANDROID__) || defined(__linux__)
#define OPENGL_VARIANT_ES
#define _NO_SDL_TYPES
#include <GLES3/gl3.h>
Expand Down Expand Up @@ -331,7 +331,10 @@ EXTERNOGLEXT(PFNGLDELETERENDERBUFFERSEXTPROC, glDeleteRenderbuffersEXT)
// modification. In other words, these are one-to-one drop-in replacements.
typedef GLclampf GLclampd;
#define glClearDepth(depth) glClearDepthf(depth)

#ifndef OPENGL_VARIANT_ES
#define glDrawBuffer(x) glDrawBuffers(1, ((GLenum[]){x}))
#endif

// 1D textures may not exist for a particular OpenGL variant, so they will be promoted to
// 2D textures instead. Implementations need to modify their GLSL shaders accordingly to
Expand Down Expand Up @@ -627,8 +630,16 @@ struct OGLRenderRef

GLuint fboClearImageID;
GLuint fboRenderID;
GLuint fboRenderColor0ID[8];
GLuint fboRenderWorking0ID[8];
GLuint fboPolyID;
GLuint fboFogAttrID;
GLuint fboFramebufferFlipID;
GLuint fboColorOutMainID;
GLuint fboColorOutWorkingID;
GLuint fboMSIntermediateRenderID;
GLuint fboMSIntermediateRenderColor0ID[8];
GLuint fboMSFogAttrID;
GLuint selectedRenderingFBO;

// Shader states
Expand Down Expand Up @@ -658,7 +669,6 @@ struct OGLRenderRef
GLint uniformStateEnableFogAlphaOnly;
GLint uniformStateClearPolyID;
GLint uniformStateClearDepth;
GLint uniformStateFogColor;

GLint uniformStateAlphaTestRef[256];
GLint uniformPolyTexScale[256];
Expand Down Expand Up @@ -1030,4 +1040,47 @@ class OpenGLRenderer_2_1 : public OpenGLRenderer_2_0
virtual Render3DError RenderFlush(bool willFlushBuffer32, bool willFlushBuffer16);
};

#ifdef OPENGL_VARIANT_ES

#define glDrawBuffer my_glDrawBuffer
/*
static inline void my_glDrawBuffer(GLenum attach) {
switch(attach) {
case GL_NONE: {
GLenum bufs[1] = {GL_NONE };
glDrawBuffers(1, bufs);
break;
}
case GL_COLOR_ATTACHMENT0: {
GLenum bufs[1] = { attach };
glDrawBuffers(1, bufs);
break;
}
case GL_COLOR_ATTACHMENT1: {
GLenum bufs[2] = {GL_NONE, attach };
glDrawBuffers(2, bufs);
break;
}
case GL_COLOR_ATTACHMENT2: {
GLenum bufs[3] = {GL_NONE, GL_NONE, attach };
glDrawBuffers(3, bufs);
break;
}
case GL_COLOR_ATTACHMENT3: {
GLenum bufs[4] = {GL_NONE, GL_NONE, GL_NONE, attach };
glDrawBuffers(4, bufs);
break;
}
}
}
*/

static inline void my_glDrawBuffer(GLenum attach)
{
GLenum bufs[] = {attach};
glDrawBuffers(1, bufs);
}

#endif

#endif // OGLRENDER_H
Loading

0 comments on commit 0c7cb99

Please sign in to comment.