Permalink
Browse files

D3D11: Fix pow(0, 0) lighting handling.

This was previously fixed in GLES.
  • Loading branch information...
unknownbrackets committed Sep 9, 2018
1 parent 332788d commit 016d6ba76436a9827f47410a1f518e83d98e55a8
Showing with 22 additions and 13 deletions.
  1. +22 −13 GPU/Directx9/VertexShaderGeneratorDX9.cpp
@@ -604,7 +604,7 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
bool diffuseIsZero = true;
bool specularIsZero = true;
bool distanceNeeded = false;
bool anySpots = false;
if (enableLighting) {
WRITE(p, " float4 lightSum0 = u_ambient * %s + float4(u_matemissive, 0.0);\n", ambientStr);
@@ -618,6 +618,8 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
specularIsZero = false;
if (type != GE_LIGHTTYPE_DIRECTIONAL)
distanceNeeded = true;
if (type == GE_LIGHTTYPE_SPOT || type == GE_LIGHTTYPE_UNKNOWN)
anySpots = true;
}
if (!specularIsZero) {
@@ -631,6 +633,10 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
WRITE(p, " float distance;\n");
WRITE(p, " float lightScale;\n");
}
WRITE(p, " float ldot;\n");
if (anySpots) {
WRITE(p, " float angle;\n");
}
}
// Calculate lights if needed. If shade mapping is enabled, lights may need to be
@@ -654,12 +660,15 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
bool doSpecular = comp != GE_LIGHTCOMP_ONLYDIFFUSE;
bool poweredDiffuse = comp == GE_LIGHTCOMP_BOTHWITHPOWDIFFUSE;
WRITE(p, " ldot = max(dot(toLight, worldnormal), 0.0);\n");
if (poweredDiffuse) {
WRITE(p, " float dot%i = pow(dot(toLight, worldnormal), u_matspecular.a);\n", i);
// TODO: Somehow the NaN check from GLES seems unnecessary here?
// If it returned 0, it'd be wrong, so that's strange.
} else {
WRITE(p, " float dot%i = dot(toLight, worldnormal);\n", i);
// pow(0.0, 0.0) may be undefined, but the PSP seems to treat it as 1.0.
// Seen in Tales of the World: Radiant Mythology (#2424.)
WRITE(p, " if (ldot == 0.0 && u_matspecular.a == 0.0) {\n");
WRITE(p, " ldot = 1.0;\n");
WRITE(p, " } else {\n");
WRITE(p, " ldot = pow(ldot, u_matspecular.a);\n");
WRITE(p, " }\n");
}
const char *timesLightScale = " * lightScale";
@@ -674,9 +683,9 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
break;
case GE_LIGHTTYPE_SPOT:
case GE_LIGHTTYPE_UNKNOWN:
WRITE(p, " float angle%i = dot(normalize(u_lightdir%i), toLight);\n", i, i);
WRITE(p, " if (angle%i >= u_lightangle_spotCoef%i.x) {\n", i, i);
WRITE(p, " lightScale = clamp(1.0 / dot(u_lightatt%i, float3(1.0, distance, distance*distance)), 0.0, 1.0) * pow(angle%i, u_lightangle_spotCoef%i.y);\n", i, i, i);
WRITE(p, " angle = dot(normalize(u_lightdir%i), toLight);\n", i);
WRITE(p, " if (angle >= u_lightangle_spotCoef%i.x) {\n", i);
WRITE(p, " lightScale = clamp(1.0 / dot(u_lightatt%i, float3(1.0, distance, distance*distance)), 0.0, 1.0) * pow(angle, u_lightangle_spotCoef%i.y);\n", i, i);
WRITE(p, " } else {\n");
WRITE(p, " lightScale = 0.0;\n");
WRITE(p, " }\n");
@@ -686,11 +695,11 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
break;
}
WRITE(p, " diffuse = (u_lightdiffuse%i * %s) * max(dot%i, 0.0);\n", i, diffuseStr, i);
WRITE(p, " diffuse = (u_lightdiffuse%i * %s) * ldot;\n", i, diffuseStr);
if (doSpecular) {
WRITE(p, " dot%i = dot(normalize(toLight + float3(0.0, 0.0, 1.0)), worldnormal);\n", i);
WRITE(p, " if (dot%i > 0.0)\n", i);
WRITE(p, " lightSum1 += u_lightspecular%i * %s * (pow(dot%i, u_matspecular.a) %s);\n", i, specularStr, i, timesLightScale);
WRITE(p, " ldot = dot(normalize(toLight + float3(0.0, 0.0, 1.0)), worldnormal);\n");
WRITE(p, " if (ldot > 0.0)\n");
WRITE(p, " lightSum1 += u_lightspecular%i * %s * (pow(ldot, u_matspecular.a) %s);\n", i, specularStr, timesLightScale);
}
WRITE(p, " lightSum0.rgb += (u_lightambient%i * %s.rgb + diffuse)%s;\n", i, ambientStr, timesLightScale);
}

0 comments on commit 016d6ba

Please sign in to comment.