本篇继续讲《全局光照》第4章。

本篇继续讲着色器管理。因为延迟着色需要管理好各种类型物体的着色计算。

对于BRDF模型,游戏场景中大量物体表面都可以用比较统一的材质参数来描述,剩下仅有一些特殊的物体如毛发,皮肤等使用其他特殊材质的模型。多种几何体混在一起使用相同着色器,避免不了分支的处理,对GPU性能造成严重影响,我们看一下神秘海域4是怎么管理的。

两个G-Buffer用来存储每种物体都需要的材质参数,例如法线,位置,粗糙度等,第三个可选的G-Buffer用来存储每种类型特殊的一些材质参数,包括织物,头发,皮肤以及丝绸等等。

GCN架构提供了解码方法允许对任何整数按位解码。

神秘海域的延迟着色阶段使用计算着色器以块为单位进行渲染,其中每个块包含16x16个像素点。在延迟着色阶段,计算着色器分两步处理块中像素:

1.对每个块执行材质类型定义。

2.对每个材质类型分别执行一次计算着色器。

伪代码如下:

首先通过块里的所有像素的材质组合找到对应的shader索引,然后用这个shader去计算这个块的着色。

接下来我们讲一下延迟渲染的反走样。因为MSAA无法在延迟着色上使用,因为他会自动将片元着色器输出的结果拷贝多次,这使得本身就非常巨大的G-buffer更要使用多几倍的存储空间,这又大大增加了延迟着色计算中带宽的占用,因为每个像素要多读取几倍的数据。

而且即使存储和带宽都不是问题,但MSAA着重于解决几何走样,它仍然无法解决着色器走样。

形态反走样MLAA核心算法是找出物体的轮廓信息,并利用这些轮廓信息计算出处于轮廓点上的像素的覆盖率,然后使用一个后处理阶段对轮廓上的像素和相邻的像素进行颜色混合。

它包括三个步骤:

1.根据一定的像素属性找出图像中不连续的像素,并标记这些像素中哪些边处于轮廓边缘。

2.利用这些边缘线段的几何特征计算每个像素与周围像素进行混合的像素权重值。

3.对周围邻近像素按照混合权重进行混合计算。

SMAA是MLAA的增强算法。它包含三个渲染通道:

1.第一通道:首先边缘被存储到一个边缘纹理,纹理中的颜色表示每个边缘在像素中的位置,同时边缘像素的模板值被记录。

2.第二通道:记录每个轮廓上像素的混合权重,为了计算该权重,首先找出每条经过该像素左边和顶部边缘线段的模式,然后计算出该像素距离这些模式线段交叉边缘的距离,然后这两个距离值作为纹理坐标到一个预计算的纹理中进行采样,这个预计算纹理是根据线段模式计算出来的权重分布值。

3.第三通道:根据上一步的权重结果进行混合计算。

进行边缘检测是根据亮度差是否超过阈值来确定的,对每个像素比较它左边和上边像素的亮度值,比较的结构是一个枚举值,这两个枚举值被存在一个纹理中,分别对应上边和左边是否处在边缘。

SMAA用一种适应性双阈值的策略来克服这种问题。其中灰色的点表示当前处理的像素点,黄色表示当前像素点可能的左边边缘,蓝色表示向量像素的边缘。首先计算出所有蓝色边缘中亮度插值病区最大值cmax,然后根据c2l>0.5 * cmax是否为真决定左边缘cl是否存在。

当边缘被标记出来后,混合权重计算包括三个步骤。首先计算出每个像素中心距离其所在形状两端的距离。然后,找出该像素所在形状的交叉边缘,并连接连个交叉边缘的中点构成一条轮廓线,最后根据这个轮廓线算权重。

我们有了每个像素到两个交叉边缘的距离,以及每个交叉边缘的类型,剩下就是利用这些值来计算边缘像素的覆盖面积。我们首先需要将交叉边缘的中点连接起来,然后计算每个像素内梯形的面积,由于每个像素涉及到大量的计算,所以SMAA将这些计算放到一个面积纹理中。

不过SMAA也有自己的问题,他是基于单个像素进行反走样,这样就无法处理着色走样了,例如高光函数等。于是就有了TAA,TAA的大概原理我们讲过。

对于静态场景,要使用TAA,在不同的帧当中相同的像素应该被使用一个抖动jittering操作,以使当前帧的像素被移动到一个超采样中子采样点的位置。抖动的位移通常使用某种随机分布函数产生。该随机分布应该具有低差异性,子采样点应该尽量布满整个像素区域。一般使用Halton sequence来产生子采样点的分布。

为了不影响渲染管线的结构和流程,这个像素抖动通常发生在顶点着色器,修改投影矩阵。

然后还需要一个空间过滤器,最简单使用盒子过滤器,求加权平均,但这样需要存储n个时间的绘制结果。所以一般优化成这样:

将当前渲染结果xt和之前所有帧混合的经过反走样处理的历史结果st-1混合,这是递归指数过滤器。混合系数α决定了图像由走样到平滑过渡的快慢。

当alpha很小的时候,指数逼近结果和加权平均结果是一致的。

动态场景的话,情况会变得复杂。TAA理想状态需要除了采样点位置外完全一致的两个像素点,然而像素移动的时候,一切发生了变化。动态场景带来三个新的问题:

1.首先,需要要给额外的屏幕区域大小的缓存来存储每个历史颜色的位置,者通过延迟着色的G-buffer阶段通过将当前像素位置重投影到上一帧的摄像机的变换矩阵来计算。

2.由于重投影的操作,我们需要在上一帧图像的离散屏幕分辨率中找到一个位置来对历史颜色缓存进行采样,这涉及到重采样问题,因此可能使结果变得模糊。

3.由于场景发生变化,同一个位置像素除了采样点位置外可能发生了其他变化,例如光源遮挡关系,像素颜色值发生变化,这样的变化会导致重影。

为了计算当前像素在历史颜色缓存中的位置,通常在延迟着色的几何通道中同时计算每个像素在上一帧相对于当前帧的偏移位置,这称为一个motion vector,后面使用一个额外的颜色缓存将偏移矢量直接输出到G-buffer中。为了保证精确度,通常使用RG16格式。这需要记录上一帧摄像机的信息以及上一帧每个物体本地到世界坐标变化矩阵mat02w。

需要注意的是,这里需要使用去除抖动的坐标,因为对于历史颜色缓存而言,它存储的是每个像素中心位置的颜色,如果我们使用抖动过的位置,那么计算的结果可能是两个完全不同的像素位置。

不过由于进行了过滤,最终颜色会变得模糊,尤其当历史颜色缓存累积的越多,它越被使用了更大范围的像素进行过滤。

TAA的模糊来源于每次迭代中,对历史颜色采样使用了双线性过滤器,而这些周围参与加权的像素颜色来源于更早历史周围的加权和,以此类推,随着时间的增加,参与加权的像素范围就越来越大。它的重投影的方差公式:

σG的平方是一个常数,用来表示抖动产生的随机数的方差,v表示像素中心距离每个子采样点的差值。所以,减少每个子采样点到像素中心的距离v,v越大,则总的过滤过程向外扩散的范围越大。可以对每个像素划分为四个子像素,但是不需要每帧渲染4次,而是将四个子像素独立存储为一个缓存对象,每一帧只更新一个子像素,然后将它们合并。

另一个影响因素就是混合因子α,α越大,则历史颜色权重越低。

在UE4中,当像素附件的颜色对比度比较低时增加混合因子,而对比度高的时候减少混合因子。其次,可以使用一个单独的通道以后处理的方式对颜色缓存进行锐化处理,这通过对颜色缓存使用一个锐化过滤器来实现,例如神秘海域4的过滤器:

不过这还不够,TAA还有重影的问题。

TAA需要在混合时判断历史颜色是否失效,目前比较流行的时领域裁剪方案,这种方案基于一个假设,图像的颜色是连续的,即历史颜色应该位于当前时间帧内领域像素颜色的范围内。

当我们计算出当前像素xt周围的3x3个像素的颜色范围之后,就可以对历史颜色的采样值和该范围进行比较。不过如果把无效的点直接抛弃,那么相当于没做任何反走样处理,所以我们我们可以找到一个离它最近的合法的点,例如Ch,并把它加入混合的颜色中。

不过因为多边形判断代价比较高,所以有了一种新方法,叫做方差裁剪。它首先求出3x3个邻域像素的颜色的方差,然后使用方差围绕期望值的变化范围建立一个AABB方差包围盒。

r值大小决定了AABB方差包围盒的大小,r越大,重影效果越明显。

因为TAA面临重影模糊等问题,而且它无法有效的处理子像素的特征,例如草地,动物毛发等超薄超细的表面。聚集几何缓存反走样是2016年提出的新技术,全称是Aggregate G-buffer anti-aliasing, AGAA. 在多级纹理中,低分辨率的纹理通过从高一级分辨率纹理中提前过滤出来。它包括四步:

1.深度前向通道:在前向几何通道使用高密度的采样率对每个像素的可见性进行采样,这一步仅输出深度,法线和几何数据到G-buffer中。

2.聚集定义:按照子采样点的深度和法线特征,将该像素内的所有子采样点分成c个聚集,每个聚集包含多个子采样点。聚集定义仅表明每个子采样点的数据属于哪个聚集。

3.生成AG-buffer:使用第二个光栅化通道对几何场景进行渲染,但是此时开启早起的深度测试,并且设置深度比较为等于,只要那些处于第一步生成深度值的像素才被计算。每个子像素的几何数据被累积到根据定义聚集定义阶段定义的聚集当中。

4.在延迟着色阶段,使用AG-buffer进行着色计算。

在高密度可见性采样中,AGAA仅仅是找出所有可见的子像素,以及每个子像素的法线。它使用MSAA,保证足够多的几何细节被捕捉到。

聚集定义阶段目标是使用一个簇分配算法分配每个像素内的n可见的子采样点到c个聚集当中。聚集定义阶段的输出是一个子采样点到聚集的映射关系。

所有的前置过滤技术都基于一个假设,即所有被过滤的属性之间没有相关性,其中一个属性是完全独立宇另一个属性的,如果属性之间存在相关性,那么它的属性都不应该参与过滤。在几何数据中存在两种相关性,一个是和阴影有关,一个是法线方向。为了减少这种影响,AGAA使用基于距离的分簇算法,我们假设局部范围内,子像素之间的可见性和方向倾向于一致。

k是一个常数用来表示最大可以被标注为局部的距离。

然后要生成聚集几何缓存数据。AGAA使用第二个光栅化几何通道,对整个几何场景的几何数据以nxmsaa的分辨率执行一次渲染,但是开启早期的深度测试,并设置深度测试为EQUALS,这样就有那些在前以通道可见的像素才会参与片元着色器处理。

这个技术目前还处在早起阶段,而且只能处理比较统一的光照模型。

嗯,就到这啦。

圆弧裁剪算法c++_程序媛转TA之理论篇十二:反走样的几种算法原理相关推荐

  1. 蒙特卡洛方法_程序媛转TA之理论篇十三:蒙特卡洛方法

    本文主要来自<全局光照技术>第五章. 蒙特卡洛方法是数值分析方法中的一个重要分支,它的核心概念是使用随机性来解决确定性的问题.大数定律告诉我们,满足某个概率分布的随机变量的数学期望所描述的 ...

  2. ML之SVM:利用SVM算法对手写数字图片识别数据集(PCA降维处理)进行预测并评估模型(两种算法)性能

    ML之SVM:利用SVM算法对手写数字图片识别数据集(PCA降维处理)进行预测并评估模型(两种算法)性能 目录 输出结果 设计思路 核心代码 输出结果 设计思路 核心代码 estimator = PC ...

  3. 程序员转正述职报告_程序员转正工作总结(4篇),转正工作总结

    1.程序员转正工作总结 来公司担任程序员一职已_个月时间,在这_个月时间里,我学到了很多东西.每个人都是在不断的总结中成长,在不断的审视中完善自己.在这_个月里自己也是在总结.审视中脚踏实地地完成好本 ...

  4. 大并发下程序出错_Python并发编程理论篇

    前言 其实关于Python的并发编程是比较难写的一章,因为涉及到的知识很复杂并且理论偏多,所以在这里我尽量的用一些非常简明的语言来尽可能的将它描述清楚,在学习之前首先要记住一个点: 并发编程永远的宗旨 ...

  5. stm32l0的停止模式怎么唤醒_探索者 STM32F407 开发板资料连载第二十二章 待机唤醒实验

    1)实验平台:alientek 阿波罗 STM32F767 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第二十二章 待机唤醒实 ...

  6. 简述sd卡2.0协议_【正点原子FPGA连载】第十二章SD卡读写TXT文本实验-领航者 ZYNQ 之嵌入式开发指南...

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  7. 先来先服务算法代码_程序员算法与数据结构基础中的基础,栈与递归

    在此之前,我们介绍了动态规划.深度优先搜索等基础算法,但是,有部分好友评论说,难度太难了,我们知道动态规划的自顶向下跟深度优先搜索一般都用递归实现,今天我们就先来讲讲算法与数据结构中,基础中的基础递归 ...

  8. 章方:征服耶鲁教授的算法大神程序媛

    本文分享自华为云社区<看征服耶鲁教授的算法程序媛, 如何践行"以人为本"开发智慧社区大脑?>,原文作者:石榴裙. 家里老人在楼下散步不慎摔倒."熊孩子&quo ...

  9. 万能乘法速算法大全_小学生两位数乘法容易出错?只因没掌握这个“万能”速算法...

    儿童节快乐 两位数乘法,在小学阶段的数学学习当中,是经常遇到的.尤其是小学三.四年级,每当遇到这类乘法,小学生都非常容易出错,甚至一算就错. 原因是,一些比较大的两位数,在用列竖式法相乘时,会出现连续 ...

  10. 疑难杂症篇(十八)--ROS系统中使用SLAM算法建图时出现地图漂移的几种原因

    本篇主要介绍在ROS系统中使用SLAM算法建地图时出现地图定位漂移的几种原因及可以采取的措施. 1.SLAM建图时出现的定位漂移现象 2.原因分析 里程计数据发生异常: 计算机的配置不高,计算机建图过 ...

最新文章

  1. 那些有用但不为大家所熟知的 Java 特性
  2. php网页弹出图片,商城网站是如何单击头像直接弹出可以上传图片然后预览?
  3. Git如何回滚代码?
  4. C语言开发笔记(一)自动转换和强制转换
  5. 伯乐发卡系统源码 可用
  6. sql 逐行更新_sql优化面试题
  7. python mysql api_python mysql api
  8. PHP 5.6 已结束安全支持,你升级到 PHP 7 系列了吗?
  9. Oracle 索引原理和种类
  10. 测试创新——用户体验测试(UAT)
  11. java 热力图,热力图
  12. 什么是全量数据、增量数据?如何统一一套系统?
  13. COMPUTEX直击:戴尔笔记本新品迭出
  14. 远程教学,微信群里就能上课、培训
  15. 整流二极管的作用是什么?
  16. 两万字长文总结,梳理 Java 入门进阶哪些事
  17. 并查集的使用,臭虫同性恋问题
  18. springboot基于微信小程序的运动软件前端的设计与实现别用设计源码100932
  19. ubuntu 下 开启无线网卡的monitor mode
  20. lrs_save_param_ex的用法

热门文章

  1. [pl-slam] 几个重要的参数属性
  2. filter的详细配置
  3. 智能优化算法:飞蛾扑火优化算法-附代码
  4. 从零基础入门Tensorflow2.0 ----八、39.5. gpu5
  5. 网易编程题目——相反数:
  6. python的标准库——turtle
  7. day5--numpy
  8. 【ArcGIS|空间分析】3D可视性分析(全国大学生GIS技能大赛试题)
  9. Java微信消息推送(二)
  10. 实习踩坑之路:Mybatis写的sql语句有<符号的问题导致项目启动失败以及count(*)怎么对应到某个实体类的字段