Single Depth peeling 顺序无关渲染(OIT)
什么是顺序无关渲染
在3D渲染中,物体的渲染是按一定的顺序渲染的,这也就可能导致半透明的物体先于不透明的物体渲染,结果就是可能出现半透明物体后的物体由于深度遮挡而没有渲染出来。对于这种情况通常会先渲染所有的不透明物体再渲染半透明物体或者按深度进行排序来解决。但这样仍然无法解决半透明物体之间的透明效果渲染错误问题,特别是物体之间存在交叉无法通过简单的排序来解决。于是就有一些用专门来解决半透明物体渲染算法,OIT算法即Order Independent Transparency(顺序无关的半透明渲染)。Depth Peeling是众多OIT算法里可以得到精确blending结果的一个,在非游戏的3d应用场景中应该还是很有价值的。

两个交叉半透明四边形(未使用OIT渲染)

两个交叉半透明四边形(使用OIT渲染)
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方法
Single Depth peeling 顺序无关渲染(OIT)的更多相关文章
- DirectX11 With Windows SDK--29 计算着色器:内存模型、线程同步;实现顺序无关透明度(OIT)
前言 由于透明混合在不同的绘制顺序下结果会不同,这就要求绘制前要对物体进行排序,然后再从后往前渲染.但即便是仅渲染一个物体(如上一章的水波),也会出现透明绘制顺序不对的情况,普通的绘制是无法避免的.如 ...
- CSharpGL(22)实现顺序无关的半透明渲染(Order-Independent-Transparency)
+BIT祝威+悄悄在此留下版了个权的信息说: CSharpGL(22)实现顺序无关的半透明渲染(Order-Independent-Transparency) 在 GL.Enable(GL_BLEND ...
- NV OIT algorithm : Depth peeling is a fragment-level depth sorting technique
https://developer.nvidia.com/content/interactive-order-independent-transparency Correctly rendering ...
- depth peeling实现半透明
aaarticlea/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aH
- sqlmap映射继承机制及映射字段顺序与SQL查询字段顺序无关
<typeAlias alias="TblSpPartsinfo" type="com.bn.car.biz.supply.dao.po.PartsInfoPO&q ...
- thead、tbody、tfoot与顺序无关
今天发现一个问题,thead.tbody.tfoot等标签的内容排版与顺序无关,做了一个小的实验:
- Unity3D事件函数的执行顺序 - 包含渲染等模块的完整版,中英文对照
原文地址: http://www.cnblogs.com/ysdyaoguai/p/3746828.html In Unity scripting, there are a number of eve ...
- 浏览器加载和渲染html的顺序-css渲染效率的探究
1.浏览器加载和渲染html的顺序1.IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的.2.在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都 ...
- 浏览器加载和渲染html的顺序-css渲染效率的探究(转载)
1.浏览器加载和渲染html的顺序1.IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的.2.在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都 ...
随机推荐
- scrapy 采集数据存入excel
# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to t ...
- Apollo基于K8S的部署以及接入
Apollo镜像服务 基于开源Apollo服务进行相关服务镜像打包,实际将分发apollo-adminservice.apollo-configservice和apollo-portal 这三个镜像安 ...
- js 判断客户端 和 asp.net/C#判断客户端类型
1.js 判断客户端 <script language="JavaScript"> <!-- onload = function browserRedirect( ...
- SELECT INTO与INSERT INTO SELECT用法
SELECT INTO SELECT INTO 语句从一个表复制数据,然后把数据插入到另一个新表中: -- 创建 Websites 的备份,这种写法没走索引导致全表扫描 SELECT * INTO W ...
- 在java的多态调用中,new的是哪一个类就是调用的哪个类的方法。
在java的多态调用中,new的是哪一个类就是调用的哪个类的方法.(x) 原因: ava多态有两种情况:重载和覆写 在覆写中,运用的是动态单分配,是根据new的类型确定对象,从而确定调用的方法: 在重 ...
- ubuntu 16.04 Chrome
打开终端 输入 命令1:sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.list ...
- request-promise post请求微信小程序云函数调用http
微信小程序不支持http调用,但是可以通过服务器或者云函数实现,云函数相当于云服务器中的一段代码,可以使用http协议 首先要云函数安装request-promise,右键云函数,在终端中打开,输入n ...
- 论文解读《Deep Plug-and-Play Super-Resolution for Arbitrary Blur Kernel》
Deep Plug-and-Play Super-Resolution for Arbitrary Blur Kernels: 一旦退化模型被定义,下一步就是使用公式表示能量函数(energy fun ...
- C语言之 判断语句基础与if语句反汇编
0x01.判断语句介绍以及用法 判断语句有哪些? 1.If 用法1: if (条件) { //代码块 } 当条件成立,也就是为True时,执行{}中的代码 用法2: if(条件) { //代码块 } ...
- Jmeter——ForEach Controller&Loop Controller
今天来分享下Jmeter中的2款循环控制器,ForEach Controller和Loop Controller,在使用上还是有所区别. ForEach Controller ForEach Cont ...