As I said in the tittle, this is 100% doable as R3F users been doing it for a while, so how we would do to achieve something similar in plain THREE?
I tried coming up with some methods to get the depth as a texture but I failed miserably
renderer = new THREE.WebGLRenderer({
antialias: false
});
renderer.setClearAlpha(0);
renderer.autoClear = false;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
const depthPassVertexShader = `
varying vec4 projPosition;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
projPosition = gl_Position;
}
`;
const depthPassFragmentShader = `
varying vec4 projPosition;
void main() {
float depth = projPosition.z / projPosition.w;
gl_FragColor = vec4(vec3(depth), 1.0);
}
`;
const depthPassMaterial = new THREE.ShaderMaterial({
vertexShader: depthPassVertexShader,
fragmentShader: depthPassFragmentShader,
});
const depthPassRenderTarget = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight);
function updateDepthImage() {
renderer.setRenderTarget(depthPassRenderTarget);
renderer.render(scene, camera, depthPassMaterial);
renderer.setRenderTarget(null);
const depthTexture = depthPassRenderTarget.depthTexture;
const depthData = new Float32Array(window.innerWidth * window.innerHeight * 4);
renderer.readRenderTargetPixels(depthPassRenderTarget, 0, 0, window.innerWidth, window.innerHeight, depthData);
const canvas = document.createElement("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext("2d");
const imageData = ctx.createImageData(window.innerWidth, window.innerHeight);
for (let i = 0; i < depthData.length; i += 4) {
const depthValue = depthData[i];
const colorValue = Math.floor(depthValue * 255);
imageData.data[i] = colorValue;
imageData.data[i + 1] = colorValue;
imageData.data[i + 2] = colorValue;
imageData.data[i + 3] = 255;
}
ctx.putImageData(imageData, 0, 0);
const depthDataURL = canvas.toDataURL();
const maskedElement = document.querySelector("#chalkBoard");
maskedElement.style.maskImage = `url(${depthDataURL})`;
const renderedImageElement = document.getElementById("renderedImage");
renderedImageElement.src = depthDataURL;
requestAnimationFrame(updateDepthImage);
}
updateDepthImage();
Would THREE.DepthTexture be helpful?
1 Like
That’s perfect, I’ll see if I pull this out. not closing this thread yet tho.