OPENGL深度缓存精度问题及解决

    前段时间做的小项目需要读取场景的深度图,本打算使用OPENGL自带函数glReadPiexles()去实现此功能,但OPENGL中只提供读取单个像素处的深度信息,不支持读取整个深度缓存的功能。且当时感觉读取到深度是个单字节的,也看到网上有人说深度缓冲和模板缓冲共用4个字节,就自己使用GLSL改写了渲染管道,将深度信息直接渲染出来,这种方法可生成32位精度的深度图。这段时间又翻阅了OPENGL,发现深度缓冲并不是像网上某些人说的(他们可能指的很久以前或者其它渲染引擎)只占一个或两个字节。OPENGL深度缓冲的可为8,16,24,32都可以,但GLUT没有提出直接 设置方式,自动选择最优的深度位数。而我们若想改变深度缓冲的每个像素所占字节,有以下两种方案:  

    一,使用WINDOWS下的提出的设置渲染场景的方式,设置像素格式,可实现深度位设置。.

  pfd.cDetpBit=24;

  二,使用帧缓存P Frame Buffer为帧缓存设置深度缓存时设置深度位数 //创建FBO


  glGenFramebuffersEXT(1, &fbo);
  glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
  // 创建深度缓存
  glGenRenderbuffersEXT(1, &depthBuffer);
  glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
  glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT32, width, height);//设置为32

     如果想查询当前环境的深度缓存可使用 glGetIntegerv(GL_DEPTH_BITS,&x); 深度缓存的作用就不多说了,下面说说为什么设置深度缓冲的位数和对应的解决方法。深度缓存位数越高,代表深度缓冲的精度也就越高,在通过ZBUFFE进行比较渲染时就不容易出现Z-fight问题,如果当前深度缓冲下,仍出现了Z-fight问题,说明此时深度缓冲精度不够,此外在使用阴影贴图(shadow Map)方式生成阴影时也需要高精度的深度缓冲。

    解决方法主要有三个:

      一,OPENGL中可使用改变深度缓存位数的方式稍加改善,有的显卡已经支持浮点数深度缓存,这个时候使用浮点缓存可更加提高,这个思路 就是尽可能提高深度缓存精度,可解决部分Z-Fighting问题。对于生成阴影的方面,除了采用这个方式外,还可通过过自己SHADER语言重写ZBUFFER缓存的方式来提高精度,这个时候深度信息你可以设置DOUBLE型,也就没有这么多限制,但这种方式增加了计算量。

二,就是通过深度偏移方式来解决Z-fignth问题,OPENGL使用下面方式,

rdener1()//绘制物体glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0f,-1.0f)
rdener2()//绘制物体

这种方式,不同移动,移动后渲染,物体不在原来位置,而使用深度偏移后,物体 仍在原来位置。

三,是网上一位前辈说的,增大近裁剪面距离,公式推导有兴趣的阅读http://www.cnitblog.com/lethep/articles/25570.html

 

猜你喜欢

转载自blog.csdn.net/wang371372/article/details/49745925