The position is read once as (x, y, z, 1) for the clip, fog, texgen and
light vector rows, and lighting works on Vec4F32 throughout, without
going through arrays. Each light's constant term, its position minus
the world translation, is computed once per state instead of per
vertex. The texture matrix rows are now prepared with the transform
state, so loading that matrix dirties it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The GE never forms a world position for lighting: the vector to a point
or spot light is the light position minus the world translation, minus
the model position times the world matrix, summed like a matrix row.
gpu/probe exp153-158 (point lights 0.02-20 units away, spot exponents up
to 40, game-like world matrices; exp153 is a Syphon Filter vertex) are
exact, and Syphon Filter (#13568) becomes exact.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Found by the probe regression run on the first lighting probes:
- The normal stays as the world matrix leaves it, and N.L and N.H are
scaled by its GE reciprocal length, like the spot direction. Exact with
scaled, sheared and rotated world matrices (gpu/probe exp3).
- A negative factor (a spot pointing away with cutoff -1) scales the light
by 0 instead of subtracting (exp3, exp4).
- Shade mapping UVs use the same GE arithmetic as lighting (exp2-4).
- The half vector uses the GE's add.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The spot direction isn't normalized: its dot with the light vector is scaled
by the direction's rsqrt. And attenuation and spot scale the light's colors
as separate 8-bit factors rather than one product (gpu/probe exp97-100, exact
on all spot jobs).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Environment map S and T are (N.L + 1) / 2 with L the light's vector as
lighting uses it: from the vertex to the light for point and spot lights,
a zero vector staying zero, and the half vector for a light that does
specular. Whether lighting or the light is enabled still doesn't matter
(gpu/lighting/shademap).
The vertex shader ID now carries the type and computation of the shade
mapping lights (the ubershader reads them from u_lightControl), so both
shader caches get a new version.
Fixes the hair shine in iDOLM@STER SP (#12376).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The viewer is at infinity along view space +z, so in world space, where
lighting happens, it's the view matrix's third column rather than
(0,0,1): turning the camera moves the highlights (gpu/lighting/specular).
The shaders read it from u_view.
In a Need for Speed Carbon frame replayed on a PSP, this and the pow
bring the error of the cars from MSE 957 to 120 (Vulkan).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
In many cases, games use lighting just for diffuse or something, this
helps skip what's not needed too. Good improvement in a scene from a
Naruto game.