什么是顺序无关渲染

在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. maven项目导入eclipse报错

    错误提示: 原因:未安装maven,缺少ojdbc6.jar包 解决: 一.安装maven 第一步百度搜索Maven官网,进去之后,下载apache-maven-3.5.3-bin.zip,下载完成之 ...

  2. Python可迭代对象和迭代器对象

    可迭代对象iterable: 对象字面意思:Python中一切皆对象.一个实实在在存在的值. 可迭代:更新迭代.迭代是一个重复的过程,每次重复是基于上一次的结果而继续的,每次都有新的内容. 可迭代对象 ...

  3. ThreeJS学习6_几何体相关(BufferGeometry)

    ThreeJS学习6_几何体相关(BufferGeometry) 使用 BufferGeometry 可以有效减少向 GPU 传输几何体相关数据所需的开销 可以自定义顶点位置, 面片索引, 法向量, ...

  4. c++ 获取文件创建时间、修改时间、访问时间、文件内容长度

    int GetFileInfo(string& strPath, int& iCreateTime, int& iModifyTime, int& iAccessTim ...

  5. Rust借用机制的理解分析

    Rust初学者大多会遇到这样的问题: 为什么同一资源不可被同时可变借用和不可变借用? 为什么Rc一定只能是只读的,一定要配合std::cell系列(Cell,RefCell,UnsafeCell)才能 ...

  6. Window Mysql 解压安装

    下载MySQL zip文件 解压后没有data文件夹和my.ini文件, 在根目录下创建my.ini文件,输入如下内容 以管理员身份运行cmd ,进入bin目录 ,运行下列命令,即可. a) mysq ...

  7. AQS 自定义同步锁,挺难的!

    AQS是AbstractQueuedSynchronizer的简称. AbstractQueuedSynchronizer 同步状态 AbstractQueuedSynchronizer 内部有一个s ...

  8. The path "" is not a valid path to the 3.10.0-957.el7.x86_64 kernel headers.

    安装 kernel-devel yum install kernel-devel-$(uname -r)

  9. 最全总结 | 聊聊 Python 办公自动化之 Excel(上)

    1. 前言 在我们日常工作中,经常会使用 Word.Excel.PPT.PDF 等办公软件 但是,经常会遇到一些重复繁琐的事情,这时候手工操作显得效率极其低下:通过 Python 实现办公自动化变的很 ...

  10. Spring源码分析之Bean的创建过程详解

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...