Fix: bind sampler uniforms to a 1x1 transparent texture — null samplers broke shader linking, so no ghosts rendered
This commit is contained in:
@@ -20,10 +20,20 @@ const objCache = new Map();
|
||||
const texLoader = new THREE.TextureLoader();
|
||||
const texCache = new Map();
|
||||
|
||||
/* A sampler2D uniform must ALWAYS be bound to a real texture: leaving it null makes
|
||||
* the shader program fail to link on many GPUs, which would break every untextured
|
||||
* ghost. This 1x1 fully-transparent pixel is the safe no-op binding. */
|
||||
const EMPTY_TEX = (() => {
|
||||
const t = new THREE.DataTexture(new Uint8Array([0, 0, 0, 0]), 1, 1, THREE.RGBAFormat);
|
||||
t.needsUpdate = true;
|
||||
return t;
|
||||
})();
|
||||
|
||||
function loadTexture(url) {
|
||||
if (!url) return null;
|
||||
if (!texCache.has(url)) {
|
||||
const t = texLoader.load(url);
|
||||
const t = texLoader.load(url, undefined, undefined,
|
||||
() => console.warn('texture failed to load:', url)); // keeps the ghost alive
|
||||
t.colorSpace = THREE.SRGBColorSpace;
|
||||
texCache.set(url, t);
|
||||
}
|
||||
@@ -41,8 +51,8 @@ function gradientMaterial(top, bottom, opacity, faceTex, torsoTex, bands) {
|
||||
uMinY: { value: 0 },
|
||||
uMaxY: { value: 1 },
|
||||
uTime: { value: 0 },
|
||||
faceMap: { value: faceTex || null },
|
||||
torsoMap: { value: torsoTex || null },
|
||||
faceMap: { value: faceTex || EMPTY_TEX },
|
||||
torsoMap: { value: torsoTex || EMPTY_TEX },
|
||||
hasFace: { value: faceTex ? 1 : 0 },
|
||||
hasTorso: { value: torsoTex ? 1 : 0 },
|
||||
// [centreY, halfHeight, halfWidth] in normalized model space
|
||||
@@ -136,7 +146,8 @@ function pickModel(manifest, ov) {
|
||||
|
||||
export async function buildGhost(ghost, gradients, manifest, characters) {
|
||||
const ov = resolveOverrides(ghost, characters);
|
||||
const grad = gradients[ghost.color] || gradients.Blue;
|
||||
const grad = (gradients && (gradients[ghost.color] || gradients.Blue))
|
||||
|| { top: '#51eaf1', bottom: '#529eff' }; // survive a missing/!oddly-shaped gradient payload
|
||||
const top = ov.topColor || grad.top;
|
||||
const bottom = ov.bottomColor || grad.bottom;
|
||||
const opacity = ov.opacity != null ? Number(ov.opacity) : 0.92;
|
||||
|
||||
Reference in New Issue
Block a user