OpenGL Renderer: Fix some longstanding graphical glitches related to running Edge Mark and Fog with MSAA.

- These graphical glitches are resolved only when running 3.2 Core Profile with the GL_ARB_sample_shading extension, available on all modern GPUs.
- Do some minor optimizations to the Edge Mark and Fog shaders.
- Also fix an FBO attachment bug in legacy OpenGL that was introduced in commit 8b5ac56.
This commit is contained in:
rogerman 2024-07-20 20:49:44 -07:00
parent 8b5ac56d66
commit 3ef927100b
6 changed files with 486 additions and 230 deletions

View File

@ -553,9 +553,6 @@ void main()\n\
edgeColor[3] = texture1D(texEdgeColor, polyIDInfo[3].r);\n\
edgeColor[4] = texture1D(texEdgeColor, polyIDInfo[4].r);\n\
\n\
bool isWireframe[5];\n\
isWireframe[0] = bool(polyIDInfo[0].g);\n\
\n\
float depth[5];\n\
depth[0] = texture2D(texInFragDepth, texCoord[0]).r;\n\
depth[1] = texture2D(texInFragDepth, texCoord[1]).r;\n\
@ -563,6 +560,9 @@ void main()\n\
depth[3] = texture2D(texInFragDepth, texCoord[3]).r;\n\
depth[4] = texture2D(texInFragDepth, texCoord[4]).r;\n\
\n\
bool isWireframe[5];\n\
isWireframe[0] = bool(polyIDInfo[0].g);\n\
\n\
vec4 newEdgeColor = vec4(0.0, 0.0, 0.0, 0.0);\n\
\n\
if (!isWireframe[0])\n\
@ -583,47 +583,19 @@ void main()\n\
\n\
if ( ((gl_FragCoord.x >= FRAMEBUFFER_SIZE_X-1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[1]) && (depth[0] >= depth[1]) && !isWireframe[1])) )\n\
{\n\
if (gl_FragCoord.x >= FRAMEBUFFER_SIZE_X-1.0)\n\
{\n\
newEdgeColor = edgeColor[0];\n\
}\n\
else\n\
{\n\
newEdgeColor = edgeColor[1];\n\
}\n\
newEdgeColor = (gl_FragCoord.x >= FRAMEBUFFER_SIZE_X-1.0) ? edgeColor[0] : edgeColor[1];\n\
}\n\
else if ( ((gl_FragCoord.y >= FRAMEBUFFER_SIZE_Y-1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[2]) && (depth[0] >= depth[2]) && !isWireframe[2])) )\n\
{\n\
if (gl_FragCoord.y >= FRAMEBUFFER_SIZE_Y-1.0)\n\
{\n\
newEdgeColor = edgeColor[0];\n\
}\n\
else\n\
{\n\
newEdgeColor = edgeColor[2];\n\
}\n\
newEdgeColor = (gl_FragCoord.y >= FRAMEBUFFER_SIZE_Y-1.0) ? edgeColor[0] : edgeColor[2];\n\
}\n\
else if ( ((gl_FragCoord.x < 1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[3]) && (depth[0] >= depth[3]) && !isWireframe[3])) )\n\
{\n\
if (gl_FragCoord.x < 1.0)\n\
{\n\
newEdgeColor = edgeColor[0];\n\
}\n\
else\n\
{\n\
newEdgeColor = edgeColor[3];\n\
}\n\
newEdgeColor = (gl_FragCoord.x < 1.0) ? edgeColor[0] : edgeColor[3];\n\
}\n\
else if ( ((gl_FragCoord.y < 1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[4]) && (depth[0] >= depth[4]) && !isWireframe[4])) )\n\
{\n\
if (gl_FragCoord.y < 1.0)\n\
{\n\
newEdgeColor = edgeColor[0];\n\
}\n\
else\n\
{\n\
newEdgeColor = edgeColor[4];\n\
}\n\
newEdgeColor = (gl_FragCoord.y < 1.0) ? edgeColor[0] : edgeColor[4];\n\
}\n\
}\n\
\n\
@ -658,24 +630,10 @@ void main()\n\
float inFragDepth = texture2D(texInFragDepth, texCoord).r;\n\
vec4 inFogAttributes = texture2D(texInFogAttributes, texCoord);\n\
bool polyEnableFog = (inFogAttributes.r > 0.999);\n\
vec4 outFogWeight = vec4(0.0);\n\
float densitySelect = (FOG_STEP == 0) ? ((inFragDepth <= FOG_OFFSETF) ? 0.0 : 1.0) : (inFragDepth * (1024.0/float(FOG_STEP))) + (((-float(FOG_OFFSET)/float(FOG_STEP)) - 0.5) / 32.0);\n\
float fogMixWeight = texture1D(texFogDensityTable, densitySelect).r;\n\
\n\
float fogMixWeight = 0.0;\n\
if (FOG_STEP == 0)\n\
{\n\
fogMixWeight = texture1D( texFogDensityTable, (inFragDepth <= FOG_OFFSETF) ? 0.0 : 1.0 ).r;\n\
}\n\
else\n\
{\n\
fogMixWeight = texture1D( texFogDensityTable, (inFragDepth * (1024.0/float(FOG_STEP))) + (((-float(FOG_OFFSET)/float(FOG_STEP)) - 0.5) / 32.0) ).r;\n\
}\n\
\n\
if (polyEnableFog)\n\
{\n\
outFogWeight = (stateEnableFogAlphaOnly) ? vec4(vec3(0.0), fogMixWeight) : vec4(fogMixWeight);\n\
}\n\
\n\
gl_FragColor = outFogWeight;\n\
gl_FragColor = (polyEnableFog) ? ((stateEnableFogAlphaOnly) ? vec4(vec3(0.0), fogMixWeight) : vec4(fogMixWeight)) : vec4(0.0);\n\
}\n\
"};
@ -1300,10 +1258,11 @@ OpenGLRenderer::OpenGLRenderer()
_isFBOBlitSupported = false;
isMultisampledFBOSupported = false;
isShaderSupported = false;
_isSampleShadingSupported = false;
isVAOSupported = false;
_isDepthLEqualPolygonFacingSupported = false;
willFlipAndConvertFramebufferOnGPU = false;
willUsePerSampleZeroDstPass = false;
_willUseMultisampleShaders = false;
_emulateShadowPolygon = true;
_emulateSpecialZeroAlphaBlending = true;
@ -2253,7 +2212,16 @@ Render3DError OpenGLRenderer::ApplyRenderingSettings(const GFX3D_State &renderSt
this->_emulateDepthLEqualPolygonFacing = CommonSettings.OpenGL_Emulation_DepthLEqualPolygonFacing && this->_isDepthLEqualPolygonFacingSupported;
this->_selectedMultisampleSize = CommonSettings.GFX3D_Renderer_MultisampleSize;
const bool oldMultisampleShadingFlag = this->_willUseMultisampleShaders;
this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported);
this->_willUseMultisampleShaders = this->_isSampleShadingSupported && this->_enableMultisampledRendering;
if (this->_willUseMultisampleShaders != oldMultisampleShadingFlag)
{
// Fog program IDs don't have their own multisampled versions of the IDs, and so we
// need to reset all of the existing IDs so that the fog programs can be regenerated
this->DestroyFogPrograms();
}
error = Render3D::ApplyRenderingSettings(renderState);
if (error != RENDER3DERROR_NOERR)
@ -2842,8 +2810,8 @@ Render3DError OpenGLRenderer_1_2::CreateFBOs()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboColorOutMainID);
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);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 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);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE)
{
@ -3341,7 +3309,7 @@ void OpenGLRenderer_1_2::DestroyGeometryZeroDstAlphaProgram()
OGLRef.fragShaderGeometryZeroDstAlphaID = 0;
}
Render3DError OpenGLRenderer_1_2::CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString)
Render3DError OpenGLRenderer_1_2::CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
@ -3404,11 +3372,13 @@ void OpenGLRenderer_1_2::DestroyEdgeMarkProgram()
{
OGLRenderRef &OGLRef = *this->ref;
if (!this->isShaderSupported || (OGLRef.programEdgeMarkID == 0))
if (!this->isShaderSupported)
{
return;
}
if (OGLRef.programEdgeMarkID != 0)
{
glDetachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID);
glDetachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID);
glDeleteProgram(OGLRef.programEdgeMarkID);
@ -3418,9 +3388,23 @@ void OpenGLRenderer_1_2::DestroyEdgeMarkProgram()
OGLRef.programEdgeMarkID = 0;
OGLRef.vertexEdgeMarkShaderID = 0;
OGLRef.fragmentEdgeMarkShaderID = 0;
}
if (OGLRef.programMSEdgeMarkID != 0)
{
glDetachShader(OGLRef.programMSEdgeMarkID, OGLRef.vertexMSEdgeMarkShaderID);
glDetachShader(OGLRef.programMSEdgeMarkID, OGLRef.fragmentMSEdgeMarkShaderID);
glDeleteProgram(OGLRef.programMSEdgeMarkID);
glDeleteShader(OGLRef.vertexMSEdgeMarkShaderID);
glDeleteShader(OGLRef.fragmentMSEdgeMarkShaderID);
OGLRef.programMSEdgeMarkID = 0;
OGLRef.vertexMSEdgeMarkShaderID = 0;
OGLRef.fragmentMSEdgeMarkShaderID = 0;
}
}
Render3DError OpenGLRenderer_1_2::CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString)
Render3DError OpenGLRenderer_1_2::CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
@ -3485,11 +3469,9 @@ Render3DError OpenGLRenderer_1_2::CreateFogProgram(const OGLFogProgramKey fogPro
glValidateProgram(shaderID.program);
glUseProgram(shaderID.program);
const GLint uniformTexGColor = glGetUniformLocation(shaderID.program, "texInFragColor");
const GLint uniformTexGDepth = glGetUniformLocation(shaderID.program, "texInFragDepth");
const GLint uniformTexGFog = glGetUniformLocation(shaderID.program, "texInFogAttributes");
const GLint uniformTexFogDensityTable = glGetUniformLocation(shaderID.program, "texFogDensityTable");
glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil);
glUniform1i(uniformTexGFog, OGLTextureUnitID_FogAttr);
glUniform1i(uniformTexFogDensityTable, OGLTextureUnitID_LookupTable);
@ -3781,7 +3763,7 @@ Render3DError OpenGLRenderer_1_2::InitPostprocessingPrograms(const char *edgeMar
if (this->isVBOSupported && this->isFBOSupported)
{
error = this->CreateEdgeMarkProgram(edgeMarkVtxShaderCString, edgeMarkFragShaderCString);
error = this->CreateEdgeMarkProgram(false, edgeMarkVtxShaderCString, edgeMarkFragShaderCString);
if (error != OGLERROR_NOERR)
{
return error;
@ -4145,6 +4127,21 @@ void OpenGLRenderer_1_2::_ResolveGeometry()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
}
void OpenGLRenderer_1_2::_ResolveFinalFramebuffer()
{
OGLRenderRef &OGLRef = *this->ref;
if (!this->_enableMultisampledRendering || (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID))
{
return;
}
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateColorOutMainID);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboColorOutMainID);
glBlitFramebufferEXT(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboColorOutMainID);
}
Render3DError OpenGLRenderer_1_2::ReadBackPixels()
{
OGLRenderRef &OGLRef = *this->ref;
@ -4585,9 +4582,11 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry()
this->DisableVertexAttributes();
}
if (!this->_willUseMultisampleShaders)
{
this->_ResolveGeometry();
this->_lastTextureDrawTarget = OGLTextureUnitID_GColor;
}
return OGLERROR_NOERR;
}
@ -4689,7 +4688,7 @@ Render3DError OpenGLRenderer_1_2::PostprocessFramebuffer()
std::map<u32, OGLFogShaderID>::iterator it = this->_fogProgramMap.find(this->_fogProgramKey.key);
if (it == this->_fogProgramMap.end())
{
Render3DError error = this->CreateFogProgram(this->_fogProgramKey, FogVtxShader_100, FogFragShader_100);
Render3DError error = this->CreateFogProgram(this->_fogProgramKey, false, FogVtxShader_100, FogFragShader_100);
if (error != OGLERROR_NOERR)
{
return error;
@ -4734,6 +4733,12 @@ Render3DError OpenGLRenderer_1_2::EndRender()
//needs to happen before endgl because it could free some textureids for expired cache items
texCache.Evict();
if (this->_willUseMultisampleShaders)
{
this->_ResolveFinalFramebuffer();
this->_lastTextureDrawTarget = OGLTextureUnitID_GColor;
}
this->ReadBackPixels();
ENDGL();
@ -5465,7 +5470,7 @@ Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h)
if (this->isVBOSupported && this->isFBOSupported)
{
this->CreateEdgeMarkProgram(EdgeMarkVtxShader_100, EdgeMarkFragShader_100);
this->CreateEdgeMarkProgram(false, EdgeMarkVtxShader_100, EdgeMarkFragShader_100);
}
if (OGLRef.readPixelsBestFormat == GL_BGRA)

View File

@ -625,6 +625,9 @@ struct OGLRenderRef
GLuint texEdgeColorTableID;
GLuint texMSGColorID;
GLuint texMSGWorkingID;
GLuint texMSGDepthStencilID;
GLuint texMSGPolyID;
GLuint texMSGFogAttrID;
GLuint rboMSGColorID;
GLuint rboMSGWorkingID;
@ -637,6 +640,7 @@ struct OGLRenderRef
GLuint fboRenderMutableID;
GLuint fboColorOutMainID;
GLuint fboColorOutWorkingID;
GLuint fboMSIntermediateColorOutMainID;
GLuint fboMSIntermediateRenderID;
GLuint fboMSIntermediateRenderMutableID;
GLuint selectedRenderingFBO;
@ -655,6 +659,10 @@ struct OGLRenderRef
GLuint fragShaderMSGeometryZeroDstAlphaID;
GLuint programMSGeometryZeroDstAlphaID;
GLuint vertexMSEdgeMarkShaderID;
GLuint fragmentMSEdgeMarkShaderID;
GLuint programMSEdgeMarkID;
GLuint vertexEdgeMarkShaderID;
GLuint vertexFogShaderID;
GLuint vertexFramebufferOutput6665ShaderID;
@ -825,9 +833,10 @@ protected:
bool _isFBOBlitSupported;
bool isMultisampledFBOSupported;
bool isShaderSupported;
bool _isSampleShadingSupported;
bool isVAOSupported;
bool willFlipAndConvertFramebufferOnGPU;
bool willUsePerSampleZeroDstPass;
bool _willUseMultisampleShaders;
bool _emulateShadowPolygon;
bool _emulateSpecialZeroAlphaBlending;
@ -889,9 +898,9 @@ protected:
virtual void DestroyGeometryPrograms() = 0;
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString) = 0;
virtual void DestroyGeometryZeroDstAlphaProgram() = 0;
virtual Render3DError CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString) = 0;
virtual Render3DError CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString) = 0;
virtual void DestroyEdgeMarkProgram() = 0;
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString) = 0;
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString) = 0;
virtual void DestroyFogProgram(const OGLFogProgramKey fogProgramKey) = 0;
virtual void DestroyFogPrograms() = 0;
virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString) = 0;
@ -914,6 +923,7 @@ protected:
virtual Render3DError DisableVertexAttributes() = 0;
virtual void _ResolveWorkingBackFacing() = 0;
virtual void _ResolveGeometry() = 0;
virtual void _ResolveFinalFramebuffer() = 0;
virtual Render3DError ReadBackPixels() = 0;
virtual Render3DError DrawShadowPolygon(const GLenum polyPrimitive, const GLsizei vertIndexCount, const GLushort *indexBufferPtr, const bool performDepthEqualTest, const bool enableAlphaDepthWrite, const bool isTranslucent, const u8 opaquePolyID) = 0;
@ -964,9 +974,9 @@ protected:
virtual void DestroyGeometryPrograms();
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual void DestroyGeometryZeroDstAlphaProgram();
virtual Render3DError CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
virtual void DestroyEdgeMarkProgram();
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
virtual void DestroyFogProgram(const OGLFogProgramKey fogProgramKey);
virtual void DestroyFogPrograms();
virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
@ -990,6 +1000,7 @@ protected:
virtual Render3DError ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry();
virtual void _ResolveFinalFramebuffer();
virtual Render3DError ReadBackPixels();
// Base rendering methods

View File

@ -447,9 +447,6 @@ void main()\n\
polyIDInfo[3] = texture(texInPolyID, texCoord[3]);\n\
polyIDInfo[4] = texture(texInPolyID, texCoord[4]);\n\
\n\
bool isWireframe[5];\n\
isWireframe[0] = bool(polyIDInfo[0].g);\n\
\n\
float depth[5];\n\
depth[0] = texture(texInFragDepth, texCoord[0]).r;\n\
depth[1] = texture(texInFragDepth, texCoord[1]).r;\n\
@ -457,6 +454,9 @@ void main()\n\
depth[3] = texture(texInFragDepth, texCoord[3]).r;\n\
depth[4] = texture(texInFragDepth, texCoord[4]).r;\n\
\n\
bool isWireframe[5];\n\
isWireframe[0] = bool(polyIDInfo[0].g);\n\
\n\
outEdgeColor = vec4(0.0, 0.0, 0.0, 0.0);\n\
\n\
if (!isWireframe[0])\n\
@ -477,47 +477,109 @@ void main()\n\
\n\
if ( ((gl_FragCoord.x >= FRAMEBUFFER_SIZE_X-1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[1]) && (depth[0] >= depth[1]) && !isWireframe[1])) )\n\
{\n\
if (gl_FragCoord.x >= FRAMEBUFFER_SIZE_X-1.0)\n\
{\n\
outEdgeColor = state.edgeColor[polyID[0]/8];\n\
}\n\
else\n\
{\n\
outEdgeColor = state.edgeColor[polyID[1]/8];\n\
}\n\
outEdgeColor = (gl_FragCoord.x >= FRAMEBUFFER_SIZE_X-1.0) ? state.edgeColor[polyID[0]/8] : state.edgeColor[polyID[1]/8];\n\
}\n\
else if ( ((gl_FragCoord.y >= FRAMEBUFFER_SIZE_Y-1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[2]) && (depth[0] >= depth[2]) && !isWireframe[2])) )\n\
{\n\
if (gl_FragCoord.y >= FRAMEBUFFER_SIZE_Y-1.0)\n\
{\n\
outEdgeColor = state.edgeColor[polyID[0]/8];\n\
}\n\
else\n\
{\n\
outEdgeColor = state.edgeColor[polyID[2]/8];\n\
}\n\
outEdgeColor = (gl_FragCoord.y >= FRAMEBUFFER_SIZE_Y-1.0) ? state.edgeColor[polyID[0]/8] : state.edgeColor[polyID[2]/8];\n\
}\n\
else if ( ((gl_FragCoord.x < 1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[3]) && (depth[0] >= depth[3]) && !isWireframe[3])) )\n\
{\n\
if (gl_FragCoord.x < 1.0)\n\
{\n\
outEdgeColor = state.edgeColor[polyID[0]/8];\n\
}\n\
else\n\
{\n\
outEdgeColor = state.edgeColor[polyID[3]/8];\n\
}\n\
outEdgeColor = (gl_FragCoord.x < 1.0) ? state.edgeColor[polyID[0]/8] : state.edgeColor[polyID[3]/8];\n\
}\n\
else if ( ((gl_FragCoord.y < 1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[4]) && (depth[0] >= depth[4]) && !isWireframe[4])) )\n\
{\n\
if (gl_FragCoord.y < 1.0)\n\
{\n\
outEdgeColor = state.edgeColor[polyID[0]/8];\n\
outEdgeColor = (gl_FragCoord.y < 1.0) ? state.edgeColor[polyID[0]/8] : state.edgeColor[polyID[4]/8];\n\
}\n\
else\n\
{\n\
outEdgeColor = state.edgeColor[polyID[4]/8];\n\
}\n\
}\n\
"};
// Vertex shader for applying edge marking, GLSL 1.50
const char *MSEdgeMarkVtxShader_150 = {"\
IN_VTX_POSITION vec2 inPosition;\n\
IN_VTX_TEXCOORD0 vec2 inTexCoord0;\n\
\n\
void main()\n\
{\n\
gl_Position = vec4(inPosition, 0.0, 1.0);\n\
}\n\
"};
// Fragment shader for applying edge marking, GLSL 1.50
const char *MSEdgeMarkFragShader_150 = {"\
layout (std140) uniform RenderStates\n\
{\n\
bool enableAntialiasing;\n\
bool enableFogAlphaOnly;\n\
int clearPolyID;\n\
float clearDepth;\n\
float alphaTestRef;\n\
float fogOffset;\n\
float fogStep;\n\
float pad_0;\n\
vec4 fogColor;\n\
vec4 edgeColor[8];\n\
vec4 toonColor[32];\n\
} state;\n\
\n\
uniform sampler2DMS texInFragDepth;\n\
uniform sampler2DMS texInPolyID;\n\
\n\
OUT_COLOR vec4 outEdgeColor;\n\
\n\
void main()\n\
{\n\
vec4 polyIDInfo[5];\n\
polyIDInfo[0] = texelFetch(texInPolyID, ivec2(gl_FragCoord.xy) + ivec2( 0, 0), gl_SampleID);\n\
polyIDInfo[1] = texelFetch(texInPolyID, ivec2(gl_FragCoord.xy) + ivec2( 1, 0), gl_SampleID);\n\
polyIDInfo[2] = texelFetch(texInPolyID, ivec2(gl_FragCoord.xy) + ivec2( 0, 1), gl_SampleID);\n\
polyIDInfo[3] = texelFetch(texInPolyID, ivec2(gl_FragCoord.xy) + ivec2(-1, 0), gl_SampleID);\n\
polyIDInfo[4] = texelFetch(texInPolyID, ivec2(gl_FragCoord.xy) + ivec2( 0,-1), gl_SampleID);\n\
\n\
float depth[5];\n\
depth[0] = texelFetch(texInFragDepth, ivec2(gl_FragCoord.xy) + ivec2( 0, 0), gl_SampleID).r;\n\
depth[1] = texelFetch(texInFragDepth, ivec2(gl_FragCoord.xy) + ivec2( 1, 0), gl_SampleID).r;\n\
depth[2] = texelFetch(texInFragDepth, ivec2(gl_FragCoord.xy) + ivec2( 0, 1), gl_SampleID).r;\n\
depth[3] = texelFetch(texInFragDepth, ivec2(gl_FragCoord.xy) + ivec2(-1, 0), gl_SampleID).r;\n\
depth[4] = texelFetch(texInFragDepth, ivec2(gl_FragCoord.xy) + ivec2( 0,-1), gl_SampleID).r;\n\
\n\
bool isWireframe[5];\n\
isWireframe[0] = bool(polyIDInfo[0].g);\n\
\n\
outEdgeColor = vec4(0.0, 0.0, 0.0, 0.0);\n\
\n\
if (!isWireframe[0])\n\
{\n\
int polyID[5];\n\
polyID[0] = int((polyIDInfo[0].r * 63.0) + 0.5);\n\
polyID[1] = int((polyIDInfo[1].r * 63.0) + 0.5);\n\
polyID[2] = int((polyIDInfo[2].r * 63.0) + 0.5);\n\
polyID[3] = int((polyIDInfo[3].r * 63.0) + 0.5);\n\
polyID[4] = int((polyIDInfo[4].r * 63.0) + 0.5);\n\
\n\
isWireframe[1] = bool(polyIDInfo[1].g);\n\
isWireframe[2] = bool(polyIDInfo[2].g);\n\
isWireframe[3] = bool(polyIDInfo[3].g);\n\
isWireframe[4] = bool(polyIDInfo[4].g);\n\
\n\
bool isEdgeMarkingClearValues = ((polyID[0] != state.clearPolyID) && (depth[0] < state.clearDepth) && !isWireframe[0]);\n\
\n\
if ( ((gl_FragCoord.x >= FRAMEBUFFER_SIZE_X-1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[1]) && (depth[0] >= depth[1]) && !isWireframe[1])) )\n\
{\n\
outEdgeColor = (gl_FragCoord.x >= FRAMEBUFFER_SIZE_X-1.0) ? state.edgeColor[polyID[0]/8] : state.edgeColor[polyID[1]/8];\n\
}\n\
else if ( ((gl_FragCoord.y >= FRAMEBUFFER_SIZE_Y-1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[2]) && (depth[0] >= depth[2]) && !isWireframe[2])) )\n\
{\n\
outEdgeColor = (gl_FragCoord.y >= FRAMEBUFFER_SIZE_Y-1.0) ? state.edgeColor[polyID[0]/8] : state.edgeColor[polyID[2]/8];\n\
}\n\
else if ( ((gl_FragCoord.x < 1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[3]) && (depth[0] >= depth[3]) && !isWireframe[3])) )\n\
{\n\
outEdgeColor = (gl_FragCoord.x < 1.0) ? state.edgeColor[polyID[0]/8] : state.edgeColor[polyID[3]/8];\n\
}\n\
else if ( ((gl_FragCoord.y < 1.0) ? isEdgeMarkingClearValues : ((polyID[0] != polyID[4]) && (depth[0] >= depth[4]) && !isWireframe[4])) )\n\
{\n\
outEdgeColor = (gl_FragCoord.y < 1.0) ? state.edgeColor[polyID[0]/8] : state.edgeColor[polyID[4]/8];\n\
}\n\
}\n\
}\n\
@ -570,16 +632,58 @@ void main()\n\
\n\
if (polyEnableFog)\n\
{\n\
float fogMixWeight = 0.0;\n\
if (FOG_STEP == 0)\n\
{\n\
fogMixWeight = texture( texFogDensityTable, vec2( (inFragDepth <= FOG_OFFSETF) ? 0.0 : 1.0, 0.0 ) ).r;\n\
}\n\
else\n\
{\n\
fogMixWeight = texture( texFogDensityTable, vec2( (inFragDepth * (1024.0/float(FOG_STEP))) + (((-float(FOG_OFFSET)/float(FOG_STEP)) - 0.5) / 32.0), 0.0 ) ).r;\n\
float densitySelect = (FOG_STEP == 0) ? ((inFragDepth <= FOG_OFFSETF) ? 0.0 : 1.0) : (inFragDepth * (1024.0/float(FOG_STEP))) + (((-float(FOG_OFFSET)/float(FOG_STEP)) - 0.5) / 32.0);\n\
float fogMixWeight = texture( texFogDensityTable, vec2(densitySelect, 0.0) ).r;\n\
outFogWeight = (state.enableFogAlphaOnly) ? vec4(vec3(0.0), fogMixWeight) : vec4(fogMixWeight);\n\
}\n\
}\n\
"};
// Vertex shader for applying fog, GLSL 1.50
const char *MSFogVtxShader_150 = {"\
IN_VTX_POSITION vec2 inPosition;\n\
IN_VTX_TEXCOORD0 vec2 inTexCoord0;\n\
\n\
void main()\n\
{\n\
gl_Position = vec4(inPosition, 0.0, 1.0);\n\
}\n\
"};
// Fragment shader for applying fog, GLSL 1.50
const char *MSFogFragShader_150 = {"\
layout (std140) uniform RenderStates\n\
{\n\
bool enableAntialiasing;\n\
bool enableFogAlphaOnly;\n\
int clearPolyID;\n\
float clearDepth;\n\
float alphaTestRef;\n\
float fogOffset;\n\
float fogStep;\n\
float pad_0;\n\
vec4 fogColor;\n\
vec4 edgeColor[8];\n\
vec4 toonColor[32];\n\
} state;\n\
\n\
uniform sampler2DMS texInFragDepth;\n\
uniform sampler2DMS texInFogAttributes;\n\
uniform sampler2D texFogDensityTable;\n\
\n\
OUT_COLOR vec4 outFogWeight;\n\
\n\
void main()\n\
{\n\
float inFragDepth = texelFetch(texInFragDepth, ivec2(gl_FragCoord.xy), gl_SampleID).r;\n\
vec4 inFogAttributes = texelFetch(texInFogAttributes, ivec2(gl_FragCoord.xy), gl_SampleID);\n\
bool polyEnableFog = (inFogAttributes.r > 0.999);\n\
outFogWeight = vec4(0.0);\n\
\n\
if (polyEnableFog)\n\
{\n\
float densitySelect = (FOG_STEP == 0) ? ((inFragDepth <= FOG_OFFSETF) ? 0.0 : 1.0) : (inFragDepth * (1024.0/float(FOG_STEP))) + (((-float(FOG_OFFSET)/float(FOG_STEP)) - 0.5) / 32.0);\n\
float fogMixWeight = texture( texFogDensityTable, vec2(densitySelect, 0.0) ).r;\n\
outFogWeight = (state.enableFogAlphaOnly) ? vec4(vec3(0.0), fogMixWeight) : vec4(fogMixWeight);\n\
}\n\
}\n\
@ -632,7 +736,6 @@ OpenGLRenderer_3_2::OpenGLRenderer_3_2()
_is64kUBOSupported = false;
_isTBOSupported = false;
_isShaderFixedLocationSupported = false;
_isSampleShadingSupported = false;
_isConservativeDepthSupported = false;
_isConservativeDepthAMDSupported = false;
_syncBufferSetup = NULL;
@ -733,21 +836,10 @@ Render3DError OpenGLRenderer_3_2::InitExtensions()
if (this->_isSampleShadingSupported)
{
error = this->CreateMSGeometryZeroDstAlphaProgram(GeometryZeroDstAlphaPixelMaskVtxShader_150, MSGeometryZeroDstAlphaPixelMaskFragShader_150);
if (error == OGLERROR_NOERR)
{
this->willUsePerSampleZeroDstPass = true;
}
else
{
glUseProgram(0);
this->DestroyGeometryPrograms();
this->DestroyGeometryZeroDstAlphaProgram();
this->isShaderSupported = false;
this->_isSampleShadingSupported = false;
this->willUsePerSampleZeroDstPass = false;
this->_isSampleShadingSupported = (error == OGLERROR_NOERR);
return error;
}
error = this->CreateEdgeMarkProgram(true, MSEdgeMarkVtxShader_150, MSEdgeMarkFragShader_150);
this->_isSampleShadingSupported = this->_isSampleShadingSupported && (error == OGLERROR_NOERR);
}
INFO("OpenGL: Successfully created geometry shaders.\n");
@ -827,6 +919,7 @@ Render3DError OpenGLRenderer_3_2::InitExtensions()
this->_isDepthLEqualPolygonFacingSupported = true;
this->_enableMultisampledRendering = ((this->_selectedMultisampleSize >= 2) && this->isMultisampledFBOSupported);
this->_willUseMultisampleShaders = this->_isSampleShadingSupported && this->_enableMultisampledRendering;
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
@ -1065,16 +1158,14 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples)
{
OGLRenderRef &OGLRef = *this->ref;
// Set up FBO render targets
glGenRenderbuffers(1, &OGLRef.rboMSGPolyID);
glGenRenderbuffers(1, &OGLRef.rboMSGFogAttrID);
glGenRenderbuffers(1, &OGLRef.rboMSGDepthStencilID);
#ifdef GL_VERSION_3_2
if (this->willUsePerSampleZeroDstPass)
if (this->_isSampleShadingSupported)
{
glGenTextures(1, &OGLRef.texMSGColorID);
glGenTextures(1, &OGLRef.texMSGWorkingID);
glGenTextures(1, &OGLRef.texMSGDepthStencilID);
glGenTextures(1, &OGLRef.texMSGPolyID);
glGenTextures(1, &OGLRef.texMSGFogAttrID);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID);
@ -1084,6 +1175,18 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples)
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGWorkingID);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, GL_TRUE);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_DepthStencil);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGDepthStencilID);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_DEPTH24_STENCIL8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, GL_TRUE);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGPolyID);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, GL_TRUE);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGFogAttrID);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight, GL_TRUE);
glActiveTexture(GL_TEXTURE0);
}
else
@ -1091,42 +1194,76 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples)
{
glGenRenderbuffers(1, &OGLRef.rboMSGColorID);
glGenRenderbuffers(1, &OGLRef.rboMSGWorkingID);
glGenRenderbuffers(1, &OGLRef.rboMSGDepthStencilID);
glGenRenderbuffers(1, &OGLRef.rboMSGPolyID);
glGenRenderbuffers(1, &OGLRef.rboMSGFogAttrID);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGColorID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGWorkingID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight);
}
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_DEPTH24_STENCIL8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGPolyID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGFogAttrID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_DEPTH24_STENCIL8, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight);
}
// Set up multisampled rendering FBO
glGenFramebuffers(1, &OGLRef.fboMSIntermediateColorOutMainID);
glGenFramebuffers(1, &OGLRef.fboMSIntermediateRenderID);
glGenFramebuffers(1, &OGLRef.fboMSIntermediateRenderMutableID);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateColorOutMainID);
#ifdef GL_VERSION_3_2
if (this->_isSampleShadingSupported)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGWorkingID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGDepthStencilID, 0);
}
else
#endif
{
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboMSGColorID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, OGLRef.rboMSGWorkingID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID);
}
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
INFO("OpenGL: Failed to create multisampled FBO. Multisample antialiasing will be disabled.\n");
this->DestroyMultisampledFBO();
return OGLERROR_FBO_CREATE_ERROR;
}
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderID);
#ifdef GL_VERSION_3_2
if (this->willUsePerSampleZeroDstPass)
if (this->_isSampleShadingSupported)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_WORKING_ATTACHMENT_ID, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGWorkingID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGDepthStencilID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_POLYID_ATTACHMENT_ID, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGPolyID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_FOGATTRIBUTES_ATTACHMENT_ID, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGFogAttrID, 0);
}
else
#endif
{
glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_COLOROUT_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGColorID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_WORKING_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGWorkingID);
}
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_POLYID_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGPolyID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_FOGATTRIBUTES_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGFogAttrID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID);
}
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
@ -1136,24 +1273,29 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples)
return OGLERROR_FBO_CREATE_ERROR;
}
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMSIntermediateRenderMutableID);
#ifdef GL_VERSION_3_2
if (this->willUsePerSampleZeroDstPass)
if (this->_isSampleShadingSupported)
{
glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_COLOROUT_ATTACHMENT_ID, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGColorID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_WORKING_ATTACHMENT_ID, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGWorkingID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGDepthStencilID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_POLYID_ATTACHMENT_ID, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGPolyID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, OGL_FOGATTRIBUTES_ATTACHMENT_ID, GL_TEXTURE_2D_MULTISAMPLE, OGLRef.texMSGFogAttrID, 0);
}
else
#endif
{
glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_COLOROUT_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGColorID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_WORKING_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGWorkingID);
}
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_POLYID_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGPolyID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, OGL_FOGATTRIBUTES_ATTACHMENT_ID, GL_RENDERBUFFER, OGLRef.rboMSGFogAttrID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID);
}
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
@ -1163,6 +1305,9 @@ Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO(GLsizei numSamples)
return OGLERROR_FBO_CREATE_ERROR;
}
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID);
INFO("OpenGL: Successfully created multisampled FBO.\n");
@ -1179,19 +1324,28 @@ void OpenGLRenderer_3_2::DestroyMultisampledFBO()
OGLRenderRef &OGLRef = *this->ref;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateColorOutMainID);
glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderID);
glDeleteFramebuffers(1, &OGLRef.fboMSIntermediateRenderMutableID);
glDeleteTextures(1, &OGLRef.texMSGColorID);
glDeleteTextures(1, &OGLRef.texMSGWorkingID);
glDeleteTextures(1, &OGLRef.texMSGDepthStencilID);
glDeleteTextures(1, &OGLRef.texMSGPolyID);
glDeleteTextures(1, &OGLRef.texMSGFogAttrID);
glDeleteRenderbuffers(1, &OGLRef.rboMSGColorID);
glDeleteRenderbuffers(1, &OGLRef.rboMSGWorkingID);
glDeleteRenderbuffers(1, &OGLRef.rboMSGPolyID);
glDeleteRenderbuffers(1, &OGLRef.rboMSGFogAttrID);
glDeleteRenderbuffers(1, &OGLRef.rboMSGDepthStencilID);
OGLRef.fboMSIntermediateColorOutMainID = 0;
OGLRef.fboMSIntermediateRenderID = 0;
OGLRef.fboMSIntermediateRenderMutableID = 0;
OGLRef.texMSGColorID = 0;
OGLRef.texMSGWorkingID = 0;
OGLRef.texMSGDepthStencilID = 0;
OGLRef.texMSGPolyID = 0;
OGLRef.texMSGFogAttrID = 0;
OGLRef.rboMSGColorID = 0;
OGLRef.rboMSGWorkingID = 0;
OGLRef.rboMSGPolyID = 0;
@ -1222,12 +1376,18 @@ void OpenGLRenderer_3_2::ResizeMultisampledFBOs(GLsizei numSamples)
}
#ifdef GL_VERSION_3_2
if (this->willUsePerSampleZeroDstPass)
if (this->_isSampleShadingSupported)
{
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, w, h, GL_TRUE);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, w, h, GL_TRUE);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_DepthStencil);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_DEPTH24_STENCIL8, w, h, GL_TRUE);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, w, h, GL_TRUE);
glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numSamples, GL_RGBA8, w, h, GL_TRUE);
glActiveTexture(GL_TEXTURE0);
}
else
@ -1237,14 +1397,13 @@ void OpenGLRenderer_3_2::ResizeMultisampledFBOs(GLsizei numSamples)
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8, w, h);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGWorkingID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8, w, h);
}
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_DEPTH24_STENCIL8, w, h);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGPolyID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8, w, h);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGFogAttrID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_RGBA8, w, h);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMSGDepthStencilID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, GL_DEPTH24_STENCIL8, w, h);
}
}
Render3DError OpenGLRenderer_3_2::CreateVAOs()
@ -1737,7 +1896,7 @@ void OpenGLRenderer_3_2::DestroyMSGeometryZeroDstAlphaProgram()
OGLRef.fragShaderMSGeometryZeroDstAlphaID = 0;
}
Render3DError OpenGLRenderer_3_2::CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString)
Render3DError OpenGLRenderer_3_2::CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
@ -1756,6 +1915,12 @@ Render3DError OpenGLRenderer_3_2::CreateEdgeMarkProgram(const char *vtxShaderCSt
{
shaderHeader << "#version 150\n";
}
if (isMultisample)
{
shaderHeader << "#extension GL_ARB_sample_shading : require\n";
}
shaderHeader << "\n";
shaderHeader << "#define FRAMEBUFFER_SIZE_X " << this->_framebufferWidth << ".0 \n";
shaderHeader << "#define FRAMEBUFFER_SIZE_Y " << this->_framebufferHeight << ".0 \n";
@ -1787,12 +1952,29 @@ Render3DError OpenGLRenderer_3_2::CreateEdgeMarkProgram(const char *vtxShaderCSt
std::string vtxShaderCode = shaderHeader.str() + vsHeader.str() + std::string(vtxShaderCString);
std::string fragShaderCode = shaderHeader.str() + fsHeader.str() + std::string(fragShaderCString);
GLuint programID = 0;
if (isMultisample)
{
error = this->ShaderProgramCreate(OGLRef.vertexMSEdgeMarkShaderID,
OGLRef.fragmentMSEdgeMarkShaderID,
OGLRef.programMSEdgeMarkID,
vtxShaderCode.c_str(),
fragShaderCode.c_str());
programID = OGLRef.programMSEdgeMarkID;
}
else
{
error = this->ShaderProgramCreate(OGLRef.vertexEdgeMarkShaderID,
OGLRef.fragmentEdgeMarkShaderID,
OGLRef.programEdgeMarkID,
vtxShaderCode.c_str(),
fragShaderCode.c_str());
programID = OGLRef.programEdgeMarkID;
}
if (error != OGLERROR_NOERR)
{
INFO("OpenGL: Failed to create the EDGE MARK shader program.\n");
@ -1804,14 +1986,14 @@ Render3DError OpenGLRenderer_3_2::CreateEdgeMarkProgram(const char *vtxShaderCSt
#if defined(GL_VERSION_3_0)
if (!this->_isShaderFixedLocationSupported)
{
glBindAttribLocation(OGLRef.programEdgeMarkID, OGLVertexAttributeID_Position, "inPosition");
glBindAttribLocation(OGLRef.programEdgeMarkID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
glBindFragDataLocation(OGLRef.programEdgeMarkID, 0, "outEdgeColor");
glBindAttribLocation(programID, OGLVertexAttributeID_Position, "inPosition");
glBindAttribLocation(programID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
glBindFragDataLocation(programID, 0, "outEdgeColor");
}
#endif
glLinkProgram(OGLRef.programEdgeMarkID);
if (!this->ValidateShaderProgramLink(OGLRef.programEdgeMarkID))
glLinkProgram(programID);
if (!this->ValidateShaderProgramLink(programID))
{
INFO("OpenGL: Failed to link the EDGE MARK shader program.\n");
glUseProgram(0);
@ -1819,21 +2001,21 @@ Render3DError OpenGLRenderer_3_2::CreateEdgeMarkProgram(const char *vtxShaderCSt
return OGLERROR_SHADER_CREATE_ERROR;
}
glValidateProgram(OGLRef.programEdgeMarkID);
glUseProgram(OGLRef.programEdgeMarkID);
glValidateProgram(programID);
glUseProgram(programID);
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(OGLRef.programEdgeMarkID, "RenderStates");
glUniformBlockBinding(OGLRef.programEdgeMarkID, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
const GLuint uniformBlockRenderStates = glGetUniformBlockIndex(programID, "RenderStates");
glUniformBlockBinding(programID, uniformBlockRenderStates, OGLBindingPointID_RenderStates);
const GLint uniformTexGDepth = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth");
const GLint uniformTexGPolyID = glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID");
const GLint uniformTexGDepth = glGetUniformLocation(programID, "texInFragDepth");
const GLint uniformTexGPolyID = glGetUniformLocation(programID, "texInPolyID");
glUniform1i(uniformTexGDepth, OGLTextureUnitID_DepthStencil);
glUniform1i(uniformTexGPolyID, OGLTextureUnitID_GPolyID);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString)
Render3DError OpenGLRenderer_3_2::CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
@ -1864,6 +2046,12 @@ Render3DError OpenGLRenderer_3_2::CreateFogProgram(const OGLFogProgramKey fogPro
{
shaderHeader << "#version 150\n";
}
if (isMultisample)
{
shaderHeader << "#extension GL_ARB_sample_shading : require\n";
}
shaderHeader << "\n";
std::stringstream vsHeader;
@ -2107,8 +2295,8 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLY *rawPolyList, cons
this->DisableVertexAttributes();
const bool isRunningMSAA = this->isMultisampledFBOSupported && (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID);
const bool isRunningMSAAWithPerSampleShading = isRunningMSAA && this->willUsePerSampleZeroDstPass; // Doing per-sample shading should be a little more accurate than not doing so.
const bool isRunningMSAA = this->_enableMultisampledRendering && (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID);
const bool isRunningMSAAWithPerSampleShading = isRunningMSAA && this->_willUseMultisampleShaders; // Doing per-sample shading will be more accurate than not doing so.
if (isRunningMSAA && !isRunningMSAAWithPerSampleShading)
{
@ -2181,7 +2369,7 @@ void OpenGLRenderer_3_2::_ResolveWorkingBackFacing()
{
OGLRenderRef &OGLRef = *this->ref;
if (!this->_emulateDepthLEqualPolygonFacing || !this->isMultisampledFBOSupported || (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID))
if (!this->_emulateDepthLEqualPolygonFacing || !this->_enableMultisampledRendering || (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID))
{
return;
}
@ -2200,7 +2388,7 @@ void OpenGLRenderer_3_2::_ResolveGeometry()
{
OGLRenderRef &OGLRef = *this->ref;
if (!this->isMultisampledFBOSupported || (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID))
if (!this->_enableMultisampledRendering || (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID))
{
return;
}
@ -2231,6 +2419,21 @@ void OpenGLRenderer_3_2::_ResolveGeometry()
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboRenderID);
}
void OpenGLRenderer_3_2::_ResolveFinalFramebuffer()
{
OGLRenderRef &OGLRef = *this->ref;
if (!this->_enableMultisampledRendering || (OGLRef.selectedRenderingFBO != OGLRef.fboMSIntermediateRenderID))
{
return;
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboMSIntermediateColorOutMainID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboColorOutMainID);
glBlitFramebuffer(0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, 0, 0, (GLint)this->_framebufferWidth, (GLint)this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboColorOutMainID);
}
Render3DError OpenGLRenderer_3_2::ReadBackPixels()
{
OGLRenderRef &OGLRef = *this->ref;
@ -2544,7 +2747,8 @@ Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer()
OGLRenderRef &OGLRef = *this->ref;
// Set up the postprocessing states
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboColorOutMainID);
const GLuint fboPostprocess = (this->_willUseMultisampleShaders) ? OGLRef.fboMSIntermediateColorOutMainID : OGLRef.fboColorOutMainID;
glBindFramebuffer(GL_FRAMEBUFFER, fboPostprocess);
glViewport(0, 0, (GLsizei)this->_framebufferWidth, (GLsizei)this->_framebufferHeight);
glDisable(GL_DEPTH_TEST);
@ -2553,6 +2757,20 @@ Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer()
if (this->_enableEdgeMark)
{
GLuint pGZeroDstAlphaID = 0;
GLuint pEdgeMarkID = 0;
if (this->_willUseMultisampleShaders)
{
pGZeroDstAlphaID = OGLRef.programMSGeometryZeroDstAlphaID;
pEdgeMarkID = OGLRef.programMSEdgeMarkID;
}
else
{
pGZeroDstAlphaID = OGLRef.programGeometryZeroDstAlphaID;
pEdgeMarkID = OGLRef.programEdgeMarkID;
}
if (this->_needsZeroDstAlphaPass && this->_emulateSpecialZeroAlphaBlending)
{
// Pass 1: Determine the pixels with zero alpha
@ -2563,12 +2781,12 @@ Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer()
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0x40);
glUseProgram(OGLRef.programGeometryZeroDstAlphaID);
glUseProgram(pGZeroDstAlphaID);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Pass 2: Unblended edge mark colors to zero-alpha pixels
glDrawBuffer(OGL_COLOROUT_ATTACHMENT_ID);
glUseProgram(OGLRef.programEdgeMarkID);
glUseProgram(pEdgeMarkID);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@ -2581,7 +2799,7 @@ Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer()
}
else
{
glUseProgram(OGLRef.programEdgeMarkID);
glUseProgram(pEdgeMarkID);
glEnable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@ -2594,7 +2812,17 @@ Render3DError OpenGLRenderer_3_2::PostprocessFramebuffer()
std::map<u32, OGLFogShaderID>::iterator it = this->_fogProgramMap.find(this->_fogProgramKey.key);
if (it == this->_fogProgramMap.end())
{
Render3DError error = this->CreateFogProgram(this->_fogProgramKey, FogVtxShader_150, FogFragShader_150);
Render3DError error = OGLERROR_NOERR;
if (this->_willUseMultisampleShaders)
{
error = this->CreateFogProgram(this->_fogProgramKey, true, MSFogVtxShader_150, MSFogFragShader_150);
}
else
{
error = this->CreateFogProgram(this->_fogProgramKey, false, FogVtxShader_150, FogFragShader_150);
}
if (error != OGLERROR_NOERR)
{
return error;
@ -2697,8 +2925,6 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf
Render3DError OpenGLRenderer_3_2::ClearUsingValues(const Color4u8 &clearColor6665, const FragmentAttributes &clearAttributes)
{
OGLRenderRef &OGLRef = *this->ref;
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);
glClearBufferfi(GL_DEPTH_STENCIL, 0, (GLfloat)clearAttributes.depth / (GLfloat)0x00FFFFFF, clearAttributes.opaquePolyID);
@ -2907,16 +3133,30 @@ Render3DError OpenGLRenderer_3_2::SetFramebufferSize(size_t w, size_t h)
this->DestroyFramebufferOutput6665Programs();
this->DestroyMSGeometryZeroDstAlphaProgram();
this->CreateEdgeMarkProgram(EdgeMarkVtxShader_150, EdgeMarkFragShader_150);
this->CreateFramebufferOutput6665Program(0, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150);
this->CreateFramebufferOutput6665Program(1, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150);
this->CreateEdgeMarkProgram(false, EdgeMarkVtxShader_150, EdgeMarkFragShader_150);
const bool oldMultisampleShadingFlag = this->_willUseMultisampleShaders;
if (this->_isSampleShadingSupported)
{
Render3DError shaderError = this->CreateMSGeometryZeroDstAlphaProgram(GeometryZeroDstAlphaPixelMaskVtxShader_150, MSGeometryZeroDstAlphaPixelMaskFragShader_150);
this->willUsePerSampleZeroDstPass = (shaderError == OGLERROR_NOERR);
this->_isSampleShadingSupported = (shaderError == OGLERROR_NOERR);
shaderError = this->CreateEdgeMarkProgram(true, MSEdgeMarkVtxShader_150, MSEdgeMarkFragShader_150);
this->_isSampleShadingSupported = this->_isSampleShadingSupported && (shaderError == OGLERROR_NOERR);
this->_willUseMultisampleShaders = this->_isSampleShadingSupported && this->_enableMultisampledRendering;
}
if (this->_willUseMultisampleShaders != oldMultisampleShadingFlag)
{
// If, for some reason or another, this flag gets changed due to a shader compilation error,
// then reset all fog shader programs now.
this->DestroyFogPrograms();
}
this->CreateFramebufferOutput6665Program(0, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150);
this->CreateFramebufferOutput6665Program(1, FramebufferOutputVtxShader_150, FramebufferOutput6665FragShader_150);
// Call ResizeMultisampledFBOs() after _framebufferWidth and _framebufferHeight are set
// since this method depends on them.
GLsizei sampleSize = this->GetLimitedMultisampleSize();

View File

@ -64,7 +64,6 @@ protected:
bool _is64kUBOSupported;
bool _isTBOSupported;
bool _isShaderFixedLocationSupported;
bool _isSampleShadingSupported;
bool _isConservativeDepthSupported;
bool _isConservativeDepthAMDSupported;
@ -85,8 +84,8 @@ protected:
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateMSGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
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 CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, 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);
@ -97,6 +96,7 @@ protected:
virtual Render3DError ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry();
virtual void _ResolveFinalFramebuffer();
virtual Render3DError ReadBackPixels();
virtual Render3DError BeginRender(const GFX3D_State &renderState, const GFX3D_GeometryList &renderGList);
virtual Render3DError PostprocessFramebuffer();

View File

@ -677,7 +677,7 @@ Render3DError OpenGLESRenderer_3_0::CreateGeometryZeroDstAlphaProgram(const char
return OGLERROR_NOERR;
}
Render3DError OpenGLESRenderer_3_0::CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString)
Render3DError OpenGLESRenderer_3_0::CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
@ -743,7 +743,7 @@ Render3DError OpenGLESRenderer_3_0::CreateEdgeMarkProgram(const char *vtxShaderC
return OGLERROR_NOERR;
}
Render3DError OpenGLESRenderer_3_0::CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString)
Render3DError OpenGLESRenderer_3_0::CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString)
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;

View File

@ -45,8 +45,8 @@ class OpenGLESRenderer_3_0 : public OpenGLRenderer_3_2
protected:
virtual Render3DError CreateGeometryPrograms();
virtual Render3DError CreateGeometryZeroDstAlphaProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateEdgeMarkProgram(const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateEdgeMarkProgram(const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFogProgram(const OGLFogProgramKey fogProgramKey, const bool isMultisample, const char *vtxShaderCString, const char *fragShaderCString);
virtual Render3DError CreateFramebufferOutput6665Program(const size_t outColorIndex, const char *vtxShaderCString, const char *fragShaderCString);
public: