mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
GPU: Apply fog before color test.
Hardware tests confirm the fog result is what's color tested.
This commit is contained in:
parent
8eb011c22d
commit
022670d882
4 changed files with 52 additions and 80 deletions
|
@ -268,6 +268,11 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
|||
WRITE(p, " float4 v = p;\n"); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (enableColorDoubling) {
|
||||
// This happens before fog is applied.
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
|
||||
}
|
||||
} else {
|
||||
// No texture mapping
|
||||
WRITE(p, " float4 v = In.v_color0 %s;\n", secondary);
|
||||
|
@ -303,12 +308,13 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
|||
}
|
||||
}
|
||||
}
|
||||
if (enableColorTest) {
|
||||
// Color doubling happens before the color test, but we try to optimize doubling when test is off.
|
||||
if (enableColorDoubling) {
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
|
||||
}
|
||||
|
||||
if (enableFog) {
|
||||
WRITE(p, " float fogCoef = clamp(In.v_fogdepth, 0.0, 1.0);\n");
|
||||
WRITE(p, " v = lerp(float4(u_fogcolor, v.a), v, fogCoef);\n");
|
||||
}
|
||||
|
||||
if (enableColorTest) {
|
||||
if (colorTestAgainstZero) {
|
||||
// When testing against 0 (common), we can avoid some math.
|
||||
// 0.002 is approximately half of 1.0 / 255.0.
|
||||
|
@ -342,24 +348,10 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
|||
WRITE(p, lang == HLSL_DX9 ? " clip(-1);\n" : " discard;\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
|
||||
}
|
||||
} else {
|
||||
// If there's no color test, we can potentially double and replace blend at once.
|
||||
if (enableColorDoubling && replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 4.0, 0.0, 2.0);\n");
|
||||
} else if (enableColorDoubling) {
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
|
||||
} else if (replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (enableFog) {
|
||||
WRITE(p, " float fogCoef = clamp(In.v_fogdepth, 0.0, 1.0);\n");
|
||||
WRITE(p, " v = lerp(float4(u_fogcolor, v.a), v, fogCoef);\n");
|
||||
if (replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
|
||||
}
|
||||
|
||||
if (replaceBlend == REPLACE_BLEND_PRE_SRC || replaceBlend == REPLACE_BLEND_PRE_SRC_2X_ALPHA) {
|
||||
|
|
|
@ -500,11 +500,22 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
|
|||
WRITE(p, " vec4 v = p;\n"); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (enableColorDoubling) {
|
||||
// This happens before fog is applied.
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
|
||||
}
|
||||
} else {
|
||||
// No texture mapping
|
||||
WRITE(p, " vec4 v = v_color0 %s;\n", secondary);
|
||||
}
|
||||
|
||||
if (enableFog) {
|
||||
WRITE(p, " float fogCoef = clamp(v_fogdepth, 0.0, 1.0);\n");
|
||||
WRITE(p, " v = mix(vec4(u_fogcolor, v.a), v, fogCoef);\n");
|
||||
// WRITE(p, " v.x = v_depth;\n");
|
||||
}
|
||||
|
||||
// Texture access is at half texels [0.5/256, 255.5/256], but colors are normalized [0, 255].
|
||||
// So we have to scale to account for the difference.
|
||||
std::string alphaTestXCoord = "0";
|
||||
|
@ -558,14 +569,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
|
|||
}
|
||||
|
||||
if (enableColorTest) {
|
||||
// Color doubling happens before the color test, but we try to optimize doubling when test is off.
|
||||
if (enableColorDoubling) {
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
|
||||
if (g_Config.bFragmentTestCache && !colorTestAgainstZero) {
|
||||
WRITE(p, " vScale256.rgb = vScale256.rgb * 2.0;\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (colorTestAgainstZero) {
|
||||
// When testing against 0 (common), we can avoid some math.
|
||||
// 0.002 is approximately half of 1.0 / 255.0.
|
||||
|
@ -608,25 +611,10 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
|
|||
WRITE(p, " %s\n", discardStatement);
|
||||
}
|
||||
}
|
||||
|
||||
if (replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
|
||||
}
|
||||
} else {
|
||||
// If there's no color test, we can potentially double and replace blend at once.
|
||||
if (enableColorDoubling && replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 4.0, 0.0, 2.0);\n");
|
||||
} else if (enableColorDoubling) {
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
|
||||
} else if (replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (enableFog) {
|
||||
WRITE(p, " float fogCoef = clamp(v_fogdepth, 0.0, 1.0);\n");
|
||||
WRITE(p, " v = mix(vec4(u_fogcolor, v.a), v, fogCoef);\n");
|
||||
// WRITE(p, " v.x = v_depth;\n");
|
||||
if (replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
|
||||
}
|
||||
|
||||
if (replaceBlend == REPLACE_BLEND_PRE_SRC || replaceBlend == REPLACE_BLEND_PRE_SRC_2X_ALPHA) {
|
||||
|
|
|
@ -910,14 +910,23 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4<in
|
|||
if (z < gstate.getDepthRangeMin() || z > gstate.getDepthRangeMax())
|
||||
return;
|
||||
|
||||
if (gstate.isColorTestEnabled() && !clearMode)
|
||||
if (!ColorTestPassed(prim_color.rgb()))
|
||||
return;
|
||||
|
||||
if (gstate.isAlphaTestEnabled() && !clearMode)
|
||||
if (!AlphaTestPassed(prim_color.a()))
|
||||
return;
|
||||
|
||||
// Fog is applied prior to color test.
|
||||
if (gstate.isFogEnabled() && !gstate.isModeThrough() && !clearMode) {
|
||||
Vec3<int> fogColor = Vec3<int>::FromRGB(gstate.fogcolor);
|
||||
fogColor = (prim_color.rgb() * (int)fog + fogColor * (255 - (int)fog)) / 255;
|
||||
prim_color.r() = fogColor.r();
|
||||
prim_color.g() = fogColor.g();
|
||||
prim_color.b() = fogColor.b();
|
||||
}
|
||||
|
||||
if (gstate.isColorTestEnabled() && !clearMode)
|
||||
if (!ColorTestPassed(prim_color.rgb()))
|
||||
return;
|
||||
|
||||
// In clear mode, it uses the alpha color as stencil.
|
||||
u8 stencil = clearMode ? prim_color.a() : GetPixelStencil(p.x, p.y);
|
||||
if (!clearMode && (gstate.isStencilTestEnabled() || gstate.isDepthTestEnabled())) {
|
||||
|
@ -945,14 +954,6 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4<in
|
|||
SetPixelDepth(p.x, p.y, z);
|
||||
}
|
||||
|
||||
if (gstate.isFogEnabled() && !gstate.isModeThrough() && !clearMode) {
|
||||
Vec3<int> fogColor = Vec3<int>::FromRGB(gstate.fogcolor);
|
||||
fogColor = (prim_color.rgb() * (int)fog + fogColor * (255 - (int)fog)) / 255;
|
||||
prim_color.r() = fogColor.r();
|
||||
prim_color.g() = fogColor.g();
|
||||
prim_color.b() = fogColor.b();
|
||||
}
|
||||
|
||||
const u32 old_color = GetPixelColor(p.x, p.y);
|
||||
u32 new_color;
|
||||
|
||||
|
|
|
@ -339,6 +339,11 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer) {
|
|||
WRITE(p, " vec4 v = p;\n"); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (enableColorDoubling) {
|
||||
// This happens before fog is applied.
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
|
||||
}
|
||||
} else {
|
||||
// No texture mapping
|
||||
WRITE(p, " vec4 v = v_color0 %s;\n", secondary);
|
||||
|
@ -374,12 +379,13 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer) {
|
|||
}
|
||||
}
|
||||
|
||||
if (enableColorTest) {
|
||||
// Color doubling happens before the color test, but we try to optimize doubling when test is off.
|
||||
if (enableColorDoubling) {
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
|
||||
}
|
||||
if (enableFog) {
|
||||
WRITE(p, " float fogCoef = clamp(v_fogdepth, 0.0, 1.0);\n");
|
||||
WRITE(p, " v = mix(vec4(base.fogcolor, v.a), v, fogCoef);\n");
|
||||
// WRITE(p, " v.x = v_depth;\n");
|
||||
}
|
||||
|
||||
if (enableColorTest) {
|
||||
if (colorTestAgainstZero) {
|
||||
// When testing against 0 (common), we can avoid some math.
|
||||
// Have my doubts that this special case is actually worth it, but whatever.
|
||||
|
@ -403,25 +409,10 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer) {
|
|||
WRITE(p, " %s\n", discardStatement);
|
||||
}
|
||||
}
|
||||
|
||||
if (replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
|
||||
}
|
||||
} else {
|
||||
// If there's no color test, we can potentially double and replace blend at once.
|
||||
if (enableColorDoubling && replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 4.0, 0.0, 2.0);\n");
|
||||
} else if (enableColorDoubling) {
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
|
||||
} else if (replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (enableFog) {
|
||||
WRITE(p, " float fogCoef = clamp(v_fogdepth, 0.0, 1.0);\n");
|
||||
WRITE(p, " v = mix(vec4(base.fogcolor, v.a), v, fogCoef);\n");
|
||||
// WRITE(p, " v.x = v_depth;\n");
|
||||
if (replaceBlend == REPLACE_BLEND_2X_SRC) {
|
||||
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
|
||||
}
|
||||
|
||||
if (replaceBlend == REPLACE_BLEND_PRE_SRC || replaceBlend == REPLACE_BLEND_PRE_SRC_2X_ALPHA) {
|
||||
|
|
Loading…
Add table
Reference in a new issue