Implement a specific case of alpha testing (depth discard) using extensions.

This commit is contained in:
Jean-Philip Desjardins 2021-04-15 13:30:23 -04:00
parent 8f201ab7c2
commit 3fddb1fe69
3 changed files with 63 additions and 7 deletions

View file

@ -313,6 +313,10 @@ void CGSH_OpenGL::CheckExtensions()
{ {
m_hasFramebufferFetchExtension = true; m_hasFramebufferFetchExtension = true;
} }
else if(!strcmp(extensionName, "GL_ARM_shader_framebuffer_fetch_depth_stencil"))
{
m_hasFramebufferDepthFetchExtension = true;
}
} }
} }
@ -1125,6 +1129,7 @@ void CGSH_OpenGL::FillShaderCapsFromTest(SHADERCAPS& shaderCaps, const uint64& t
{ {
shaderCaps.hasAlphaTest = m_alphaTestingEnabled ? 1 : 0; shaderCaps.hasAlphaTest = m_alphaTestingEnabled ? 1 : 0;
shaderCaps.alphaTestMethod = test.nAlphaMethod; shaderCaps.alphaTestMethod = test.nAlphaMethod;
shaderCaps.alphaTestFailMethod = test.nAlphaFail;
} }
} }
else else

View file

@ -85,10 +85,11 @@ private:
unsigned int hasFog : 1; unsigned int hasFog : 1;
unsigned int hasAlphaTest : 1; unsigned int hasAlphaTest : 1;
unsigned int alphaTestMethod : 3; unsigned int alphaTestMethod : 3;
unsigned int alphaTestFailMethod : 2;
unsigned int hasDestAlphaTest : 1; unsigned int hasDestAlphaTest : 1;
unsigned int destAlphaTestRef : 1; unsigned int destAlphaTestRef : 1;
unsigned int colorOutputWhite : 1; unsigned int colorOutputWhite : 1;
unsigned int padding : 10; unsigned int padding : 8;
bool isIndexedTextureSource() const bool isIndexedTextureSource() const
{ {
@ -316,7 +317,7 @@ private:
Framework::OpenGl::CShader GenerateVertexShader(const SHADERCAPS&); Framework::OpenGl::CShader GenerateVertexShader(const SHADERCAPS&);
Framework::OpenGl::CShader GenerateFragmentShader(const SHADERCAPS&); Framework::OpenGl::CShader GenerateFragmentShader(const SHADERCAPS&);
std::string GenerateTexCoordClampingSection(TEXTURE_CLAMP_MODE, const char*); std::string GenerateTexCoordClampingSection(TEXTURE_CLAMP_MODE, const char*);
std::string GenerateAlphaTestSection(ALPHA_TEST_METHOD); std::string GenerateAlphaTestSection(ALPHA_TEST_METHOD, ALPHA_TEST_FAIL_METHOD);
Framework::OpenGl::ProgramPtr GeneratePresentProgram(); Framework::OpenGl::ProgramPtr GeneratePresentProgram();
Framework::OpenGl::CBuffer GeneratePresentVertexBuffer(); Framework::OpenGl::CBuffer GeneratePresentVertexBuffer();
@ -462,4 +463,5 @@ private:
VertexBuffer m_vertexBuffer; VertexBuffer m_vertexBuffer;
bool m_hasFramebufferFetchExtension = false; bool m_hasFramebufferFetchExtension = false;
bool m_hasFramebufferDepthFetchExtension = false;
}; };

View file

@ -137,8 +137,35 @@ Framework::OpenGl::CShader CGSH_OpenGL::GenerateFragmentShader(const SHADERCAPS&
{ {
std::stringstream shaderBuilder; std::stringstream shaderBuilder;
bool useFramebufferFetch = false;
bool useFramebufferDepthFetch = false;
auto alphaTestFailMethod = static_cast<ALPHA_TEST_FAIL_METHOD>(caps.alphaTestFailMethod);
if(caps.hasAlphaTest)
{
switch(alphaTestFailMethod)
{
case ALPHA_TEST_FAIL_KEEP:
case ALPHA_TEST_FAIL_RGBONLY:
case ALPHA_TEST_FAIL_ZBONLY:
//TODO: Check how we can implement these correctly
alphaTestFailMethod = ALPHA_TEST_FAIL_KEEP;
break;
case ALPHA_TEST_FAIL_FBONLY:
if(!m_hasFramebufferDepthFetchExtension)
{
alphaTestFailMethod = ALPHA_TEST_FAIL_KEEP;
}
else
{
useFramebufferDepthFetch |= true;
}
break;
}
}
bool writeDestAlphaTest = caps.hasDestAlphaTest && m_hasFramebufferFetchExtension; bool writeDestAlphaTest = caps.hasDestAlphaTest && m_hasFramebufferFetchExtension;
bool useFramebufferFetch = writeDestAlphaTest; useFramebufferFetch |= writeDestAlphaTest;
shaderBuilder << GLSL_VERSION << std::endl; shaderBuilder << GLSL_VERSION << std::endl;
@ -147,6 +174,11 @@ Framework::OpenGl::CShader CGSH_OpenGL::GenerateFragmentShader(const SHADERCAPS&
shaderBuilder << "#extension GL_EXT_shader_framebuffer_fetch : require" << std::endl; shaderBuilder << "#extension GL_EXT_shader_framebuffer_fetch : require" << std::endl;
} }
if(useFramebufferDepthFetch)
{
shaderBuilder << "#extension GL_ARM_shader_framebuffer_fetch_depth_stencil : require" << std::endl;
}
shaderBuilder << "precision mediump float;" << std::endl; shaderBuilder << "precision mediump float;" << std::endl;
shaderBuilder << "in highp float v_depth;" << std::endl; shaderBuilder << "in highp float v_depth;" << std::endl;
@ -233,6 +265,8 @@ Framework::OpenGl::CShader CGSH_OpenGL::GenerateFragmentShader(const SHADERCAPS&
} }
} }
shaderBuilder << " highp float fragDepth = v_depth;" << std::endl;
shaderBuilder << " highp vec3 texCoord = v_texCoord;" << std::endl; shaderBuilder << " highp vec3 texCoord = v_texCoord;" << std::endl;
shaderBuilder << " texCoord.st /= texCoord.p;" << std::endl; shaderBuilder << " texCoord.st /= texCoord.p;" << std::endl;
@ -348,7 +382,7 @@ Framework::OpenGl::CShader CGSH_OpenGL::GenerateFragmentShader(const SHADERCAPS&
if(caps.hasAlphaTest) if(caps.hasAlphaTest)
{ {
shaderBuilder << GenerateAlphaTestSection(static_cast<ALPHA_TEST_METHOD>(caps.alphaTestMethod)); shaderBuilder << GenerateAlphaTestSection(static_cast<ALPHA_TEST_METHOD>(caps.alphaTestMethod), alphaTestFailMethod);
} }
if(caps.hasFog) if(caps.hasFog)
@ -374,7 +408,7 @@ Framework::OpenGl::CShader CGSH_OpenGL::GenerateFragmentShader(const SHADERCAPS&
shaderBuilder << " fragColor.xyz = vec3(1, 1, 1);" << std::endl; shaderBuilder << " fragColor.xyz = vec3(1, 1, 1);" << std::endl;
} }
shaderBuilder << " gl_FragDepth = v_depth;" << std::endl; shaderBuilder << " gl_FragDepth = fragDepth;" << std::endl;
shaderBuilder << "}" << std::endl; shaderBuilder << "}" << std::endl;
@ -418,7 +452,7 @@ std::string CGSH_OpenGL::GenerateTexCoordClampingSection(TEXTURE_CLAMP_MODE clam
return shaderSource; return shaderSource;
} }
std::string CGSH_OpenGL::GenerateAlphaTestSection(ALPHA_TEST_METHOD testMethod) std::string CGSH_OpenGL::GenerateAlphaTestSection(ALPHA_TEST_METHOD testMethod, ALPHA_TEST_FAIL_METHOD testFailMethod)
{ {
std::stringstream shaderBuilder; std::stringstream shaderBuilder;
@ -456,10 +490,25 @@ std::string CGSH_OpenGL::GenerateAlphaTestSection(ALPHA_TEST_METHOD testMethod)
break; break;
} }
const char* testFailOp = " discard;";
switch(testFailMethod)
{
case CGSHandler::ALPHA_TEST_FAIL_KEEP:
testFailOp = " discard;";
break;
case CGSHandler::ALPHA_TEST_FAIL_FBONLY:
//Depth is discarded
testFailOp = " fragDepth = gl_LastFragDepthARM;";
break;
default:
assert(false);
break;
}
shaderBuilder << "uint textureColorAlphaInt = uint(textureColor.a * 255.0);" << std::endl; shaderBuilder << "uint textureColorAlphaInt = uint(textureColor.a * 255.0);" << std::endl;
shaderBuilder << test << std::endl; shaderBuilder << test << std::endl;
shaderBuilder << "{" << std::endl; shaderBuilder << "{" << std::endl;
shaderBuilder << " discard;" << std::endl; shaderBuilder << testFailOp << std::endl;
shaderBuilder << "}" << std::endl; shaderBuilder << "}" << std::endl;
std::string shaderSource = shaderBuilder.str(); std::string shaderSource = shaderBuilder.str();