From 0c5c776bb9474a56ea0b7ccb670a839267e8e03f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 17 Nov 2018 18:33:07 -0800 Subject: [PATCH] GPU: Correct shade mapping with 0,0,0 light pos. May need to audit more normalize() usage, if it's consistent in other places. --- GPU/Common/SoftwareTransformCommon.cpp | 12 ++++++++++-- GPU/Directx9/VertexShaderGeneratorDX9.cpp | 6 +++++- GPU/GLES/VertexShaderGeneratorGLES.cpp | 6 +++++- GPU/Vulkan/VertexShaderGeneratorVulkan.cpp | 8 ++++++-- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index b097a4d833..311333e791 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -397,9 +397,17 @@ void SoftwareTransform( auto getLPos = [&](int l) { return Vec3f(getLPosFloat(l, 0), getLPosFloat(l, 1), getLPosFloat(l, 2)); }; + auto calcShadingLPos = [&](int l) { + Vec3f pos = getLPos(l); + if (pos.Length() == 0.0f) { + return Vec3f(0.0f, 0.0f, 1.0f); + } else { + return pos.Normalized(); + } + }; // Might not have lighting enabled, so don't use lighter. - Vec3f lightpos0 = getLPos(gstate.getUVLS0()).Normalized(); - Vec3f lightpos1 = getLPos(gstate.getUVLS1()).Normalized(); + Vec3f lightpos0 = calcShadingLPos(gstate.getUVLS0()); + Vec3f lightpos1 = calcShadingLPos(gstate.getUVLS1()); uv[0] = (1.0f + Dot(lightpos0, worldnormal))/2.0f; uv[1] = (1.0f + Dot(lightpos1, worldnormal))/2.0f; diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.cpp b/GPU/Directx9/VertexShaderGeneratorDX9.cpp index 53ef880c17..9b456fe3a3 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.cpp +++ b/GPU/Directx9/VertexShaderGeneratorDX9.cpp @@ -715,7 +715,11 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage break; case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use dots from light sources. - WRITE(p, " Out.v_texcoord = float3(u_uvscaleoffset.xy * float2(1.0 + dot(normalize(u_lightpos%i), worldnormal), 1.0 + dot(normalize(u_lightpos%i), worldnormal)) * 0.5, 1.0);\n", ls0, ls1); + { + std::string lightFactor0 = StringFromFormat("(length(u_lightpos%i) == 0.0 ? worldnormal.z : dot(normalize(u_lightpos%i), worldnormal))", ls0, ls0); + std::string lightFactor1 = StringFromFormat("(length(u_lightpos%i) == 0.0 ? worldnormal.z : dot(normalize(u_lightpos%i), worldnormal))", ls1, ls1); + WRITE(p, " Out.v_texcoord = float3(u_uvscaleoffset.xy * float2(1.0 + %s, 1.0 + %s) * 0.5, 1.0);\n", lightFactor0.c_str(), lightFactor1.c_str()); + } break; default: diff --git a/GPU/GLES/VertexShaderGeneratorGLES.cpp b/GPU/GLES/VertexShaderGeneratorGLES.cpp index 7efc8e6341..c51da43f75 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.cpp +++ b/GPU/GLES/VertexShaderGeneratorGLES.cpp @@ -810,7 +810,11 @@ void GenerateVertexShader(const VShaderID &id, char *buffer, uint32_t *attrMask, break; case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use dots from light sources. - WRITE(p, " v_texcoord = vec3(u_uvscaleoffset.xy * vec2(1.0 + dot(normalize(u_lightpos%i), worldnormal), 1.0 + dot(normalize(u_lightpos%i), worldnormal)) * 0.5, 1.0);\n", ls0, ls1); + { + std::string lightFactor0 = StringFromFormat("(length(u_lightpos%i) == 0.0 ? worldnormal.z : dot(normalize(u_lightpos%i), worldnormal))", ls0, ls0); + std::string lightFactor1 = StringFromFormat("(length(u_lightpos%i) == 0.0 ? worldnormal.z : dot(normalize(u_lightpos%i), worldnormal))", ls1, ls1); + WRITE(p, " v_texcoord = vec3(u_uvscaleoffset.xy * vec2(1.0 + %s, 1.0 + %s) * 0.5, 1.0);\n", lightFactor0.c_str(), lightFactor1.c_str()); + } break; default: diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index 6d2051828e..e64e81508d 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -602,8 +602,12 @@ bool GenerateVulkanGLSLVertexShader(const VShaderID &id, char *buffer) { break; case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use dots from light sources. - WRITE(p, " v_texcoord = vec3(base.uvscaleoffset.xy * vec2(1.0 + dot(normalize(light.pos[%i]), worldnormal), 1.0 + dot(normalize(light.pos[%i]), worldnormal)) * 0.5, 1.0);\n", ls0, ls1); - break; + { + std::string lightFactor0 = StringFromFormat("(length(light.pos[%i]) == 0.0 ? worldnormal.z : dot(normalize(light.pos[%i]), worldnormal))", ls0, ls0); + std::string lightFactor1 = StringFromFormat("(length(light.pos[%i]) == 0.0 ? worldnormal.z : dot(normalize(light.pos[%i]), worldnormal))", ls1, ls1); + WRITE(p, " v_texcoord = vec3(base.uvscaleoffset.xy * vec2(1.0 + %s, 1.0 + %s) * 0.5, 1.0);\n", lightFactor0.c_str(), lightFactor1.c_str()); + } + break; default: // ILLEGAL