共计 1875 个字符,预计需要花费 5 分钟才能阅读完成。
什么是程序无关渲染
在 3D 渲染中,物体的渲染是按肯定的程序渲染的,这也就可能导致半透明的物体先于不通明的物体渲染,后果就是可能呈现半透明物体后的物体因为深度遮挡而没有渲染进去。对于这种状况通常会先渲染所有的不通明物体再渲染半透明物体或者按深度进行排序来解决。但这样依然无奈解决半透明物体之间的通明成果渲染谬误问题,特地是物体之间存在穿插无奈通过简略的排序来解决。于是就有一些用专门来解决半透明物体渲染算法,OIT 算法即 Order Independent Transparency(程序无关的半透明渲染)。Depth Peeling 是泛滥 OIT 算法里能够失去准确 blending 后果的一个,在非游戏的 3d 利用场景中应该还是很有价值的。
两个穿插半透明四边形(未应用 OIT 渲染)
两个穿插半透明四边形(应用 OIT 渲染)
Single Depth Peeling 原理
Single Depth Peeling 原文
Single Depth Peeling 顾名思义,就是通过屡次绘制,每次绘制剥离离相机最靠近的一层,像剥洋葱一样层层剥开,按程序混合就失去了准确的混合后果。既然有 Single Depth Peeling,还有一种优化版本就是 Dual Depth Peeling,从前后两个方向剥离,不在本次探讨的范畴,有趣味能够参考链接论文。
深度剥离是一种对深度值进行排序的技术。它的原理比拟直观,通常的深度检测是将场景中 Z 值最小的像素输入到屏幕上,就是里相机最近的像素。如此一来就肯定有离相机第二近的点,第三近的点·····。通过屡次渲染的办法,第一次失常渲染,将深度值存入纹理就失去来离相机最近像素的深度和色彩。第二遍渲染时,把每个像素的深度与上次的深度值做比拟,但凡小于上次深度值的都通过测试,在加上 FBO 深度测试的最小值性能就能失去下一个最小的深度值与色彩值,以此类推即可。
毛病
须要剥离 N 次能力实现,就须要 N 个 Pass,N 是深度复杂度。因而性能是重大的瓶颈,另外如何确定 N 也是个问题。
具体流程
1、创立两对色彩纹理和两对 GL_FLOAT 类型的深度纹理用来 pingpong。
2、clear 深度纹理为 0,敞开 OpenGL 混合
2、失常渲染,大于深度纹理上的值都能够通过测试,加上深度缓冲测试的最小深度值就能够失去离相机最近的深度与色彩值。将色彩后果与色彩纹理中的色彩做混合,深度写入深度纹理。
3、应用上次失去的色彩与深度作为输出纹理反复 2 的操作,直到剥离实现。
如何从前向后混合色彩
从前向后间接混合显著是谬误的,然而咱们能够依据混合算法推导出反向混合的算法,具体推导能够参考 Dual Peth Peeling 的 paper。具体混合算法为:
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
如何确定 N
咱们无奈确定须要剥离多少次,因为不同的渲染指标的深度复杂度是不同的。目前来说最好的办法是采纳遮挡查问的形式来检测是否剥离实现。但这种形式须要 GPU 同步,也会带来重大的性能问题。形式如下
GLuint queryId;
glBeginQuery(GL_SAMPLES_PASSED, queryId);
//depth peeling
glEndQuery(GL_SAMPLES_PASSED);
GLuint queryReady = GL_FALSE;
glGetQueryObjectuiv(queryId, GL_QUERY_RESULT_AVAILABLE, &queryReady);
GLuint samples = 0;
glGetQueryObjectuiv(mOITQueryId, GL_QUERY_RESULT, &samples);
samples 为 0 时就剥离实现了,不能 0 则持续剥离。
理论利用中值得注意的中央
因为深度精度问题可能会造成穿插的中央有接缝,具体做法如下:
1、深度缓冲及纹理应用 GL_FLOAT 类型减少精度。
2、纹理须要应用高精度的纹理 precision highp sampler2D;
3、离摄像机过于依然会因为精度有余而呈现接缝,这时就须要动静调整摄像机远近立体来晋升精度
4、优化遮挡查问中的同步操作
5、防止遮挡查问呈现死循环
优化方向
1、本文采纳从前向后剥离,在细节要求不高的状况下能够固定 N,疏忽后续的剥离影响不大。
2、应用 Dpeth Peeling 的优化版本 Dual Dpeth Peeling
3、应用高版本能力反对的 per pixel linked list 办法