From a1e2763f32dc5d09cef6afdea07ae5a5d041ca96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 5 Oct 2026 14:02:39 -0600 Subject: [PATCH] GPU: Write 1.0's bits in decimal in the shader pspPow HLSL types an unsuffixed hex literal as uint, so asint(x) - 0x3F800000 went unsigned and wrapped for every x below 1. The huge t then turned into a NaN, and anything lit with specular or powered diffuse came out black on D3D11 (the flags in Everybody's Golf's language select, #22418). GLSL types it as int and was unaffected. Co-Authored-By: Claude Opus 5.5 (1M context) --- GPU/Common/VertexShaderGenerator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index b93ebd085f..8d27eaa676 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -440,7 +440,8 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag // pow is close enough. WRITE(p, "float pspPow(float x, float e) {\n"); if (compat.bitwiseOps) { - WRITE(p, " float t = max(e, 0.0) * float(floatBitsToInt(max(x, 1e-30)) - 0x3F800000) + 1065353216.0;\n"); + // 1065353216 is 1.0's bits. Not written in hex: HLSL makes 0x3F800000 a uint, and the subtraction wraps. + WRITE(p, " float t = max(e, 0.0) * float(floatBitsToInt(max(x, 1e-30)) - 1065353216) + 1065353216.0;\n"); WRITE(p, " return x > 0.0 || e <= 0.0 ? intBitsToFloat(int(max(t, 0.0))) : 0.0;\n"); } else { WRITE(p, " return e <= 0.0 ? 1.0 : pow(max(x, 0.0), e);\n");