Using depth + mask-image as a way to occlude css3D elements

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?

image

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.