diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index fc943993b454..311333e791c8 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -391,8 +391,23 @@ void SoftwareTransform( case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use two light sources to generate U and V. { - Vec3f lightpos0 = Vec3f(&lighter.lpos[gstate.getUVLS0() * 3]).Normalized(); - Vec3f lightpos1 = Vec3f(&lighter.lpos[gstate.getUVLS1() * 3]).Normalized(); + auto getLPosFloat = [&](int l, int i) { + return getFloat24(gstate.lpos[l * 3 + i]); + }; + 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 = 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/Common/TransformCommon.cpp b/GPU/Common/TransformCommon.cpp index a80b2769e5aa..7e74f321a7e5 100644 --- a/GPU/Common/TransformCommon.cpp +++ b/GPU/Common/TransformCommon.cpp @@ -107,9 +107,9 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ Vec3f lightDir(0, 0, 0); if (type == GE_LIGHTTYPE_DIRECTIONAL) - toLight = Vec3f(&lpos[l * 3]); // lightdir is for spotlights + toLight = Vec3Packedf(&lpos[l * 3]); // lightdir is for spotlights else - toLight = Vec3f(&lpos[l * 3]) - pos; + toLight = Vec3Packedf(&lpos[l * 3]) - pos; bool doSpecular = gstate.isUsingSpecularLight(l); bool poweredDiffuse = gstate.isUsingPoweredDiffuseLight(l); @@ -139,7 +139,7 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ break; case GE_LIGHTTYPE_SPOT: case GE_LIGHTTYPE_UNKNOWN: - lightDir = Vec3f(&ldir[l * 3]); + lightDir = Vec3Packedf(&ldir[l * 3]); angle = Dot(toLight.Normalized(), lightDir.Normalized()); if (angle >= lcutoff[l]) lightScale = clamp(1.0f / (latt[l * 3] + latt[l * 3 + 1] * distanceToLight + latt[l * 3 + 2] * distanceToLight*distanceToLight), 0.0f, 1.0f) * powf(angle, lconv[l]); diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.cpp b/GPU/Directx9/VertexShaderGeneratorDX9.cpp index 53ef880c17d0..9b456fe3a3a0 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 7efc8e6341dd..c51da43f758b 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/Software/Lighting.cpp b/GPU/Software/Lighting.cpp index c322e381a993..2a1e6398aa30 100644 --- a/GPU/Software/Lighting.cpp +++ b/GPU/Software/Lighting.cpp @@ -38,7 +38,8 @@ void Process(VertexData& vertex, bool hasColor) // TODO: Not sure if this really should be done even if lighting is disabled altogether if (gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP) { Vec3 L = Vec3(getFloat24(gstate.lpos[3 * light]), getFloat24(gstate.lpos[3 * light + 1]),getFloat24(gstate.lpos[3 * light + 2])); - float diffuse_factor = Dot(L.Normalized(), vertex.worldnormal); + // In other words, L.Length() == 0.0f means Dot({0, 0, 1}, worldnormal). + float diffuse_factor = L.Length() == 0.0f ? vertex.worldnormal.z : Dot(L.Normalized(), vertex.worldnormal); if (gstate.getUVLS0() == (int)light) vertex.texturecoords.s() = (diffuse_factor + 1.f) / 2.f; diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index 6d2051828ef2..e64e81508d6d 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