Description
When a depth texture is sampled directly in the TSL output AND also sampled inside an If() branch gated by a runtime uniform, the direct output sample breaks when the If() branch is not taken (uniform = 0).
The unused If() branch should have no effect on the output — the depth texture is used unconditionally in the return value. However, the presence of the disabled branch causes the depth texture to read as a constant/incorrect value.
Removing the If() block entirely restores correct behavior.
Reproduction Steps
- Create a render target with a
DepthTexture
- Render a scene to the render target
- In a fullscreen quad's TSL
colorNode, sample the depth texture directly in the output
- Add an
If() branch gated by a uniform(0.0) that also samples the same depth texture
- Observe the depth texture output is broken despite being used unconditionally
- Either remove the
If() block or set the uniform to 1.0 — rendering is correct again
Code
import * as THREE from "three/webgpu";
import { Fn, texture, screenUV, vec4, float, uniform, If, step } from "three/tsl";
async function init() {
const renderer = new THREE.WebGPURenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
await renderer.init();
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.z = 3;
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x222222);
scene.add(new THREE.Mesh(new THREE.SphereGeometry(), new THREE.MeshBasicMaterial()));
const rt = new THREE.RenderTarget(window.innerWidth, window.innerHeight);
rt.depthTexture = new THREE.DepthTexture(window.innerWidth, window.innerHeight);
const featureEnabled = uniform(0.0);
const colorNode = Fn(() => {
const depth = texture(rt.depthTexture, screenUV);
const extra = float(0.0).toVar();
// BUG: This unused If() block breaks the depth sample in the return
If(featureEnabled.greaterThan(0.5), () => {
extra.assign(depth.r);
});
return vec4(step(float(1.0).sub(depth.r), float(0.0)), 0, 0, 1.0);
})();
const quadMat = new THREE.MeshBasicNodeMaterial();
quadMat.colorNode = colorNode;
const quadScene = new THREE.Scene();
quadScene.add(new THREE.Mesh(new THREE.PlaneGeometry(2, 2), quadMat));
const quadCam = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
renderer.setAnimationLoop(() => {
renderer.setRenderTarget(rt);
renderer.render(scene, camera);
renderer.setRenderTarget(null);
renderer.render(quadScene, quadCam);
});
}
init();
Live Example
https://jsfiddle.net/w8v0Lfx2/3/
Version
r183.2
Device
Desktop
Browser
Chrome
OS
MacOS
Description
When a depth texture is sampled directly in the TSL output AND also sampled inside an
If()branch gated by a runtime uniform, the direct output sample breaks when theIf()branch is not taken (uniform = 0).The unused
If()branch should have no effect on the output — the depth texture is used unconditionally in the return value. However, the presence of the disabled branch causes the depth texture to read as a constant/incorrect value.Removing the
If()block entirely restores correct behavior.Reproduction Steps
DepthTexturecolorNode, sample the depth texture directly in the outputIf()branch gated by auniform(0.0)that also samples the same depth textureIf()block or set the uniform to1.0— rendering is correct againCode
Live Example
https://jsfiddle.net/w8v0Lfx2/3/
Version
r183.2
Device
Desktop
Browser
Chrome
OS
MacOS