mirror of
https://github.com/libretro/ppsspp.git
synced 2025-03-04 22:49:46 +00:00
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:
parent
3cde4921ae
commit
214cc01976
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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()) {
|
||||
|
@ -674,4 +674,4 @@ void EmuScreen::autoLoad() {
|
||||
if (g_Config.bEnableAutoLoad && lastSlot != -1) {
|
||||
SaveState::LoadSlot(lastSlot, 0, 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user