Skip to content

Commit

Permalink
Correct alpha compare:
Browse files Browse the repository at this point in the history
- Take into account coverage flags.
  This is still not quite correct without proper coverage emulation.
- Discard pixels with zero alpha if uCvgXAlpha flag is set.
  Resulted pixel coverage is function of pixel alpha multiplied by actual
  coverage in that mode, thus pixel with zero alpha has zero coverage and discarded.

Fixed regression in BAR, issue #866
  • Loading branch information
gonetz committed Mar 12, 2016
1 parent 56f85e0 commit b7369e9
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 29 deletions.
25 changes: 13 additions & 12 deletions src/GLES2/GLSLCombiner_gles2.cpp
Expand Up @@ -145,7 +145,7 @@ void DestroyShaderCombiner() {

ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCombine & _combine) : m_combine(_combine)
{
char strCombiner[1024];
char strCombiner[2048];
m_nInputs = compileCombiner(_color, _alpha, strCombiner);

if (usesTexture()) {
Expand Down Expand Up @@ -179,6 +179,10 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
strFragmentShader.append(" vec_color = vec4(input_color, vShadeColor.a); \n");
strFragmentShader.append(strCombiner);

strFragmentShader.append(
" if (uCvgXAlpha != 0 && alpha2 == 0.0) discard; \n"
);

if (!g_weakGLSL) {
strFragmentShader.append(
" lowp int fogUsage = uFogUsage; \n"
Expand Down Expand Up @@ -253,6 +257,8 @@ void ShaderCombiner::_locateUniforms() {
LocateUniform(uFogMode);
LocateUniform(uFogUsage);
LocateUniform(uAlphaCompareMode);
LocateUniform(uCvgXAlpha);
LocateUniform(uAlphaCvgSel);
LocateUniform(uEnableAlphaTest);
LocateUniform(uEnableDepth);
LocateUniform(uEnableDepthCompare)
Expand Down Expand Up @@ -482,28 +488,23 @@ void ShaderCombiner::updateDepthInfo(bool _bForce) {
void ShaderCombiner::updateAlphaTestInfo(bool _bForce) {
if (gDP.otherMode.cycleType == G_CYC_FILL) {
m_uniforms.uEnableAlphaTest.set(0, _bForce);
m_uniforms.uAlphaTestValue.set(0.0f, _bForce);
} else if (gDP.otherMode.cycleType == G_CYC_COPY) {
if (gDP.otherMode.alphaCompare & G_AC_THRESHOLD) {
m_uniforms.uEnableAlphaTest.set(1, _bForce);
m_uniforms.uAlphaCvgSel.set(0, _bForce);
m_uniforms.uAlphaTestValue.set(0.5f, _bForce);
} else {
m_uniforms.uEnableAlphaTest.set(0, _bForce);
m_uniforms.uAlphaTestValue.set(0.0f, _bForce);
}
} else if (((gDP.otherMode.alphaCompare & G_AC_THRESHOLD) != 0) && (gDP.otherMode.alphaCvgSel == 0) && (gDP.otherMode.forceBlender == 0 || gDP.blendColor.a > 0)) {
} else if ((gDP.otherMode.alphaCompare & G_AC_THRESHOLD) != 0) {
m_uniforms.uEnableAlphaTest.set(1, _bForce);
m_uniforms.uAlphaTestValue.set(max(gDP.blendColor.a, 1.0f / 256.0f), _bForce);
} else if ((gDP.otherMode.alphaCompare == G_AC_DITHER) && (gDP.otherMode.alphaCvgSel == 0)) {
m_uniforms.uEnableAlphaTest.set(1, _bForce);
m_uniforms.uAlphaTestValue.set(0.0f, _bForce);
} else if (gDP.otherMode.cvgXAlpha != 0) {
m_uniforms.uEnableAlphaTest.set(1, _bForce);
m_uniforms.uAlphaTestValue.set(0.125f, _bForce);
m_uniforms.uAlphaTestValue.set(gDP.blendColor.a, _bForce);
m_uniforms.uAlphaCvgSel.set(gDP.otherMode.alphaCvgSel, _bForce);
} else {
m_uniforms.uEnableAlphaTest.set(0, _bForce);
m_uniforms.uAlphaTestValue.set(0.0f, _bForce);
}

m_uniforms.uCvgXAlpha.set(gDP.otherMode.cvgXAlpha, _bForce);
}

void SetMonochromeCombiner() {
Expand Down
4 changes: 4 additions & 0 deletions src/GLES2/Shaders_gles2.h
Expand Up @@ -166,6 +166,8 @@ SHADER_VERSION
"uniform lowp ivec2 uFbFixedAlpha;\n"
"uniform lowp int uSpecialBlendMode;\n"
"uniform lowp int uEnableAlphaTest; \n"
"uniform lowp int uCvgXAlpha; \n"
"uniform lowp int uAlphaCvgSel; \n"
"uniform lowp float uAlphaTestValue;\n"
"uniform mediump vec2 uDepthScale; \n"
"IN lowp vec4 vShadeColor; \n"
Expand Down Expand Up @@ -202,6 +204,8 @@ SHADER_VERSION
"uniform lowp int uFogUsage; \n"
"uniform lowp int uSpecialBlendMode;\n"
"uniform lowp int uEnableAlphaTest; \n"
"uniform lowp int uCvgXAlpha; \n"
"uniform lowp int uAlphaCvgSel; \n"
"uniform lowp float uAlphaTestValue;\n"
"uniform mediump vec2 uDepthScale; \n"
"IN lowp vec4 vShadeColor; \n"
Expand Down
3 changes: 2 additions & 1 deletion src/GLSLCombiner.h
Expand Up @@ -96,7 +96,8 @@ class ShaderCombiner {
uEnableDepth, uEnableDepthCompare, uEnableDepthUpdate,
uDepthMode, uDepthSource, uRenderState, uSpecialBlendMode,
uMaxTile, uTextureDetail, uTexturePersp, uTextureFilterMode, uMSAASamples,
uAlphaCompareMode, uAlphaDitherMode, uColorDitherMode;
uAlphaCompareMode, uAlphaDitherMode, uColorDitherMode,
uCvgXAlpha, uAlphaCvgSel;

fUniform uFogAlpha, uMinLod, uDeltaZ, uAlphaTestValue, uMSAAScale;

Expand Down
25 changes: 13 additions & 12 deletions src/OGL3X/GLSLCombiner_ogl3x.cpp
Expand Up @@ -282,7 +282,7 @@ ShaderCombiner::ShaderCombiner() : m_bNeedUpdate(true)

ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCombine & _combine) : m_combine(_combine), m_bNeedUpdate(true)
{
char strCombiner[1024];
char strCombiner[2048];
m_nInputs = compileCombiner(_color, _alpha, strCombiner);

const bool bUseLod = usesLOD();
Expand Down Expand Up @@ -369,6 +369,10 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
strFragmentShader.append(" vec_color = vec4(input_color, vShadeColor.a); \n");
strFragmentShader.append(strCombiner);

strFragmentShader.append(
" if (uCvgXAlpha != 0 && alpha2 == 0.0) discard; \n"
);

if (config.generalEmulation.enableNoise != 0) {
strFragmentShader.append(
" if (uColorDitherMode == 2) colorNoiseDither(snoise(), color2); \n"
Expand Down Expand Up @@ -484,6 +488,8 @@ void ShaderCombiner::_locateUniforms() {
LocateUniform(uAlphaCompareMode);
LocateUniform(uAlphaDitherMode);
LocateUniform(uColorDitherMode);
LocateUniform(uCvgXAlpha);
LocateUniform(uAlphaCvgSel);
LocateUniform(uEnableLod);
LocateUniform(uEnableAlphaTest);
LocateUniform(uEnableDepth);
Expand Down Expand Up @@ -749,28 +755,23 @@ void ShaderCombiner::updateDepthInfo(bool _bForce) {
void ShaderCombiner::updateAlphaTestInfo(bool _bForce) {
if (gDP.otherMode.cycleType == G_CYC_FILL) {
m_uniforms.uEnableAlphaTest.set(0, _bForce);
m_uniforms.uAlphaTestValue.set(0.0f, _bForce);
} else if (gDP.otherMode.cycleType == G_CYC_COPY) {
if (gDP.otherMode.alphaCompare & G_AC_THRESHOLD) {
m_uniforms.uEnableAlphaTest.set(1, _bForce);
m_uniforms.uAlphaCvgSel.set(0, _bForce);
m_uniforms.uAlphaTestValue.set(0.5f, _bForce);
} else {
m_uniforms.uEnableAlphaTest.set(0, _bForce);
m_uniforms.uAlphaTestValue.set(0.0f, _bForce);
}
} else if (((gDP.otherMode.alphaCompare & G_AC_THRESHOLD) != 0) && (gDP.otherMode.alphaCvgSel == 0) && (gDP.otherMode.forceBlender == 0 || gDP.blendColor.a > 0)) {
} else if ((gDP.otherMode.alphaCompare & G_AC_THRESHOLD) != 0) {
m_uniforms.uEnableAlphaTest.set(1, _bForce);
m_uniforms.uAlphaTestValue.set(max(gDP.blendColor.a, 1.0f / 256.0f), _bForce);
} else if ((gDP.otherMode.alphaCompare == G_AC_DITHER) && (gDP.otherMode.alphaCvgSel == 0)) {
m_uniforms.uEnableAlphaTest.set(1, _bForce);
m_uniforms.uAlphaTestValue.set(0.0f, _bForce);
} else if (gDP.otherMode.cvgXAlpha != 0) {
m_uniforms.uEnableAlphaTest.set(1, _bForce);
m_uniforms.uAlphaTestValue.set(0.125f, _bForce);
m_uniforms.uAlphaTestValue.set(gDP.blendColor.a, _bForce);
m_uniforms.uAlphaCvgSel.set(gDP.otherMode.alphaCvgSel, _bForce);
} else {
m_uniforms.uEnableAlphaTest.set(0, _bForce);
m_uniforms.uAlphaTestValue.set(0.0f, _bForce);
}

m_uniforms.uCvgXAlpha.set(gDP.otherMode.cvgXAlpha, _bForce);
}

std::ostream & operator<< (std::ostream & _os, const ShaderCombiner & _combiner)
Expand Down
4 changes: 4 additions & 0 deletions src/OGL3X/Shaders_ogl3x.h
Expand Up @@ -168,6 +168,8 @@ MAIN_SHADER_VERSION
"uniform lowp ivec2 uFbFixedAlpha;\n"
"uniform lowp int uSpecialBlendMode;\n"
"uniform lowp int uEnableAlphaTest; \n"
"uniform lowp int uCvgXAlpha; \n"
"uniform lowp int uAlphaCvgSel; \n"
"uniform lowp float uAlphaTestValue;\n"
"uniform mediump vec2 uDepthScale; \n"
"in lowp vec4 vShadeColor; \n"
Expand Down Expand Up @@ -215,6 +217,8 @@ MAIN_SHADER_VERSION
"uniform lowp int uFogUsage; \n"
"uniform lowp int uSpecialBlendMode;\n"
"uniform lowp int uEnableAlphaTest; \n"
"uniform lowp int uCvgXAlpha; \n"
"uniform lowp int uAlphaCvgSel; \n"
"uniform lowp float uAlphaTestValue;\n"
"uniform mediump vec2 uDepthScale; \n"
"in lowp vec4 vShadeColor; \n"
Expand Down
18 changes: 14 additions & 4 deletions src/ShaderUtils.cpp
Expand Up @@ -253,12 +253,22 @@ int compileCombiner(Combiner & _color, Combiner & _alpha, char * _strShader)
}
strcpy(_strShader, " alpha1 = ");
int nInputs = _compileCombiner(_alpha.stage[0], AlphaInput, _strShader);

strcat(_strShader,
" if (uEnableAlphaTest != 0) { \n"
" lowp float alphaTestValue = (uAlphaCompareMode == 3 && alpha1 > 0.0) ? snoise() : uAlphaTestValue; \n"
" if (alpha1 < alphaTestValue) discard; \n"
" } \n"
" if (uEnableAlphaTest != 0) { \n"
" lowp float alphaTestValue = (uAlphaCompareMode == 3) ? snoise() : uAlphaTestValue; \n"
" lowp float alphaValue = alpha1; \n"
" if (uAlphaCvgSel == 0) { \n"
" alphaValue += 0.0078125; \n"
" alphaValue = clamp(alphaValue, 0.0, 1.0); \n"
" } else { \n"
" if (uCvgXAlpha != 0) alphaValue *= 0.5; \n"
" else alphaValue = 0.125; \n"
" } \n"
" if (alphaValue < alphaTestValue) discard; \n"
" } \n"
);

strcat(_strShader, " color1 = ");
nInputs |= _compileCombiner(_color.stage[0], ColorInput, _strShader);
strcat(_strShader, fragment_shader_blender);
Expand Down

0 comments on commit b7369e9

Please sign in to comment.