How can I read the depth buffer in WebGL?

馋奶兔 提交于 2019-12-19 02:08:41

问题


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?


回答1:


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;
    



回答2:


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.




回答3:


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.




回答4:


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.




回答5:


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.



来源:https://stackoverflow.com/questions/7327544/how-can-i-read-the-depth-buffer-in-webgl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!