0

I'm trying to read depth values from framebuffer/WebGLRenderTarget into an array. I can find information to render depth to depth Texture, but could not read the depth to a buffer. With readpixels i could only get rbga values. Ideally i am trying to get worldposition from depth and ray.

I have tried reading pixels, but dont know how to read depth in threejs.

1 Answer 1

5

Off the top of my head it's not possible to read depth values directly.

You can set a DepthTexture to your WebGLRenderTarget's depthTexture property. You can then render all or part of that depth texture to another render target and read the result.

'use strict';

/* global THREE */

const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});

const fov = 75;
const aspect = 2;  // the canvas default
const near = 0.01;
const far = 5;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.z = 0.7;

const scene = new THREE.Scene();
const geometry = new THREE.BoxBufferGeometry();
const material = new THREE.MeshBasicMaterial({color: 'red'});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
cube.position.x = 0.25;
cube.rotation.y = Math.PI * 0.25;
 
const depthTexture = new THREE.DepthTexture(canvas.width, canvas.height);
const rt = new THREE.WebGLRenderTarget(canvas.width, canvas.height, {
  depthTexture,
});

renderer.setRenderTarget(rt);
renderer.render(scene, camera);

const planeScene = new THREE.Scene();
const planeGeo = new THREE.PlaneBufferGeometry(2, 2);
const planeMat = new THREE.MeshBasicMaterial({map: depthTexture});
const plane = new THREE.Mesh(planeGeo, planeMat);
planeScene.add(plane);
const ortho = new THREE.OrthographicCamera(-1, 1, 1, -1, -1, 1)
const planeRT = new THREE.WebGLRenderTarget(canvas.width, canvas.height, {type: THREE.FloatType});
renderer.setRenderTarget(planeRT);
renderer.render(planeScene, ortho);

const depths = new Float32Array(canvas.width * canvas.height * 4);
renderer.readRenderTargetPixels(planeRT, 0, 0, canvas.width, canvas.height, depths);

console.log(depths);
<canvas id="c" width="4" height="4"></canvas>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the help, but ideally we are doing two render passes here. But, WebGL supports direct reading of depth buffers using renderbuffer objects, as mentioned here. khronos.org/registry/webgl/specs/latest/1.0/#5.14.7. May be threejs doesn't have support for renderbuffers. :(
Nothing you linked to suggest you can read directly from a depth buffer. What would you call? readPixels only reads from color attachments. You can't attach a depth buffer as a color attachment. As for passes you can set the second pass to render just 1 pixel, only the pixel you plan to read. It wasn't clear if you were planning to read just one or many but there is no other way to read the depth buffer nor a depth texture.
If it is posiible to read depthbuffer from framebuffer into an array in threejs, why would I render it to depth texture and read from that texture?. The above link says in webgl,khronos.org/registry/webgl/specs/latest/1.0/#5.14.7 you can attach a renderbuffer to framebuffer and read it into renderbuffer. In this case I dont need to do a renderpass right? This is what I understand correct me if i am wrong.
It is not possible to read a depth renderbuffer nor a depth texture directly in WebGL. If you use a depth renderbuffer you can't read it at all. If you use a depth texture you can use that texture as input to a shader but there is no way to read that texture directly. You can only read COLOR textures. You read them by attaching them to a framebuffer as COLOR_ATTACHMENT0 and then calling readPixels. You can't attach a depth texture as COLOR_ATTACHMENT0. You'll get an error since a depth texture can't be used as a COLOR_ATTACHMENT0.
I guess this can be donde indirectly by setting up a fragment shader which assigns a pixel color which depends linearly on the depth in Z (Z component of fragment center position in NDC coordinates). As you can read the output image (color) buffer with gl.readPixels, you can use this idea to access the depth values,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.