Opengl-DepthBuffer存储与还原
发布日期:2021-06-29 14:39:41 浏览次数:2 分类:技术文章

本文共 2837 字,大约阅读时间需要 9 分钟。

参考: http://math.hws.edu/graphicsbook/c7/s4.html

参考: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/framebufferTexture2D
参考: https://stackoverflow.com/questions/27535727/opengl-create-a-depth-stencil-texture-for-reading
参考: https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_frag_depth.txt
参考: https://stackoverflow.com/questions/13171036/visualizing-the-stencil-buffer-to-a-texture/13171346#13171346
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)

深度缓冲区的备份与还原

在某个场景下, 我们期望在渲染时, 保存当前的深度缓冲区, 然后再开始下一步渲染, 之后再把深度缓冲区还原, 还原后进行下一步.

时序是:

  1. 保存当前深度缓冲区
  2. 渲染某个场景, 该场景会使用和修改深度缓冲区
  3. 恢复保存的深度缓冲区

如果做到该步骤呢?

通常我们会考虑把深度模板通过渲染方式,保存到一份新的颜色纹理中;
还原时, 把这份颜色纹理作为输入, 对深度值进行还原.
当然, 前提需要我们把深度缓冲区绑定到了纹理上, 这样子我们就可以把深度模板纹理作为输入向新的颜色纹理中写入.
(下面的样例使用的js+webgl)

深度模板绑定纹理

保存的前提部分, 是我们需要Render to Target, 需要让深度写入到纹理中, 便于我们后续的操作.

新建colorTexture与depthStencilTexture:

var colorTexture = gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,colorTexture);gl.texImage2D(gl.TEXTURE_2D,0,gl.RGBA,512, 512,                              0,gl.RGBA,gl.UNSIGNED_BYTE,null);var depthStencilTexture = gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,depthStencilTexture);gl.texImage2D(gl.TEXTURE_2D,0,gl.DEPTH_STENCIL,512, 512,                              0,gl.UNSIGNED_INT_24_8,gl.UNSIGNED_BYTE,null);

我们新建一个frameBuffer, 把深度纹理depthStencilTexture绑定给它.

var frameBuffer = gl.createFramebuffer();gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);...gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTexture, 0);gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.TEXTURE_2D, depthStencilTexture, 0);

保存深度缓冲区内容

保存深度缓冲区内容, 我们需要注意depthStencil的纹理特点, 读取时的要求.

参考: https://stackoverflow.com/questions/27535727/opengl-create-a-depth-stencil-texture-for-reading

读取深度与模板缓冲是需要分开来读取的:

// Texture Image Unit 0 will treat it as a depth texturegl.glActiveTexture (GL_TEXTURE0);gl.glBindTexture(GL_TEXTURE_2D, depthStencilTexture);// 下面这句话可选,缺省使用了GL_DEPTH_COMPONENTgl.glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);// Texture Image Unit 1 will treat the stencil view of depth_stencil_tex accordinglyglActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, depthStencilTexture);// 注意模板采样出的值是整数glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);

Fragment Shader中,注意读取到值在第一个分量中存储:

// 读取depth

float depth = texture(depthtexture, uv).r;gl_FragColor = encodeDepth(depth); // encodeDepth把一个float打包到rgba四个分量中

注意: 考虑到精度, fragment精度建议使用高精度, 这样获取到的depth值能够精度高一些. 还原时可以稍微精确一定.

深度缓冲区内容的还原

还原深度缓冲区, 是保存的逆过程, 把保存的colorTexture作为输入纹理, 然后在shader中,

置位深度缓冲区的值.

Fragment Shader中

vec4 color = texture(colorTexture, uv);	gl_FragDepthEXT = decodeDepth(color); // decodeDepth把一个rgba四个分量还原到float中

注意: 同样考虑到精度, 建议使用高精度, 这样还原出的gl_FragDepthEXT可以稍微精确高一点.

(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)

转载地址:https://chunyexiyu.blog.csdn.net/article/details/100608860 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:nginx的重编过程
下一篇:IIS的url-rewrite配置预压缩

发表评论

最新留言

不错!
[***.144.177.141]2024年04月11日 01时55分48秒