3D图形基础(3):光照模型与透明渲染

内容引自《Real Time Rendering 3rd》

1. 光照现象:散射与吸收

从根本上来说,所有的光物质相互作用都是两种现象的结果: 散射(scattering)和吸收(absorption)。

  • 散射(scattering)发生在当光线遇到任何种类的光学不连续性(optical discontinuity)时,可能存在于具有不同光学性质的两种物质分界之处,晶体结构破裂处,密度的变化处等。散射不会改变光量,它只是使其改变方向。光的散射(scattering)一般又分为反射(reflection)和折射(refraction)。

3D图形基础(3):光照模型与透明渲染

  • 吸收(absorption)发生在物质内部,其会导致一些光转变成另一种能量并消失。 吸收会减少光量,但不会影响其方向。
  • 镜面反射光表示在表面反射的光。而漫反射光表示经历透射(transmission),吸收(absorption)和散射(scattering) 的光。

 

2. 着色与着色方程

着色(Shade)是使用方程式根据材质属性和光源,计算沿着视线的出射光亮度的过程。我们使用的着色方程具有漫反射和镜面反射分量。

2.1 着色方程的漫反射分量

其中漫反射分量较为简单,书中推导出的对Ldiff的着色方程如下:

3D图形基础(3):光照模型与透明渲染

这种类型的漫反射着色也被叫做兰伯特(Lambertian)着色。兰伯特定律指出,对于理想的漫反射表面,出射光亮度与cosθi成正比。

2.2 着色方程的镜面反射分量

原书中推导出的镜面反射项的着色方程:

3D图形基础(3):光照模型与透明渲染

2.3 着色方程

组合漫反射和镜面反射两个项,得到完整的着色方程,总出射光亮度

3D图形基础(3):光照模型与透明渲染

3. 三种着色处理方法

着色处理是计算光照并由此决定像素颜色的过程,存在3种常见的着色处理方法:平滑着色、高洛德着色与冯氏着色。

  • 平滑着色(Flat shading):简单来讲,就是一个三角面用同一个颜色。如果一个三角面的代表顶点(也许是按在index中的第一个顶点),恰好被光照成了白色,那么整个面都会是白的。
  • 高洛德着色(Gouraud shading):每顶点求值后的线性插值结果通常称为高洛德着色。在高洛德着色的实现中,顶点着色器传递世界空间的顶点法线和位置到Shade( ) 函数(首先确保法线矢量长度为1),然后将结果写入内插值。像素着色器将获取内插值并将其直接写入输出。 高洛德着色可以为无光泽表面产生合理的结果,但是对于强高光反射的表面,可能会失真(artifacts)。
  • 冯氏着色(Phong shading):冯氏着色是对着色方程进行完全的像素求值。在冯氏着色实现中,顶点着色器将世界空间法线和位置写入内插值,此值通过像素着色器传递给Shade( )函数。而将Shade( )函数返回值写入到输出中。请注意,即使表面法线在顶点着色器中缩放为长度1,插值也可以改变其长度,因此可能需要在像素着色器中再次执行此归一化操作。

4. 抗锯齿

       抗锯齿(英语:anti-aliasing,简称AA),也译为边缘柔化、消除混叠、抗图像折叠有损,反走样等。它是一种消除显示器输出的画面中图物边缘出现凹凸锯齿的技术,那些凹凸的锯齿通常因为高分辨率的信号以低分辨率表示或无法准确运算出3D图形坐标定位时所导致的图形混叠(aliasing)而产生的,抗锯齿技术能有效地解决这些问题。

4.1 超级采样抗锯齿(SSAA)
       超级采样抗锯齿(Super-Sampling Anti-Aliasing,简称SSAA)是比较早期的抗锯齿方法,比较消耗资源,但简单直接。这种抗锯齿方法先把图像映射到缓存并把它放大,再用超级采样把放大后的图像像素进行采样,一般选取2个或4个邻近像素,把这些采样混合起来后,生成的最终像素,令每个像素拥有邻近像素的特征,像素与像素之间的过渡色彩,就变得近似,令图形的边缘色彩过渡趋于平滑。再把最终像素还原回原来大小的图像,并保存到帧缓存也就是显存中,替代原图像存储起来,最后输出到显示器,显示出一帧画面。这样就等于把一幅模糊的大图,通过细腻化后再缩小成清晰的小图。如果每帧都进行抗锯齿处理,游戏或视频中的所有画面都带有抗锯齿效果。 超级采样抗锯齿中使用的采样法一般有两种:

  • OGSS,顺序栅格超级采样(Ordered Grid Super-Sampling,简称OGSS),采样时选取2个邻近像素。
  • RGSS,旋转栅格超级采样(Rotated Grid Super-Sampling,简称RGSS),采样时选取4个邻近像素。

4.2 多重采样抗锯齿(MSAA)
多重采样抗锯齿(Multi Sampling Anti-Aliasing,简称MSAA),是一种特殊的超级采样抗锯齿(SSAA)。MSAA首先来自于OpenGL。具体是MSAA只对Z缓存(Z-Buffer)和模板缓存(Stencil Buffer)中的数据进行超级采样抗锯齿的处理。可以简单理解为只对多边形的边缘进行抗锯齿处理。这样的话,相比SSAA对画面中所有数据进行处理,MSAA对资源的消耗需求大大减弱,不过在画质上可能稍有不如SSAA。


4.3 覆盖采样抗锯齿(CSAA)
覆盖采样抗锯齿(Coverage Sampling Anti-Aliasing,简称CSAA)是NVIDIA在G80及其衍生产品首次推向实用化的AA技术,也是目前NVIDIA GeForce 8/9/G200系列独享的AA技术。CSAA就是在MSAA基础上更进一步的节省显存使用量及带宽,简单说CSAA就是将边缘多边形里需要取样的子像素坐标覆盖掉,把原像素坐标强制安置在硬件和驱动程序预先算好的坐标中。这就好比取样标准统一的MSAA,能够最高效率的执行边缘取样,效能提升非常的显著。比方说16xCSAA取样性能下降幅度仅比4xMSAA略高一点,处理效果却几乎和8xMSAA一样。8xCSAA有着4xMSAA的处理效果,性能消耗却和2xMSAA相同。


4.4 高分辨率抗锯齿(HRAA)
高分辨率抗锯齿方法(High Resolution Anti-Aliasing,简称HRAA),也称Quincunx方法,也出自NVIDIA公司。“Quincunx”意思是5个物体的排列方式,其中4个在正方形角上,第五个在正方形中心,也就是梅花形,很像六边模型上的五点图案模式。此方法中,采样模式是五点梅花状,其中四个样本在像素单元的角上,最后一个在中心。


4.5 可编程过滤抗锯齿(CFAA)
可编程过滤抗锯齿(Custom Filter Anti-Aliasing,简称CFAA)技术起源于AMD-ATI的R600家庭。简单地说CFAA就是扩大取样面积的MSAA,比方说之前的MSAA是严格选取物体边缘像素进行缩放的,而CFAA则可以通过驱动和谐灵活地选择对影响锯齿效果较大的像素进行缩放,以较少的性能牺牲换取平滑效果。显卡资源占用也比较小。


4.6 形态抗锯齿(MLAA)
形态抗锯齿(Morphological Anti-Aliasing,简称MLAA),是AMD推出的完全基于CPU处理的抗锯齿解决方案。与MSAA不同, MLAA将跨越边缘像素的前景和背景色进行混合,用第2种颜色来填充该像素,从而更有效地改进图像边缘的变现效果。


4.7 快速近似抗锯齿(FXAA)
快速近似抗锯齿(Fast Approximate Anti-Aliasing,简称FXAA) ,是传统MSAA(多重采样抗锯齿)效果的一种高性能近似。它是一种单程像素着色器,和MLAA一样运行于目标游戏渲染管线的后期处理阶段,但不像后者那样使用DirectCompute,而只是单纯的后期处理着色器,不依赖于任何GPU计算API。正因为如此,FXAA技术对显卡没有特殊要求,完全兼容NVIDIA、AMD的不同显卡(MLAA仅支持A卡)和DirectX 9.0、DirectX 10、DirectX 11。


4.8 时间性抗锯齿(TXAA)
时间性抗锯齿(Temporal Anti-Aliasing,简称TXAA),将 MSAA、时间滤波以及后期处理相结合,用于呈现更高的视觉保真度。与CG电影中所采用的技术类似,TXAA集MSAA的强大功能与复杂的解析滤镜于一身,可呈现出更加平滑的图像效果。此外,TXAA还能够对帧之间的整个场景进行抖动采样,以减少闪烁情形,闪烁情形在技术上又称作时间性锯齿。目前,TXAA有两种模式:TXAA 2X和TXAA 4X。TXAA 2X可提供堪比8X MSAA的视觉保真度,然而所需性能却与2X MSAA相类似;TXAA 4X的图像保真度胜过8XMSAA,所需性能仅仅与4X MSAA相当。


4.9 多帧采样抗锯齿(MFAA)
多帧采样抗锯齿(Multi-Frame Sampled Anti-Aliasing,MFAA)是 NVIDIA公司根据MSAA改进出的一种抗锯齿技术。目前仅搭载 Maxwell 架构GPU的显卡才能使用。可以将MFAA理解为MSAA的优化版,能够在得到几乎相同效果的同时提升性能上的表现。MFAA与MSAA最大的差别就在于在同样开启4倍效果的时候MSAA是真正的针对每个边缘像素周围的4个像素进行采样,MFAA则是仅仅只是采用交错的方式采样边缘某个像素周围的两个像素。

5. 透明渲染

Alpha混合(Alpha Blending)方法。这个方法比较常见,其实就是按照Alpha混合向量的值来混合源像素和目标像素。当在屏幕上绘制某个物体时,与每个像素相关联的值有RGB颜色和Z缓冲深度值,以及另外一个成分alpha分量,这个alpha值也可以根据需要生成并存储,它描述的是给定像素的对象片段的不透明度的值。 alpha为1.0表示对象不透明,完全覆盖像素所在区域; 0.0表示像素完全透明。为了使对象透明,在现有场景的上方,以小于1的透明度进行绘制即可。每个像素将从渲染管线接收到一个RGBA结果,并将这个值和原始像素颜色相混合。

6. 透明排序

要将透明对象正确地渲染到场景中,通常需要对物体进行排序。下面分别介绍两种比较基本的透明排序方法(深度缓存和油画家算法)和两种高级别的透明排序算法(加权平均值算法和深度剥离)。

6.1 深度缓存(Z-Buffer)
Z-Buffer也称深度缓冲。在计算机图形学中,深度缓冲是在三维图形中处理图像深度坐标的过程,这个过程通常在硬件中完成,它也可以在软件中完成,它是可见性问题的一个解决方法。可见性问题是确定渲染场景中哪部分可见、哪部分不可见的问题。

Z-buffer的限制是每像素只存储一个对象。如果一些透明对象与同一个像素重叠,那么单独的Z-buffer就不能存储并且稍后再解析出所有可见对象的效果。这个问题是通过改变加速器架构来解决的,比如用A-buffer。A-buffer具有“深度像素(deep pixels)”,其可以在单个像素中存储一系列呈现在所有对象之后被解析为单个像素颜色的多个片段。但需注意,Z-buffer是市场的主流选择。

6.2 画家算法(Painter's Algorithm)
画家算法也称优先填充算法,效率虽然较低,但还是可以有效处理透明排序的问题。其基本思想是按照画家在绘制一幅画作时,首先绘制距离较远的场景,然后用绘制距离较近的场景覆盖较远的部分的思想。画家算法首先将场景中的多边形根据深度进行排序,然后按照顺序进行描绘。这种方法通常会将不可见的部分覆盖,这样就可以解决可见性问题。


6.3 加权平均值算法(Weighted Average)
使用简单的透明混合公式来实现无序透明渲染的算法,它通过扩展透明混合公式,来实现无序透明物件的渲染,从而得到一定程度上逼真的结果。


6.4 深度剥离算法(Depth Peeling)
深度剥离是一种对深度值进行排序的技术。它的原理比较直观,标准的深度检测使场景中的Z值最小的点输出到屏幕上,就是离我们最近的顶点。但还有离我们第二近的顶点,第三近的顶点存在。要想显示它们,可以用多遍渲染的方法。第一遍渲染时,按照正常方式处理,这样就得到了离我们最近的表面中的每个顶点的z值。在第二遍渲染时,把现在每个顶点的深度值和刚才的那个深度值进行比较,凡是小于等于第一遍得到的z值,把它们剥离,后面的过程依次类推即可。