什么是顺序无关渲染

在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方法

Single Depth peeling 顺序无关渲染(OIT)的更多相关文章

  1. DirectX11 With Windows SDK--29 计算着色器:内存模型、线程同步;实现顺序无关透明度(OIT)

    前言 由于透明混合在不同的绘制顺序下结果会不同,这就要求绘制前要对物体进行排序,然后再从后往前渲染.但即便是仅渲染一个物体(如上一章的水波),也会出现透明绘制顺序不对的情况,普通的绘制是无法避免的.如 ...

  2. CSharpGL(22)实现顺序无关的半透明渲染(Order-Independent-Transparency)

    +BIT祝威+悄悄在此留下版了个权的信息说: CSharpGL(22)实现顺序无关的半透明渲染(Order-Independent-Transparency) 在 GL.Enable(GL_BLEND ...

  3. NV OIT algorithm : Depth peeling is a fragment-level depth sorting technique

    https://developer.nvidia.com/content/interactive-order-independent-transparency Correctly rendering ...

  4. depth peeling实现半透明

    aaarticlea/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aH

  5. sqlmap映射继承机制及映射字段顺序与SQL查询字段顺序无关

    <typeAlias alias="TblSpPartsinfo" type="com.bn.car.biz.supply.dao.po.PartsInfoPO&q ...

  6. thead、tbody、tfoot与顺序无关

    今天发现一个问题,thead.tbody.tfoot等标签的内容排版与顺序无关,做了一个小的实验:

  7. Unity3D事件函数的执行顺序 - 包含渲染等模块的完整版,中英文对照

    原文地址: http://www.cnblogs.com/ysdyaoguai/p/3746828.html In Unity scripting, there are a number of eve ...

  8. 浏览器加载和渲染html的顺序-css渲染效率的探究

    1.浏览器加载和渲染html的顺序1.IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的.2.在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都 ...

  9. 浏览器加载和渲染html的顺序-css渲染效率的探究(转载)

    1.浏览器加载和渲染html的顺序1.IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的.2.在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都 ...

随机推荐

  1. ansible2.9.5使用become参数实现sudo功能

    一,为什么要使用sudo? 1, 生产环境中,为了安全因素,我们不会直接使用root来登录到server, 确实有需要的情况下,我们再使用sudo切换到root权限. 所以很多ansible的演示直接 ...

  2. 第十八章 HTTPS介绍及实战演练

    一.HTTPS介绍 1.概述 为什么需要使用HTTPS,因为HTTP不安全,当我们使用http网站时,会遭到劫持和篡改,如果采用https协议,那么数据在传输过程中是加密的,所以黑客无法窃取或者篡改数 ...

  3. Python函数名的应用和新特性格式化输出

    1.函数名指向的是函数的内存地址. ​ def func(): print(123) print(func,type(func)) # <function func at 0x000000000 ...

  4. Linux命令提示符

    命令提示符:prompt [root@localhost ~]# 用户@主机名 所在目录 用户身份(#管理员 $普通用户) 显示提示符格式 Ubuntu sun@u18-2:~$ echo $PS1 ...

  5. ucore操作系统学习(三) ucore lab3虚拟内存管理分析

    1. ucore lab3介绍 虚拟内存介绍 在目前的硬件体系结构中,程序要想在计算机中运行,必须先加载至物理主存中.在支持多道程序运行的系统上,我们想要让包括操作系统内核在内的各种程序能并发的执行, ...

  6. GitHub如何删除项目库Repositories

    1.在头像那里找到settings按钮 2.选择repositories 3.找到你要删除的项目 4.点击settings 5.滑到页面最下面,点击delete 7.输入项目名称,复制即可 8.删除后 ...

  7. abp(net core)+easyui+efcore实现仓储管理系统——出库管理之三(五十二)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...

  8. SpringBoot整合原生OpenFegin的坑(非SpringCloud)

    写在前面 最近,在使用SpringBoot+K8S开发微服务系统,既然使用了K8S,我就不想使用SpringCloud了.为啥,因为K8S本身的就提供了非常6的服务注册与发现.限流.熔断.负载均衡等等 ...

  9. Kubernetes 搭建 ES 集群(存储使用 cephfs)

    一.集群规划 使用 cephfs 实现分布式存储和数据持久化 ES 集群的 master 节点至少需要三个,防止脑裂. 由于 master 在配置过程中需要保证主机名固定和唯一,所以搭建 master ...

  10. Hive 如何快速拉取大批量数据

    用hive来做数仓类操作,或者大数据的运算,是没有疑问的,至少在你没有更多选择之前. 当我们要hive来做类似于大批量数据的select时,也许问题就会发生了变化. 1. 通用解决方案之分页 首先,我 ...