How can I read the depth buffer in WebGL?
Asked Answered
S

5

9

Using the WebGL API, how can I get a value from the depth buffer, or in any other way determine 3D coordinates from screen coordinates (i.e. to find a location clicked on), other than by performing my own raycasting?

Superconductivity answered 7/9, 2011 at 0:10 Comment(0)
C
10

Several years have passed, these days the WEBGL_depth_texture extension is widely available... unless you need to support IE.

General usage:

Preparation:

  1. Query the extension (required)
  2. Allocate a separate color and depth texture (gl.DEPTH_COMPONENT)
  3. Combine both textures in to a single framebuffer (gl.COLOR_ATTACHMENT0, gl.DEPTH_ATTACHMENT)

Rendering:

  1. Bind the framebuffer, render your scene (usually a simplified version)
  2. Unbind the framebuffer, pass the depth texture to your shaders and read it like any other texture:

    texPos.xyz = (gl_Position.xyz / gl_Position.w) * 0.5 + 0.5;
    float depthFromZBuffer = texture2D(uTexDepthBuffer, texPos.xy).x;
    
Casavant answered 7/11, 2015 at 9:4 Comment(3)
The question was about reading depth values from JS code, not GLSL.Stepper
@Stepper I think after rendering to your depth buffer you can use JS function WebGLRenderingContext.readPixels() to read from that buffer. developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/…Subinfeudate
seems depth texture cannot be read with readPixels() directly, only formats ALPHA/RGB/RGBA are supported...Momentarily
R
8

I don't know if it's possible to directly access the depth buffer but if you want depth information in a texture, you'll have to create a rgba texture, attach it as a colour attachment to an frame buffer object and render depth information into the texture, using a fragment shader that writes the depth value into gl_FragColor.

For more information, see the answers to one of my older questions: WebGL - render depth to fbo texture does not work

If you google for opengl es and shadow mapping or depth, you'll find more explanations and example source code.

Reece answered 7/9, 2011 at 9:2 Comment(0)
H
4

From section 5.13.12 of the WebGL specification it seems you cannot directly read the depth buffer, so maybe Markus' suggestion is the best way to do it, although you might not neccessarily need an FBO for this.

But if you want to do something like picking, there are other methods for it. Just browse SO, as it has been asked very often.

Heiney answered 7/9, 2011 at 10:36 Comment(1)
I ended up implementing raycasting, for now.Superconductivity
F
1

Not really a duplicate but see also: How to get object in WebGL 3d space from a mouse click coordinate

Aside of unprojecting and casting a ray (and then performing intersection tests against it as needed), your best bet is to look at 'picking'. This won't give exact 3D coordinates, but it is a useful substitute for unprojection when you only care about which object was clicked on, and don't really need per-pixel precision.

Picking in WebGL means to render the entire scene (or at least, the objects you care about) using a specific shader. The shader renders each object with a different unique ID, which is encoded in the red and green channels, using the blue channel as a key (non-blue means no object of interest). The scene is rendered into an offscreen framebuffer so that it's not visible to the end user. Then you read back, using gl.readPixels(), the pixel or pixels of interest and see which object ID was encoded at the given position.

If it helps, see my own implementation of WebGL picking. This implementation picks a rectangular region of pixels; passing in a 1x1 region results in picking at a single pixel. See also the functions at lines 146, 162, and 175.

Fictional answered 10/9, 2011 at 18:51 Comment(0)
S
1

As of January 23, 2012, there is a draft WebGL extension to enable depth buffer reading, WEBGL_depth_texture. I have no information about its availability in implementations, but I do not expect it at this early date.

Superconductivity answered 4/2, 2012 at 20:5 Comment(1)
That link is dead, but I found this on the website: khronos.org/registry/webgl/extensions/WEBGL_depth_textureRefrigeration

© 2022 - 2024 — McMap. All rights reserved.