From 75f2738f5c32bc7a28078983d1a7da2c31e7acbf Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 16 Sep 2013 17:10:19 +0200 Subject: [PATCH] VideoCommon: fix ogl lighting bug which happens because of NaN emulation attn is sometimes very big (eg 1e27), so attn*attn doesn't fit into a float. So the funny part here is: 0.0 * (1e27*1e27) = 0.0 * Inf = NaN As the shader compiler is allowed to change the order of multiplications, this issue isn't fixed completely. --- Source/Core/VideoCommon/Src/LightingShaderGen.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/Src/LightingShaderGen.h b/Source/Core/VideoCommon/Src/LightingShaderGen.h index 09b2dfd257..17dd0a6273 100644 --- a/Source/Core/VideoCommon/Src/LightingShaderGen.h +++ b/Source/Core/VideoCommon/Src/LightingShaderGen.h @@ -78,15 +78,18 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index, "ldir = ldir / dist;\n" "attn = max(0.0f, dot(ldir, " LIGHT_DIR".xyz));\n", LIGHT_DIR_PARAMS(lightsName, index)); - object.Write("attn = max(0.0f, dot(" LIGHT_COSATT".xyz, float3(1.0f, attn, attn*attn))) / dot(" LIGHT_DISTATT".xyz, float3(1.0f,dist,dist2));\n", - LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index)); + // attn*attn may overflow + object.Write("attn = max(0.0f, " LIGHT_COSATT".x + " LIGHT_COSATT".y*attn + " LIGHT_COSATT".z*attn*attn) / dot(" LIGHT_DISTATT".xyz, float3(1.0f,dist,dist2));\n", + LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index)); } else if (chan.attnfunc == 1) { // specular object.Write("ldir = normalize(" LIGHT_POS".xyz);\n", LIGHT_POS_PARAMS(lightsName, index)); object.Write("attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, " LIGHT_DIR".xyz)) : 0.0f;\n", LIGHT_DIR_PARAMS(lightsName, index)); - object.Write("attn = max(0.0f, dot(" LIGHT_COSATT".xyz, float3(1,attn,attn*attn))) / dot(" LIGHT_DISTATT".xyz, float3(1,attn,attn*attn));\n", - LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index)); + // attn*attn may overflow + object.Write("attn = max(0.0f, " LIGHT_COSATT".x + " LIGHT_COSATT".y*attn + " LIGHT_COSATT".z*attn*attn) / (" LIGHT_DISTATT".x + " LIGHT_DISTATT".y*attn + " LIGHT_DISTATT".z*attn*attn);\n", + LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), + LIGHT_DISTATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index)); } switch (chan.diffusefunc)