本文共 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)深度缓冲区的备份与还原
在某个场景下, 我们期望在渲染时, 保存当前的深度缓冲区, 然后再开始下一步渲染, 之后再把深度缓冲区还原, 还原后进行下一步.
时序是:- 保存当前深度缓冲区
- 渲染某个场景, 该场景会使用和修改深度缓冲区
- 恢复保存的深度缓冲区
如果做到该步骤呢?
通常我们会考虑把深度模板通过渲染方式,保存到一份新的颜色纹理中; 还原时, 把这份颜色纹理作为输入, 对深度值进行还原. 当然, 前提需要我们把深度缓冲区绑定到了纹理上, 这样子我们就可以把深度模板纹理作为输入向新的颜色纹理中写入. (下面的样例使用的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中,注意读取到值在第一个分量中存储:
// 读取depthfloat 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!