Fix bugs in stencil2alpha, fix bugs in glsl 3 support, enable dual source blending where available

The stencil2alpha bug fixes fix some glows in Wipeout, dual source fixes the rest.
This commit is contained in:
Henrik Rydgard 2013-12-15 12:49:13 +01:00
parent 3cde4921ae
commit 214cc01976
5 changed files with 64 additions and 17 deletions

View File

@ -127,6 +127,11 @@ bool CanReplaceAlphaWithStencil() {
if (!gstate.isStencilTestEnabled()) {
return false;
}
if (gl_extensions.ARB_blend_func_extended) {
return true;
}
if (gstate.isAlphaBlendEnabled()) {
return nonAlphaSrcFactors[gstate.getBlendFuncA()] && nonAlphaDestFactors[gstate.getBlendFuncA()];
}
@ -386,12 +391,16 @@ void GenerateFragmentShader(char *buffer) {
else
WRITE(p, "vec3 roundAndScaleTo255v(in vec3 x) { return floor(x * 255.0 + 0.5); }\n");
}
if (gl_extensions.ARB_blend_func_extended) {
WRITE(p, "out lowp vec4 fragColor0;\n");
WRITE(p, "out lowp vec4 fragColor1;\n");
}
WRITE(p, "void main() {\n");
if (gstate.isModeClear()) {
// Clear mode does not allow any fancy shading.
WRITE(p, " gl_FragColor = v_color0;\n");
WRITE(p, " vec4 v = v_color0;\n");
} else {
const char *secondary = "";
// Secondary color for specular on top of texture
@ -491,31 +500,38 @@ void GenerateFragmentShader(char *buffer) {
if (enableFog) {
WRITE(p, " float fogCoef = clamp(v_fogdepth, 0.0, 1.0);\n");
WRITE(p, " gl_FragColor = mix(vec4(u_fogcolor, v.a), v, fogCoef);\n");
WRITE(p, " v = mix(vec4(u_fogcolor, v.a), v, fogCoef);\n");
// WRITE(p, " v.x = v_depth;\n");
} else {
WRITE(p, " gl_FragColor = v;\n");
}
}
const char *fragColor = "gl_FragColor";
if (gl_extensions.ARB_blend_func_extended) {
WRITE(p, " fragColor0 = vec4(v.rgb, 0.0);\n");
WRITE(p, " fragColor1 = vec4(0.0, 0.0, 0.0, v.a);\n");
fragColor = "fragColor0";
} else {
WRITE(p, " gl_FragColor = v;\n");
}
if (stencilToAlpha) {
switch (ReplaceAlphaWithStencilType()) {
case STENCIL_VALUE_UNIFORM:
WRITE(p, " gl_FragColor.a = u_stencilReplaceValue;\n");
WRITE(p, " %s.a = u_stencilReplaceValue;\n", fragColor);
break;
case STENCIL_VALUE_ZERO:
WRITE(p, " gl_FragColor.a = 0.0;\n");
WRITE(p, " %s.a = 0.0;\n", fragColor);
break;
case STENCIL_VALUE_ONE:
WRITE(p, " gl_FragColor.a = 1.0;\n");
WRITE(p, " %s.a = 1.0;\n", fragColor);
break;
case STENCIL_VALUE_UNKNOWN:
// Maybe we should even mask away alpha using glColorMask and not change it at all? We do get here
// if the stencil mode is KEEP for example.
WRITE(p, " gl_FragColor.a = 0.0;\n");
WRITE(p, " %s.a = 0.0;\n", fragColor);
break;
case STENCIL_VALUE_KEEP:

View File

@ -96,6 +96,14 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans
glBindAttribLocation(program, ATTR_COLOR0, "color0");
glBindAttribLocation(program, ATTR_COLOR1, "color1");
#ifndef USING_GLES2
if (gl_extensions.ARB_blend_func_extended) {
// Dual source alpha
glBindFragDataLocationIndexed(program, 0, 0, "fragColor0");
glBindFragDataLocationIndexed(program, 0, 1, "fragColor1");
}
#endif
glLinkProgram(program);
// Detaching shaders is annoying when debugging with gDebugger
@ -213,6 +221,8 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans
if (u_world != -1) availableUniforms |= DIRTY_WORLDMATRIX;
if (u_view != -1) availableUniforms |= DIRTY_VIEWMATRIX;
if (u_texmtx != -1) availableUniforms |= DIRTY_TEXMATRIX;
if (u_stencilReplaceValue != -1) availableUniforms |= DIRTY_STENCILREPLACEVALUE;
// Looping up to numBones lets us avoid checking u_bone[i]
for (int i = 0; i < numBones; i++) {
if (u_bone[i] != -1)
@ -474,7 +484,7 @@ void LinkedShader::UpdateUniforms(u32 vertType) {
}
if (dirty & DIRTY_STENCILREPLACEVALUE) {
glUniform1f(u_stencilReplaceValue, gstate.getStencilTestRef());
glUniform1f(u_stencilReplaceValue, (float)gstate.getStencilTestRef() * (1.0f / 255.0f));
}
// TODO: Could even set all bones in one go if they're all dirty.
#ifdef USE_BONE_ARRAY

View File

@ -129,6 +129,19 @@ static const GLushort logicOps[] = {
};
#endif
static GLenum toDualSource(GLenum blendfunc) {
switch (blendfunc) {
#ifndef USING_GLES2
case GL_SRC_ALPHA:
return GL_SRC1_ALPHA;
case GL_ONE_MINUS_SRC_ALPHA:
return GL_ONE_MINUS_SRC1_ALPHA;
#endif
default:
return blendfunc;
}
}
static GLenum blendColor2Func(u32 fix) {
if (fix == 0xFFFFFF)
return GL_ONE;
@ -189,6 +202,12 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
// Shortcut by using GL_ONE where possible, no need to set blendcolor
GLuint glBlendFuncA = blendFuncA == GE_SRCBLEND_FIXA ? blendColor2Func(gstate.getFixA()) : aLookup[blendFuncA];
GLuint glBlendFuncB = blendFuncB == GE_DSTBLEND_FIXB ? blendColor2Func(gstate.getFixB()) : bLookup[blendFuncB];
if (gl_extensions.ARB_blend_func_extended) {
glBlendFuncA = toDualSource(glBlendFuncA);
glBlendFuncB = toDualSource(glBlendFuncB);
}
if (blendFuncA == GE_SRCBLEND_FIXA || blendFuncB == GE_DSTBLEND_FIXB) {
Vec3f fixA = Vec3f::FromRGB(gstate.getFixA());
Vec3f fixB = Vec3f::FromRGB(gstate.getFixB());

View File

@ -142,6 +142,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf
// In GLSL ES 3.0, you use "out" variables instead.
bool glslES30 = false;
const char *varying = "varying";
const char *attribute = "attribute";
bool highpFog = false;
#if defined(USING_GLES2)
@ -177,6 +178,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf
#endif
if (glslES30) {
attribute = "in";
varying = "out";
}
@ -209,23 +211,23 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf
}
if (useHWTransform)
WRITE(p, "attribute vec3 position;\n");
WRITE(p, "%s vec3 position;\n", attribute);
else
WRITE(p, "attribute vec4 position;\n"); // need to pass the fog coord in w
WRITE(p, "%s vec4 position;\n", attribute); // need to pass the fog coord in w
if (useHWTransform && hasNormal)
WRITE(p, "attribute mediump vec3 normal;\n");
WRITE(p, "%s mediump vec3 normal;\n", attribute);
if (doTexture) {
if (!useHWTransform && doTextureProjection)
WRITE(p, "attribute vec3 texcoord;\n");
WRITE(p, "%s vec3 texcoord;\n", attribute);
else
WRITE(p, "attribute vec2 texcoord;\n");
WRITE(p, "%s vec2 texcoord;\n", attribute);
}
if (hasColor) {
WRITE(p, "attribute lowp vec4 color0;\n");
WRITE(p, "%s lowp vec4 color0;\n", attribute);
if (lmode && !useHWTransform) // only software transform supplies color1 as vertex data
WRITE(p, "attribute lowp vec3 color1;\n");
WRITE(p, "%s lowp vec3 color1;\n", attribute);
}
if (gstate.isModeThrough()) {

View File

@ -674,4 +674,4 @@ void EmuScreen::autoLoad() {
if (g_Config.bEnableAutoLoad && lastSlot != -1) {
SaveState::LoadSlot(lastSlot, 0, 0);
}
};
}