fix(web): declare card shader UV uniforms

three.js does not auto-declare uniforms added via onBeforeCompile, so the
injected uMapRepeat/uMapOffset were undeclared and the card shader failed
to compile, rendering cards transparent. Prepend the declarations to the
vertex shader.
This commit is contained in:
2026-08-14 10:52:54 +08:00
parent 2430be9661
commit 7163451d1f
2 changed files with 16 additions and 6 deletions
@@ -18,8 +18,11 @@ describe('applyMapTransform', () => {
// Uniforms are copied, so the caller's vectors stay reusable.
expect(shader.uniforms.uMapRepeat!.value).toEqual(new THREE.Vector2(0.5, 0.25));
expect(shader.uniforms.uMapOffset!.value).toEqual(new THREE.Vector2(0.1, 0.2));
// The override is injected right after the chunk include, which stays in
// place (it declares `vMapUv`/`uv`).
// The uniforms are declared in the GLSL (three.js does not auto-declare
// uniforms added via `onBeforeCompile`), and the override is injected right
// after the chunk include, which stays in place (it declares `vMapUv`/`uv`).
expect(shader.vertexShader).toContain('uniform vec2 uMapRepeat;');
expect(shader.vertexShader).toContain('uniform vec2 uMapOffset;');
expect(shader.vertexShader).toContain('#include <uv_vertex>\n\tvMapUv = uv * uMapRepeat + uMapOffset;');
});
@@ -14,6 +14,14 @@ import * as THREE from 'three';
* refreshed from `map.matrix` every frame, overwriting any per-material
* transform we set on the shared texture.
*/
// Uniforms added via `onBeforeCompile` are not auto-declared by three.js, so
// they must be declared in the GLSL explicitly (the built-in `mapTransform` is
// declared in `uv_pars_vertex.glsl.js`).
const UNIFORM_DECLS = /* glsl */ `
uniform vec2 uMapRepeat;
uniform vec2 uMapOffset;
`;
const VERTEX_INJECT = /* glsl */ `
#include <uv_vertex>
vMapUv = uv * uMapRepeat + uMapOffset;
@@ -36,9 +44,8 @@ export function applyMapTransform(
material.onBeforeCompile = (shader) => {
shader.uniforms.uMapRepeat = { value: r };
shader.uniforms.uMapOffset = { value: o };
shader.vertexShader = shader.vertexShader.replace(
'#include <uv_vertex>',
VERTEX_INJECT,
);
shader.vertexShader =
UNIFORM_DECLS +
shader.vertexShader.replace('#include <uv_vertex>', VERTEX_INJECT);
};
}