diff --git a/apps/web/src/components/viewers/cardMaterial.test.ts b/apps/web/src/components/viewers/cardMaterial.test.ts index be71c51..ae5de3e 100644 --- a/apps/web/src/components/viewers/cardMaterial.test.ts +++ b/apps/web/src/components/viewers/cardMaterial.test.ts @@ -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 \n\tvMapUv = uv * uMapRepeat + uMapOffset;'); }); diff --git a/apps/web/src/components/viewers/cardMaterial.ts b/apps/web/src/components/viewers/cardMaterial.ts index d2af5fd..9d82e95 100644 --- a/apps/web/src/components/viewers/cardMaterial.ts +++ b/apps/web/src/components/viewers/cardMaterial.ts @@ -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 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 ', - VERTEX_INJECT, - ); + shader.vertexShader = + UNIFORM_DECLS + + shader.vertexShader.replace('#include ', VERTEX_INJECT); }; } \ No newline at end of file