《real-time提炼总结 第四章》《Real-Time Rendering 3rd 第五章》《unity shader 入门精要 第六章 》
图形渲染与视觉外观
渲染的物理现象分为三类:
- 太阳光与其他光源(天然,人造)发出的光
- 光与场景中的物体互相作用。部分被吸收,部分散射开。
- 最终,光被传感器(人眼电子传感器)吸收
光源分类:平行光,点光源,聚光灯
吸收和散射
从根本上,所有光物质相互作用都是两种现象结果:散射(scattering)和吸收(absorption)
散射(scattering):
- 发生在当光线遇到任何种类的光学不连续性(Optical discontinuity)时,可能存在于具有不同光学性质的两种物质分界之处,密度变换处等。
- 散射不会改变光量,他只是改变方向
- 分类:反射(reflection),折射(refraction)
吸收(absorption):
- 发生在物质内部,会导致一些光转变成另一类能量并消失
- 吸收会减少光量(改变光线的密度和颜色),但不会影响其方向
镜面反射光:在表面反射的光
漫反射光:经过透射(transmission),吸收(absorption),散射(scattering)的光。
入射光(Incoming illumination):通过表面辉度(irradiance)来度量
出射光(outgoing light):通过出射率(exitance)来度量,类似于辉度是单位面积的能量。
辉度:从某一方向的一个表面积单位所放射光的量
辐照度(light source):用来量化光,和cos a成正比
辐照度和出射度之间满足线性关系,他们之间的比值就是材质的漫反射和高光反射属性
光物质互相作用是线性的:使辉度加倍将会使出射率增加一倍,出射率/辉度 可以作为材质衡量特性 对于不发光的表面,该比率为0到1之间。出射率和辉度的比率对于不同的光颜色是不同的,所以其表示为RGB矢量或者颜色,也就是我们常说的表面颜色C
(《real-time提炼总结 第四章》中说辉度,《unity shader 入门精要 第六章 》说 辐照度,猜测是一个意思,猜测)
表面:
镜面反射项的方向分布取决于 表面粗糙度(roughness,其反义词是smooothness,光滑度)。
反射光线对于更平滑的表面更加紧密,对于较粗糙的表面更加分散。
着色
着色(shade)是使用方程根据材质属性和光源,计算沿着视线V的射出高度L0的过程。我们使用的着色方程具有漫反射和镜面反射分量。
光照模型(Light Model):计算出射度过程的等式
BRDF光照模型:双向反射分布函数(Bidirectional Reflectance Distribution Function)
BTDF光照模型:双向透射分布函数
BSDF光照模型:双向散射分布函数:出射光的辐射亮度总和 和 入射光的辐射照度 的比例
BSDF=BRDF+BTDF
计算机图形学的第一定律:如果它看起来是对的,那么他就是对的
标准光照模型:
- 自发光(emissive): 用于描述当给定一个方向时,一个表面本身会向该方向发射多少辐射量。需要注意的是如果没有使用全局光照(global illumination)技术,这些自发光的表面并不会真的照亮周围的物体,而是本身看起来更亮了而已。
- 高光反射(specular):用于描述当光线从光源照射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量
- 漫反射(diffuse):用于描述当光线从光源照射到模型表面时,该表面会向每个方向散射多少辐射量
- 环境光(ambient):用于描述其他的间接光照。
直接照明:不考虑物体间的传播和物体内部的传播,直接照明是时时渲染的计算重点
间接光照(indirect light):光线在多个物体之间反射,最后进入摄像机。在标准光照模型中,我们使用一种被称为环境光的部分来近似模拟间接光。
着色的计算:
环境光的计算:通常是一个全局变量,即场景中的所有物体都用这个环境光 【C ambition=G ambition】
自发光的计算:直接进入摄像机,不经过任何物体的反射。直接使用该材质的自发光颜色 【C emissive = G emissive】
漫反射计算 :
- 视角的位置不重要,因为漫反射是完全随机的,因此可以认为任何反射方向上的分布都是一样的,但是入射光线的角度很重要。
- 漫反射光照符合 兰伯特定律 (Lambert law):反射光线的强度与表面法线和光源方向之间夹角的余弦值成正比。
- 【 C diffuse =(C light * M diffuse)* Max (0,dot(n ,l)) 】
-
高光反射计算:
- 用于计算沿着完全镜面反射方向被反射的光线
- 需要知道的信息:表面法线n ,视角方向v,光源方向l,反射方向r(反射方向可以计算的得到) 等。
- 反射方向:【 ^r=2 * dot(^n ,^l) * ^n - ^l 】
- 利用phong模型来计算高光反射部分:【Cspecular=(Clight * Mspecular) * pow( max(0,dot(n ,l) ) , Mgloss) 】
- 光泽度(gloss):也被称为 反光度(shininss),用于控制高光区域有多宽
- Blinn模型 基本思想是避免计算反射方向^r,为此引入^h 【^h=(^v+^l)/|^v+^l|】
- Blinn模型公式:【Cspecular = ( Clight * Mspecular)pow(max(0,dot(^n,^h)),Mgloss)】
- 在硬件实现,如果摄像机和光源距离足够远的话,Blinn模型会快于phong模型,这是因为此时可以认为v和l都是定值,因此h是一个常亮。但当v和l不是定值时,phong模型可能反应更快一些。-
- 原谅。。。数学公式没看懂
着色处理方法:
逐像素光照:(per-pixel lighting)片元着色器中计算,
逐顶点光照:(per-vertex lighting)在顶点着色器中计算,
着色处理是计算光照并由此决定像素着色的过程,存在3种常见着色方法:平滑着色,高洛德着色,冯氏着色。
- 平滑着色(Flat Shading):简单来说就是一个三角形面同用一个颜色,如果一个三角形的代表顶点(也许按在index中的第一个顶点),恰好被光照成了白色,那么整个面会是白色。
- 高洛德着色(Gouraud Shading):结果是每个 求值后的线性插值。实现中,顶点着色器传递空间的顶点法线和位置到shade()函数(首先确保法线矢量长度为1),然后将结果写入内插值。像素着色器将获得内插值并将其写入输出。高洛德着色可以为无光泽表面产生合理的结果,但是对于强高光反射的表面,可能会产生失真(artifacts)。
- 冯氏着色(Phong shading):是对着着色方程进行完全的像素求值。实现中,顶点着色器将世界空间法线和位置写入内插值,此值通过世界空间法线和位置写入内插值(可以是对顶点法线插值得到的,也可以是从法线纹理中采样得到的),此值通过像素着色器传递给shade()函数,而将shade()函数返回值写入到输出中。请注意即使表面法线在顶点中缩放长度1,插值也可以改变长度,因此可能需要在像素着色器中再执行此归一化操作。
- .注意 phong shading和phong Lighting Model 的区别,前者是考虑如何在三个顶点中填充颜色,而后者表示的是物体被光照产生的效果。
- 注意 冯氏着色可以说是三者中最接近真实的着色效果,当然也是开销最大的。因为高洛德着色是每个顶点(vertex)计算一次,冯氏着色是每个 片元(fragment)或者说每个像素计算一次光照,点的法线向量是通过顶点的法线向量插值得到的。所以说不会出现高洛德着色也许会遇到失真的问题。
抗锯齿与常见抗锯齿类型总结
抗锯齿(anti-aliasing 简称AA),也译为边缘软化,消除混叠,抗图像折叠有损,反走样 等。
是一种消除显示器输出的画面中图像边缘出现凹凸锯齿的技术,那些凹凸的锯齿通常因为高分辨率的信号以低分辨率表示或无法准确运算出3D图形坐标定位时所导致的图形混叠(aliasing)而产生的,抗锯齿技术能有效解决这些问题。
超级采样抗锯齿(SSAA)
(super-sampling Anti-Aliasing)是比较早的抗锯齿方法,比较消耗资源,但简单直接。
这种抗锯齿方法先把图像映射到缓存并把它放大,再用超级采样把放大后的图像像素进行采样,一般选取2个或4个临近的像素,把这些采样混合起来后,生成的最终像素,令每个像素拥有临近像素的特征,像素与像素之间的过渡颜色就变得近似,令图形的边缘色彩过渡于平滑。再把最终像素还原回原来大小的图像,并保存到帧缓存也就是显存中,替代原图像保存起来,最后输出到显示器,显示出一帧画面。这样就等于把一幅模糊的大图,通过细腻化后再缩小成清晰的小图。
如果每帧都进行抗锯齿,游戏或视频中的所有画面都带有抗锯齿效果,超级采样抗锯齿中使用的采样法一般为两种:
- OGSS,顺序栅格超级采样(Ordered Grid Super-Sampling),采样时选取两个临近像素。
- RGSS,旋转栅格超级采样(Rotated Grid Super-Sampling),采样时选取4个临近像素
另外,作为概念上最简单的一种采样方法,全景抗锯齿(Full-Scene Antialiasing,FSAA)比较高的分辨率对场景进行绘制,然后对相邻的采样样本进行平均,从而生成一副新的图像。
多重采样抗锯齿(MSAA)
(Multi Sampling Anti-Aliasing),是一种特殊的采样抗锯齿(SSAA)。
MSAA首先来自于OpenGL。具体是MSAA只对Z缓存(Z-Buffer)和模板缓存(Stencil Buffer)中的数据进行超级采样抗锯齿的处理。
可以简单理解为只对多边形的边缘进行抗锯齿处理。这样的话相比SSAA对性能的消耗需求大大降低,不过画质上可能稍有不如SSAA
覆盖采样抗锯齿(CSAA)
(Coverage Sampling Anti-Aliasing)是在MSAA基础上更进一步的节省显存使用量及带宽。
简单来说就是将边缘多边形里需要的子像素坐标覆盖掉,把原像素坐标强制安置在硬件和驱动程序预先算好的坐标中,就好比取样标准一样的MSAA能够最高效率的执行边缘采样,效能提升非常显著。比方说16xCSAA取样性能下降幅度仅比4xMSAA略高一点,处理效果几乎和8xMSAA一样。
高分辨率抗锯齿(HRAA)
(Hight Resolution Anti-Aliasing)也称Quincunx方法。采样是五点梅花状。
可编程过滤抗锯齿(CFAA)
(Custom Filter Anti-Aliasing)简单说就是扩大面积的MSAA,比方说之前的MSAA是严格选取物体边缘像素进行缩放,而CFAA则可以通过驱动和灵活地选择对影响锯齿效果较大的像素进行缩放,以较少的性能牺牲换取平滑效果,显卡资源占用也比较小。
形态抗锯齿(MLAA)
(Morphological Anti-Aliasing)与MSAA不同,MLAA将跨边缘像素的前景和背景色进行混合,用第2 种颜色来填充该像素,从而更有效地进行图像边缘的变现效果。
快速近似抗锯齿(FXAA)
(Fast Approximate Anti-Aliasing)是传统MSAA(多重采样抗锯齿)效果的一种高性能近似。它是一种单程像素着色器,和MLAA一样运行于目标游戏管线的后期处理阶段,但不像后者那样使用DirectCompute,而只是单纯的后期处理着色,不依赖于任何GPU计算API。正因如此,FXAA技术对显卡没有特殊要求,完全兼容NIVIDA,AMD的不同显卡(MLAA仅支持A卡)和DirectX9.0、10、11。
时间性抗锯齿(TXAA)
(Temporal Anti-Aliasing)将MSAA,时间滤波以及后处理相结合,用于呈现更高的视觉效果保真度。与CG电影中所采用的技术类似,TXAA集MSAA的强大功能与复杂的解析滤镜于一身,可呈现出更加平滑的图像效果。
此外,TXAA还能对帧之间的整个场景进行抖动采样,以减少闪烁情形,闪烁情形在技术上又称作时间性锯齿。
目前,TXAA有两种模式:TXAA2X和TXAA4X。
- TXAA2X的图像保真度胜过8X MSAA的视觉保真度,然而所需性能却与2X MSAA相类似;
- TXAA4X的图像保真度胜过8X MSAA的视觉保真度,然而所需性能却与4X MSAA相类似;
多帧采样抗锯齿(MFAA)
(Multi-Frame Sampled Anti-Aliasing)是NVIDIA公司根据MSAA改进的一种抗锯齿技术。目前仅搭载Maxwell架构GPU的显卡才能使用。
可以将MFAA理解为MSAA的优化版,能够在得到几乎相同的效果的同时提升性能上的表现。
MFAA与MSAA最大的差别就是在于同样开启4倍效果的时候MSAA是真正的针对每个边缘像素周围的4个像素进行采样,MFAA则是仅仅只是采用交错的方式采样边缘某个像素周围的两个像素
透明渲染与透明排序
透明渲染:
透明渲染是图形学常见的问题之一,从RTR3 中总结出的两个算法:
1.Screen-Door Transparency方法:
- 基本思想是用棋盘格填充模式来绘制透明多边形,也就是说,以每隔一个像素绘制一点的方式来绘制一个多边形,这样会使在其后的物体部分可见,通常情况下,屏幕上的像素比较紧凑,以至于棋盘的这种绘制方式并不会露馅。
- 同样的想法也用于剪切纹理的抗锯齿边缘,但是在子像素级别中的,这是一种称为alpha覆盖(alpha to coverage)的特征。
- screen-door transparency方法的有点就是简单,可以在任何时间任何顺序绘制透明物体,并不需要特殊的硬件支持(只要支持填充模式)。缺点是透明度效果仅在50%时最好,且屏幕的每个区域中只能绘制一个透明物体。
2.Alpha混合(Alpha Blending)
- 这个方法比较常见,其实就是按照Alpha混合向量的值来混合源像素和目标像素。当在屏幕上绘制某个物体时,与每个像素相关联的值有RGB颜色和Z缓冲深度值,以及另外一个成分alpha分量,这个alpha值也可以根据需要生成并储存,它描述的是给定像素的对象片段的不透明度值。
- alpha为1.0表示对物体不透明,完全覆盖所在像素的区域。0.0表示像素完全透明。
- 为了使对象透明,在现有场景的上方,以小于1的透明度进行绘制即可。每个像素将从渲染管线接收到一个RGBA结果,并将这个值和原像素颜色混合。
透明排序:
比较基本的透明度排序方法:深度缓存,优化家算法
高级别的透明度算法:加权平均算法,深度剥离算法
深度缓存(Z-Buffer):
- 在计算机图形学中,深度缓存是三维图形中处理图像深度坐标的过程,这个过程通常在硬件中完成,她也可以在软件中完成,它是可见性问题的一个解决方法。
- 可见性问题是确定渲染场景中哪部分可见的问题
- 限制:每个像素只能储存一个对象,如果一些透明对象与同一个像素重叠,那么单独的Z-Buffer就不能储存并稍后再解析出所有可见对象的效果。这个问题通过改变加速器架构来解决,比如用A-Buufer.
- A-Buffer:具有“深度像素(deep pixels)”,其可以在单个像素中储存一系列呈现在所有对象之后被解析为单个像素颜色的多个片段,但需要注意的是市场的主流选择。
画家算法(Paiinter's Algorithm)
- 也称优先填充算法,效率虽然较低,但是可以有效处理透明度排序的问题。
- 其基本思想是按照画家在绘制一幅画作时,首先绘制距离较远的场景,然后用绘制距离近的场景覆盖较远的部分的思想。画家算法首先将场景中的多边形根据深度进行排序,然后按照顺序进行描绘。这种方法通常会将不可看见的部分覆盖,这样就可以解决可见性的问题。
加权平均值算法(Weighted Average)
- 通过扩展透明度混合公式,来实现无序透明物件的渲染,从而得到一定程度上逼真的结果
深度剥离算法(Depth Peeling)
- 深度剥离是一种对深度值进行排序的技术。
- 它的原理比较直观,标准的深度测试使场景中的Z值最小的点输出到屏幕上,就是离我们最近的顶点。但还有离我们第二近的顶点,第三近的顶点存在。要想显示他们,可以用很多遍渲染的方法。第一遍渲染时,按照正常方式处理,这样就得到了离我们最近的表面中的每个顶点Z值,在第二遍渲染时,把现在每个顶点的深度值和刚才的那个深度值进行比较,凡是小于等于第一遍得到的Z值,就把他们剥离,后面的程序以此类推
伽马校正
- Gamma Correction 又叫伽马非线性化(Gamma Nonlinearyity),伽马编码(Gamma Encoding),或直接叫伽马(gamma)
- 是用来对光线的辉度(luminance)或是三色刺激值(tristimulus Values)所进行非线性的运算或反运算的一种操作。
- 为图像进行伽马编码的目的是用来对人类视觉的特性进行补偿,从而根据人类对光线或黑白的感知,最大化地利用表示黑白的数据位或宽带。