大概是近期,媒体将我在腾讯的职位“Lead Engine Programmer”翻译成了浮夸的“首席引擎程序员”,然后多个媒体又相互引用报道。
Lead Engine Programmer,可能部分国外的公司的定位确实是“首席引擎程序员”,但在腾讯并不是。在腾讯内部,这本身是一个组长的title,正确的翻译应该类似“引擎组组长”,“引擎主程序”。
“腾讯游戏首席引擎程序员”这个误读的称呼,对于一个今年刚满30,还在成长中的程序员来说,真的受不起。
真的是满屏的尴尬。
这篇文章将总结和提炼《Real-Time Rendering 3rd》(实时渲染图形学第三版)的第五章“Visual Appearance(视觉外观)”的内容。
壹·导读
当我们渲染三维模型的图像时,模型不仅要有适当的几何形状,还应该有所需的视觉外观。《Real-Time Rendering 3rd》第五章内容,讨论光照和材质在现实世界的表现,关于光照和表面模型,着色方程,以及渲染出真实外观的一些额外技术。
简而言之,通过阅读这篇总结式文章,你将对图形渲染中的以下要点有所了解:
- 渲染与视觉物理现象
- 光照与材质
- 着色原理
- 抗锯齿
- 透明渲染
- 伽玛校正
当然,本文作为总结式文章,知识点会相对密集,很多地方对细节并不可能展开描述,对一些地方不太理解的朋友,自然还是推荐是去阅读《Real-Time Rendering 3rd》的对应原文与相应文献。
贰·渲染与视觉物理现象
当渲染类似图1中的逼真场景时,可以帮助了解渲染相关的物理现象。一般情况,这些物理现象分为三种:
- 太阳光与其他光源(天然或人造光)发出光。
- 光与场景中的物体相互作用。部分被吸收;部分散射开来,向新的方向传播。
- 最终,光被传感器(人眼,电子传感器)吸收。
图1 光源与各种物体交互的卧室照片
而在图1中,我们可以看到所有的如上三种物理现象:
- 光线从灯光发出并直接传播给房间里其他物体。
- 物体表面吸收一些物体,并将一些物体散射到新的方向。没有被吸收的光线继续在环境中移动,遇到其他物体。
- 通过场景的光一小部分光进入用于捕获图像的传感器(如摄像机)。
叁·光照与材质
- 关于光源的特性。光被不同地模拟为几何光线,电磁波或光子(具有一些波特性的量子粒子)。无论如何处理,光都是电磁辐射能-通过空间传播的电磁能。光源发光,而不是散射或吸收光。根据渲染目的,光源可以以许多不同的方式来表示。光源可以分为三种不同类型:平行光源、点光源和聚光灯。
- 关于材质的特性。在渲染中,通过将材质附加到场景中的模型来描绘对象外观。每个材质都和一系列的Shader代码,纹理,和其他属性联系在一起,用来模拟光与材质相互作用。
3.1 光照现象:散射与吸收
- 从根本上来说,所有的光物质相互作用都是两种现象的结果:
散射(scattering)和吸收(absorption)。 - 散射(scattering)发生在当光线遇到任何种类的光学不连续性(optical
discontinuity)时,可能存在于具有不同光学性质的两种物质分界之处,晶体结构破裂处,密度的变化处等。散射不会改变光量,它只是使其改变方向。光的散射(scattering)一般又分为反射(reflection)和折射(refraction)。
图2 光的散射(scattering)——反射(reflection)和折射(refraction)
- 吸收(absorption)发生在物质内部,其会导致一些光转变成另一种能量并消失。 吸收会减少光量,但不会影响其方向。
图3 反射(reflected
light)和透射光(transmitted light)的相互作用
- 镜面反射光表示在表面反射的光。而漫反射光表示经历透射(transmission),吸收(absorption)和散射(scattering) 的光。
- 入射光(Incoming illumination)通过表面辉度(irradiance)来度量。而出射光(outgoing light)通过出射率(exitance)来度量,类似于辉度是每单位面积的能量。光物质相互作用是线性的; 使辉度加倍将会使出射率增加一倍。出射率除以辉度可以作为材质的衡量特性。对于不发光的表面,该比率为0到1之间。出射率和辉度的比率对于不同的光颜色是不同的,所以其表示为RGB矢量或者颜色,也就是我们通常说的表面颜色c。
3.2 表面粗糙度
- 镜面反射项的方向分布取决于表面粗糙度(roughness,其反义词是smoothness,光滑度)。反射光线对于更平滑的表面更加紧密,并且对于较粗糙的表面更加分散。我们可以看到下图中的这种依赖关系,它显示了不同粗糙度的两个表面的反射效果。
图4 光在粗糙度不同表面的反射
肆·着色
4.1 着色与着色方程
着色(Shade)是使用方程式根据材质属性和光源,计算沿着视线v的出射光亮度Lo的过程。我们使用的着色方程具有漫反射和镜面反射分量。
4.1.1 着色方程的漫反射分量
其中漫反射分量较为简单,书中推导出的对Ldiff的着色方程如下:
这种类型的漫反射着色也被叫做兰伯特(Lambertian)着色。兰伯特定律指出,对于理想的漫反射表面,出射光亮度与cosθi成正比。注意,这种夹紧型cos因子(clamped
dot product,可写作max(n·l, 0),通常称为n点乘l因子),不是兰伯特表面的特征;正如我们所见,它一般适用于辉度(irradiance)的度量。兰伯特表面的决定性特征是出射光亮度(radiance)和辉度(irradiance)成正比。
4.1.2 着色方程的镜面反射分量
原书中推导出的镜面反射项的着色方程:
4.1.3 着色方程
组合漫反射和镜面反射两个项,得到完整的着色方程,总出射光亮度Lo:
这个着色方程与“Blinn-Phong”方程类似,“Blinn-Phong”方程是Blinn在1977年首次提出的。主要形式如下:
4.2 三种着色处理方法
着色处理是计算光照并由此决定像素颜色的过程,存在3种常见的着色处理方法:平滑着色、高洛德着色与冯氏着色。
- 平滑着色(Flat
shading):简单来讲,就是一个三角面用同一个颜色。如果一个三角面的代表顶点(也许是按在index中的第一个顶点),恰好被光照成了白色,那么整个面都会是白的。 - 高洛德着色(Gouraud
shading):每顶点求值后的线性插值结果通常称为高洛德着色。在高洛德着色的实现中,顶点着色器传递世界空间的顶点法线和位置到Shade( )函数 (首先确保法线矢量长度为1),然后将结果写入内插值。像素着色器将获取内插值并将其直接写入输出。
高洛德着色可以为无光泽表面产生合理的结果,但是对于强高光反射的表面,可能会产生失真(artifacts)。 - 冯氏着色(Phong shading):冯氏着色是对着色方程进行完全的像素求值。在冯氏着色实现中,顶点着色器将世界空间法线和位置写入内插值,此值通过像素着色器传递给Shade( )函数。而将Shade( )函数返回值写入到输出中。请注意,即使表面法线在顶点着色器中缩放为长度1,插值也可以改变其长度,因此可能需要在像素着色器中再次执行此归一化操作。
图5 从左到右,平面着色(Flat
shading),高洛德着色( Gouraud shading), 和冯氏着色(Phong shading)
- 注意Phong Shading和Phong Lighting Model的区别,前者是考虑如何在三个顶点中填充颜色,而后者表示的是物体被光照产生的效果。
- 注意冯氏着色可以说是三者中最接近真实的着色效果,当然开销也是最大的。因为高洛德着色是每个顶点(vertex)计算一次光照,冯氏着色是每个片元(fragment)或者说每像素计算一次光照,点的法向量是通过顶点的法向量插值得到的。所以说不会出现高洛德着色也许会遇到的失真问题。
伍·抗锯齿与常见抗锯齿类型总结
抗锯齿(英语:Anti-Aliasing,简称AA),也译为边缘柔化、消除混叠、抗图像折叠有损,反走样等。它是一种消除显示器输出的画面中图物边缘出现凹凸锯齿的技术,那些凹凸的锯齿通常因为高分辨率的信号以低分辨率表示或无法准确运算出3D图形坐标定位时所导致的图形混叠(aliasing)而产生的,抗锯齿技术能有效地解决这些问题。
下面将常见的几种抗锯齿类型进行总结介绍,也包括RTR3中没有讲到的,最近几年新提出的常见抗锯齿类型。
5.1 超级采样抗锯齿(SSAA)
超级采样抗锯齿(Super-Sampling Anti-Aliasing,简称SSAA)是比较早期的抗锯齿方法,比较消耗资源,但简单直接。这种抗锯齿方法先把图像映射到缓存并把它放大,再用超级采样把放大后的图像像素进行采样,一般选取2个或4个邻近像素,把这些采样混合起来后,生成的最终像素,令每个像素拥有邻近像素的特征,像素与像素之间的过渡色彩,就变得近似,令图形的边缘色彩过渡趋于平滑。再把最终像素还原回原来大小的图像,并保存到帧缓存也就是显存中,替代原图像存储起来,最后输出到显示器,显示出一帧画面。这样就等于把一幅模糊的大图,通过细腻化后再缩小成清晰的小图。如果每帧都进行抗锯齿处理,游戏或视频中的所有画面都带有抗锯齿效果。 超级采样抗锯齿中使用的采样法一般有两种:
- OGSS,顺序栅格超级采样(Ordered Grid Super-Sampling,简称OGSS),采样时选取2个邻近像素。
- RGSS,旋转栅格超级采样(Rotated Grid Super-Sampling,简称RGSS),采样时选取4个邻近像素。
另外,作为概念上最简单的一种超采样方法,全场景抗锯齿(Full-Scene
Antialiasing,FSAA)以较高的分辨率对场景进行绘制,然后对相邻的采样样本进行平均,从而生成一幅新的图像。
5.2 多重采样抗锯齿(MSAA)
多重采样抗锯齿(Multi Sampling Anti-Aliasing,简称MSAA),是一种特殊的超级采样抗锯齿(SSAA)。MSAA首先来自于OpenGL。具体是MSAA只对Z缓存(Z-Buffer)和模板缓存(Stencil
Buffer)中的数据进行超级采样抗锯齿的处理。可以简单理解为只对多边形的边缘进行抗锯齿处理。这样的话,相比SSAA对画面中所有数据进行处理,MSAA对资源的消耗需求大大减弱,不过在画质上可能稍有不如SSAA。
5.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相同。
5.4 高分辨率抗锯齿(HRAA)
高分辨率抗锯齿方法(High Resolution Anti-Aliasing,简称HRAA),也称Quincunx方法,也出自NVIDIA公司。“Quincunx”意思是5个物体的排列方式,其中4个在正方形角上,第五个在正方形中心,也就是梅花形,很像六边模型上的五点图案模式。此方法中,采样模式是五点梅花状,其中四个样本在像素单元的角上,最后一个在中心。
5.5 可编程过滤抗锯齿(CFAA)
可编程过滤抗锯齿(Custom Filter Anti-Aliasing,简称CFAA)技术起源于AMD-ATI的R600家庭。简单地说CFAA就是扩大取样面积的MSAA,比方说之前的MSAA是严格选取物体边缘像素进行缩放的,而CFAA则可以通过驱动和谐灵活地选择对影响锯齿效果较大的像素进行缩放,以较少的性能牺牲换取平滑效果。显卡资源占用也比较小。
5.6 形态抗锯齿(MLAA)
形态抗锯齿(Morphological Anti-Aliasing,简称MLAA),是Intel率先提出(感谢龚大补充,MLAA是Intel提出的纯CPU AA Morphological Antialiasing (MLAA),AMD拿去做了个compute shader的版),然后AMD推出的完全基于CPU处理的抗锯齿解决方案。与MSAA不同, MLAA将跨越边缘像素的前景和背景色进行混合,用第2种颜色来填充该像素,从而更有效地改进图像边缘的变现效果。
5.7 快速近似抗锯齿(FXAA)
快速近似抗锯齿(Fast Approximate Anti-Aliasing,简称FXAA) ,是传统MSAA(多重采样抗锯齿)效果的一种高性能近似。它是一种单程像素着色器,和MLAA一样运行于目标游戏渲染管线的后期处理阶段,但不像后者那样使用DirectCompute,而只是单纯的后期处理着色器,不依赖于任何GPU计算API。正因为如此,FXAA技术对显卡没有特殊要求,完全兼容NVIDIA、AMD的不同显卡(MLAA仅支持A卡)和DirectX 9.0、DirectX 10、DirectX 11。
5.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相当。
5.9 多帧采样抗锯齿(MFAA)
多帧采样抗锯齿(Multi-Frame Sampled Anti-Aliasing,MFAA)是 NVIDIA公司根据MSAA改进出的一种抗锯齿技术。目前仅搭载 Maxwell 架构GPU的显卡才能使用。可以将MFAA理解为MSAA的优化版,能够在得到几乎相同效果的同时提升性能上的表现。MFAA与MSAA最大的差别就在于在同样开启4倍效果的时候MSAA是真正的针对每个边缘像素周围的4个像素进行采样,MFAA则是仅仅只是采用交错的方式采样边缘某个像素周围的两个像素。
陆·透明渲染与透明排序
6.1 透明渲染
透明渲染是是图形学里面的常见问题之一,可以从《Real-Time Rendering 3rd》中总结出如下两个算法:
- Screen-Door Transparency方法。基本思想是用棋盘格填充模式来绘制透明多边形,也就是说,以每隔一个像素绘制一点方式的来绘制一个多边形,这样会使在其后面的物体部分可见,通常情况下,屏幕上的像素比较紧凑,以至于棋盘格的这种绘制方式并不会露馅。同样的想法也用于剪切纹理的抗锯齿边缘,但是在子像素级别中的,这是一种称为alpha覆盖(alpha to coverage)的特征。screen-door transparency方法的优点就是简单,可以在任何时间任何顺序绘制透明物体,并不需要特殊的硬件支持(只要支持填充模式)。缺点是透明度效果仅在50%时最好,且屏幕的每个区域中只能绘制一个透明物体。
- Alpha混合(Alpha Blending)方法。这个方法比较常见,其实就是按照Alpha混合向量的值来混合源像素和目标像素。当在屏幕上绘制某个物体时,与每个像素相关联的值有RGB颜色和Z缓冲深度值,以及另外一个成分alpha分量,这个alpha值也可以根据需要生成并存储,它描述的是给定像素的对象片段的不透明度的值。 alpha为1.0表示对象不透明,完全覆盖像素所在区域; 0.0表示像素完全透明。为了使对象透明,在现有场景的上方,以小于1的透明度进行绘制即可。每个像素将从渲染管线接收到一个RGBA结果,并将这个值和原始像素颜色相混合。
6.2 透明排序
要将透明对象正确地渲染到场景中,通常需要对物体进行排序。下面分别介绍两种比较基本的透明排序方法(深度缓存和油画家算法)和两种高级别的透明排序算法(加权平均值算法和深度剥离)。
6.2.1 深度缓存(Z-Buffer)
Z-Buffer也称深度缓冲。在计算机图形学中,深度缓冲是在三维图形中处理图像深度坐标的过程,这个过程通常在硬件中完成,它也可以在软件中完成,它是可见性问题的一种常见解决方法。
Z-Buffering是在为物件进行着色时,执行“隐藏面消除”工作的一项技术,所以隐藏物件背后的部分就不会被显示出来。在3D环境中每个像素中会利用一组数据资料来定义像素在显示时的纵深度(即Z轴坐标值)。Z-Buffer所用的位数越高,则代表该显示卡所提供的物件纵深感也越精确。
Z-buffer的限制是每像素只存储一个对象。如果一些透明对象与同一个像素重叠,那么单独的Z-buffer就不能存储并且稍后再解析出所有可见对象的效果。这个问题是通过改变加速器架构来解决的,比如用A-buffer。A-buffer具有“深度像素(deep pixels)”,其可以在单个像素中存储一系列呈现在所有对象之后被解析为单个像素颜色的多个片段。但需注意,Z-buffer是市场的主流选择。
6.2.2 画家算法(Painter’s Algorithm)
画家算法(Painter’s Algorithm)也称优先填充算法,油画家算法。效率虽然较低,但还是可以有效处理透明排序的问题。其基本思想是按照画家在绘制一幅画作时,首先绘制距离较远的场景,然后用绘制距离较近的场景覆盖较远的部分。画家算法首先将场景中的多边形根据深度进行排序,然后按照顺序进行描绘。这种方法通常会将不可见的部分覆盖,这样就可以解决可见性问题。
6.2.3 加权平均值算法(Weighted
Average)
使用简单的透明混合公式来实现无序透明渲染的算法,它通过扩展透明混合公式,来实现无序透明物件的渲染,从而得到一定程度上逼真的结果。
6.2.4 深度剥离算法(Depth Peeling)
深度剥离是一种对深度值进行排序的技术。它的原理比较直观,标准的深度检测使场景中的Z值最小的点输出到屏幕上,就是离我们最近的顶点。但还有离我们第二近的顶点,第三近的顶点存在。要想显示它们,可以用多遍渲染的方法。第一遍渲染时,按照正常方式处理,这样就得到了离我们最近的表面中的每个顶点的z值。在第二遍渲染时,把现在每个顶点的深度值和刚才的那个深度值进行比较,凡是小于等于第一遍得到的z值,把它们剥离,后面的过程依次类推即可。
图6
每个深度剥离通道渲染特定的一层透明通道。左侧是第一个Pass,直接显示眼睛可见的层,中间的图显示了第二层,显示了每个像素处第二靠近透明表面的像素。右边的图是第三层,每个像素处第三靠近透明表面的像素。
柒·伽玛校正
伽马校正(Gamma correction) 又叫伽马非线性化(gamma nonlinearity),伽马编码(gamma encoding)
或直接叫伽马(gamma),是用来对光线的辉度(luminance)或是三色刺激值(tristimulus values)所进行非线性的运算或反运算的一种操作。为图像进行伽马编码的目的是用来对人类视觉的特性进行补偿,从而根据人类对光线或者黑白的感知,最大化地利用表示黑白的数据位或带宽。
捌·其他参考
[1] zh.wikipedia.org/wiki/%E5%8F%8D%E9%8B%B8%E9%BD%92
[2] 如何在Unity中分别实现Flat Shading(平面着色)、Gouraud Shading(高洛德着色)、Phong Shading(冯氏着色)
[3] OpenGL深度剥离算法(Depth Peeling)半透明实现
[4] Alpha混合物体的深度排序 – 逍遥剑客 – 博客频道 – CSDN.NET
[5] Gouraud shading – Wikipedia
[6] Phong shading – Wikipedia
[7] http://www.nbb.cornell.edu/neurobio/land/OldStudentProjects/cs490-95to96/guo/report.html
[8] zh.wikipedia.org/wiki/%E6%B7%B1%E5%BA%A6%E7%BC%93%E5%86%B2
[9] zh.wikipedia.org/wiki/%E4%BC%BD%E7%91%AA%E6%A0%A1%E6%AD%A3
[10] 题图来自《刺客信条:枭雄》
The end.
该去看《神奇女侠》了。
在计算机图形学中,纹理贴图(Texturing)是使用图像、函数或其他数据源来改变物体表面外观的技术。这篇文章,将总结和提炼《Real-Time Rendering 3rd》(实时渲染图形学第三版)的第六章“Texturing(纹理贴图)”的内容,讲述纹理贴图与其相关技术的方方面面。
简而言之,通过阅读这篇总结式文章,你将对纹理贴图技术中的以下要点有所了解:
- 纹理管线 The Texturing Pipeline
- 投影函数 The Projector Function
- 映射函数 The Corresponder Function
- 体纹理 Volume Texture
- 立方体贴图 Cube Map
- 纹理缓存 Texture Caching
- 纹理压缩 Texture Compression
- 程序贴图纹理 Procedural Texturing
- Blinn凹凸贴图 Blinn Bump Mapping
- 移位贴图 Displacement Mapping
- 法线贴图 Normal Mapping
- 视差贴图 Parallax Mapping
- 浮雕贴图 Relief Mapping
壹 · 导读
《Real-Time Rendering 3rd》第六章内容“Chapter 6 Texturing”,讨论了纹理贴图的方方面面。在计算机图形学中,纹理贴图是使用图像、函数或其他数据源来改变物体表面外观的技术。例如,可以将一幅砖墙的彩色图像应用到一个多边形上,而不用对砖墙的几何形状进行精确表示。当观察这个多边形的时候,这张彩色图像就出现在多边形所在位置上。只要观察者不接近这面墙,就不会注意到其中几何细节的不足(比如其实砖块和砂浆的图像是显示在光滑的表面上的事实)。通过这种方式将图像和物体表面结合起来,可以在建模、存储空间和速度方面节省很多资源。
图1 一幅使用了纹理颜色贴图、凹凸贴图和视差贴图等方法来增加画面复杂性和真实感的游戏截图(来自《黑暗之魂3》)
贰 · 纹理管线 The Texturing Pipeline
简单来说,纹理(Texturing)是一种针对物体表面属性进行“建模”的高效技术。图像纹理中的像素通常被称为纹素(Texels),区别于屏幕上的像素。根据Kershaw的术语,通过将投影方程(projector function)运用于空间中的点 ,从而得到一组称为参数空间值(parameter-spacevalues)的关于纹理的数值。这个过程就称为贴图(Mapping,也称映射 ),也就是纹理贴图(Texture Mapping,也称纹理映射 )这个词的由来。纹理贴图可以用一个通用的纹理管线来进行描述。纹理贴图过程的初始点是空间中的一个位置。这个位置可以基于世界空间,但是更常见的是基于模型空间。因为若此位置是基于模型空间的,当模型移动时,其纹理才会随之移动。
如图2 为一个纹理管线(The Texturing Pipeline),也就是单个纹理应用纹理贴图的详细过程,而此管线有点复杂的原因是每一步均为用户提供了有效的控制。
图2 单个纹理的通用纹理管线
下面是对上图中描述的纹理管线的分步概述:
- 第一步。通过将投影方程(projector function)运用于空间中的点 ,从而得到一组称为参数空间值(parameter-space values)的关于纹理的数值。
- 第二步。在使用这些新值访问纹理之前,可以使用一个或者多个映射函数(corresponder function)将参数空间值(parameter-space values )转换到纹理空间。
- 第三步。使用这些纹理空间值(texture-space locations)从纹理中获取相应的值(obtain value)。例如,可以使用图像纹理的数组索引来检索像素值。
- 第四步。再使用值变换函数(value transform function)对检索结果进行值变换,最后使用得到的新值来改变表面属性,如材质或者着色法线等等。
而如下这个例子应该对理解纹理管线有所帮助。下例将描述出使用纹理管线,一个多边形在给定一张砖块纹理时在其表面上生成样本时(如图3)发生了哪些过程。
图3 一个砖墙的纹理管线过程
如图3所示,在具体的参考帧画面中找到物体空间中的位置(x,y,z),如图中点(-2.3,7.1,88.2),然后对该位置运用投影函数。这个投影函数通常将向量(x,y,z)转换为一个二元向量(u,v)。在此示例中使用的投影函数是一个正交投影,类似一个投影仪,将具有光泽的砖墙图像投影到多边形表面上。再考虑砖墙这边,其实这个投影过程就是将砖墙平面上的点变换为值域为0到1之间的一对(u,v)值,如图,(0.32,0.29)就是这个我们通过投影函数得到的uv值。而我们图像的分辨率是256 x 256,所以,将256分别乘以(0.32,0.29),去掉小数点,得到纹理坐标(81, 74)。通过这个纹理坐标,可以在纹理贴图上查找到坐标对应的颜色值,所以,我们接着找到砖块图像上像素位置为(81,74)处的点,得到颜色(0.9,0.8,0.7)。而由于原始砖墙的颜色太暗,因此可以使用一个值变换函数,给每个向量乘以1.1,就可以得到我们纹理管线过程的结果——颜色值(0.99,0.88,0.77)。
随后,我们就可以将此值用于着色方程,作为物体的漫反射颜色值,替换掉之前的漫反射颜色。
下面对纹理管线中主要的两个组成,投影函数(The Projector Function)和映射函数(The Corresponder Function)进行概述。
2.1 投影函数 The Projector Function
作为纹理管线的第一步,投影函数的功能就是将空间中的三维点转化为纹理坐标,也就是获取表面的位置并将其投影到参数空间中。
在常规情况下,投影函数通常在美术建模阶段使用,并将投影结果存储于顶点数据中。也就是说,在软件开发过程中,我们一般不会去用投影函数去计算得到投影结果,而是直接使用在美术建模过程中,已经存储在模型顶点数据中的投影结果。但有一些特殊情况,例如:
1、OpenGL的glTexGen函数提供了一些不同的投影函数,包括球形函数和平面函数。利用空闲时间可以让图形加速器来执行投影过程,而这样做的优点是不需要将纹理坐标送往图形加速器,从而可以节省带宽。
2、更一般的情况, 可以在顶点或者像素着色器中使用投影函数,这可以实现各种效果,包括一些动画和一些渲染方法(比如如环境贴图,environment mapping,有自身特定的投影函数,可以针对每个顶点或者每个像素进行计算)。
通常在建模中使用的投影函数有球形、圆柱、以及平面投影,也可以选其他一些输入作为投影函数。
图4 不同的纹理坐标,上面一行从左到右分别为球形、圆柱、平面,以及自然uv投影:下面一行所示为把不同的投影运用于同一个物体的情形。
非交互式渲染器(Noninteractive renderers)通常将这些投影方程称为渲染过程本身的一部分。一个单独的投影方程就有可能适用于整个模型,但其实实际上,美术同学不得不使用各种各样的工具将模型进行分割,针对不同的部分,分别使用不同的投影函数。如图5所示。
图5 使用不同的投影函数将纹理以不同的方式投射到同一个模型上
各种常见投影的不同要点:
- 球形投影(The spherical projection)。球形投影将点投射到一个中心位于某个点的虚拟球体上,这个投影与Blinn与Newell的环境贴图方法相同。
- 圆柱投影(Cylindrical projection)。与球体投影一样,圆柱投影计算的是纹理坐标u,而计算得到的另一个纹理坐标v是沿该圆柱轴线的距离。这种投影方法对具有自然轴的物体比较适用,比如旋转表面,如果表面与圆柱体轴线接近垂直时,就会出现变形。
- 平面投影(The planar projection)。平面投影非常类似于x-射线幻灯片投影,它沿着一个方向进行投影,并将纹理应用到物体的所有表面上。这种方法通常使用正交投影,用来将纹理图应用到人物上,其把模型看作一个用纸做的娃娃,将不同的纹理粘贴到该模型的前后。
图6 雕塑模型上的多个较小纹理,保存在两个较大的纹理上。右图显示了多边形网格如何展开并显示在纹理上的。
2.2 映射函数 The Corresponder Function
映射函数(The Corresponder Function)的作用是将参数空间坐标(parameter-space coordinates)转换为纹理空间位置(texture space locations)。
我们知道图像会出现在物体表面的(u,v)位置上,且uv值的正常范围在[0,1)范围内。超出这个值域的纹理,其显示方式便可以由映射函数(The Corresponder Function)来决定。
在OpenGL中,这类映射函数称为“封装模式(Warapping Mode)”,在Direct3D中,这类函数叫做“寻址模式(Texture Addressing Mode)”。最常见的映射函数有以下几种:
- 重复寻址模式,wrap (DirectX), repeat (OpenGL)。图像在表面上重复出现。
- 镜像寻址模式,mirror。图像在物体表面上不断重复,但每次重复时对图像进行镜像或者反转。
- 夹取寻址模式,clamp (DirectX) ,clamp to edge (OpenGL)。夹取纹理寻址模式将纹理坐标夹取在[0.0,1.0]之间,也就是说,在[0.0,1.0]之间就是把纹理复制一遍,然后对于[0.0,1.0]之外的内容,将边缘的内容沿着u轴和v轴进行延伸。
- 边框颜色寻址模式,border (DirectX) ,clamp to border (OpenGL)。边框颜色寻址模式就是在[0.0,1.0]之间绘制纹理,然后[0.0,1.0]之外的内容就用边框颜色填充。
图7 图像寻址模式,从左到右分别是重复寻址、镜像寻址、夹取寻址、边框颜色寻址
另外,每个纹理轴可以使用不同的映射函数。例如在u轴使用重复寻址模式,在v轴使用夹取寻址模式。
叁 · 体纹理 Volume Texture
三维纹理(3D texture),即体纹理(volume texture),是传统二维纹理(2D texture)在逻辑上的扩展。二维纹理是一张简单的位图图片,用于为三维模型提供表面点的颜色值;而一个三维纹理,可以被认为由很多张 2D 纹理组成,用于描述三维空间数据的图片。三维纹理通过三维纹理坐标进行访问 。
虽然体纹理具有更高的储存要求,并且滤波成本更高,但它们具有一些独特的优势:
- 使用体纹理,可以跳过为三维网格确定良好二维参数的复杂过程,因为三维位置可以直接用作纹理坐标,从而避免了二维参数化中通常会发生的变形和接缝问题。
- 体纹理也可用于表示诸如木材或大理石的材料的体积结构。使用三维纹理实现出的这些模型,看起来会很逼真,浑然天成。
劣势:
- 使用体纹理作为表面纹理会非常低效,因为三维纹理中的绝大多数样本都没起到作用。
肆 · 立方体贴图 Cube Map
立方体纹理(cube texture)或立方体贴图(cube map)是一种特殊的纹理技术,它用6幅二维纹理图像构成一个以原点为中心的纹理立方体,这每个2D纹理是一个立方体(cube)的一个面。对于每个片段,纹理坐标(s, t, r)被当作方向向量看待,每个纹素(texel)都表示从原点所看到的纹理立方体上的图像。
图8 Cube Map图示1
图9 Cube Map图示2
可以使用三分量纹理坐标向量来访问立方体贴图中的数据,该矢量指定了从立方体中心向外指向的光线的方向。选择具有最大绝对值的纹理坐标对应的相应的面。(例如:对于给定的矢量(−3.2, 5.1, −8.4),就选择-Z面),而对剩下的两个坐标除以最大绝对值坐标的绝对值,即8.4。 那么就将剩下的两个坐标的范围转换到了-1到1,然后重映射到[0,1]范围,以方便纹理坐标的计算。例如,坐标(-3.2,5.1)映射到((-3.2 / 8.4 + 1)/ 2,(5.1/ 8.4 + 1)/ 2)≈(0.31,0.80)。
立方体贴图支持双线性滤波以及mip mapping,但问题可以可能会在贴图接缝处出现。有一些处理立方体贴图专业的工具在滤波时考虑到了可能的各种因素,如ATI公司的CubeMapGen,采用来自其他面的相邻样本创建mipmap链,并考虑每个纹素的角度范围,可以得到比较不错的效果。如图10。
图10 立方体贴图过滤。最左边两个图像使用2 x 2和4 x 4的立方体贴图的纹理层次,采用标准立方体贴图生成mipmap链。因接缝显而易见,除了极端细化的情况,这些mipmap级别并不可用。两个最右边的图像使用相同分辨率的mipmap级别,通过在立方体面和采用角度范围进行采样生成。 由于没有接缝,不易失真,这些mipmap甚至可以用于显示在很大的屏幕区域的对象。
伍 · 纹理缓存 Texture Caching
一个复杂的应用程序可能需要相当数量的纹理。快速纹理存储器的数量因系统而异,但你会发现它们永远不够用。有各种各样的纹理缓存(texture caching)技术,但我们一直在上传纹理到内存的开销和纹理单次消耗的内存量之间寻求一个好的平衡点。比如,一个由纹理贴图的多边形对象,初始化在离相机很远的位置,程序也许会只加载mipmap中更小的子纹理,就可以很完美的完成这个对象的显示了。
一些基本的建议是——保持纹理在不需要放大再用的前提下尽可能小,并尝试基于多边形将纹理分组。即便所有纹理都一直存储在内存中,这种预防措施也可能会提高处理器的缓存性能。
以下是一些常见的纹理缓存使用策略。
5.1 最近最少使用策略(Least Recently Used ,LRU)
最近最少使用(Least Recently Used ,LRU)策略是纹理缓存方案中常用的一种策略,其作用如下。加载到图形加速器的内存中的每个纹理都被给出一个时间戳,用于最后一次访问以渲染图像时。当需要空间来加载新的纹理时,首先卸载最旧时间戳的纹理。一些API还允许为每个纹理设置一个优先级:如果两个纹理的时间戳相同,则优先级较低的纹理首先被卸载。 设置优先级可以帮助避免不必要的纹理交换。
5.2 最近最常使用策略(Most Recently Used,MRU)
如果开发自己的纹理管理器,Carmack(就是那个游戏界大名鼎鼎的卡马克)提出了一种非常有用的策略,也就是对交换出缓冲器的纹理进行核查 [具体可见原书参考文献374]。大概思想是这样:鉴于如果在当前帧中载入纹理,会发生抖动(Thrashing)的情况。这种情况下,LRU策略是一种非常不好的策略,因为在每帧画面中会对每张纹理图像进行交换。在这种情况下,可以采用最近最常使用(Most Recently Used,MRU)策略,直到在画面中没有纹理交换时为止,再然后切换回LRU。
5.3 预取策略(Prefetching)
加载纹理花费显着的时间,特别是在需将纹理转换为硬件原生格式时。 纹理加载在每个框架可以有很大的不同。在单个帧中加载大量纹理使得难以保持恒定的帧速率。一种解决方案是使用预取(prefetching),在将来需要预期的情况下,预计未来的需求然后加载纹理,将加载过程分摊在多帧中。
5.4 裁剪图策略(Clipmap)
对于飞行模拟和地型模拟系统,图像数据集可能会非常巨大。传统的方法是将这些图像分解成更小的硬件可以处理的瓦片地图(tiles)。Tanner等人提出了一种称为裁剪图(clipmap)的改进数据结构。其思想是,将整个数据集视为一个mipmap,但是对于任何特定视图,只需要mipmap的较低级别的一小部分即可。支持DirectX 10的GPU就能够实现clipmap技术。用这种技术制作的图像如图11所示。
图11 高分辨率地形图访问海量图像数据库。使用clipmapp技术可以减少在同一时间所需数据量。
陆 · 纹理压缩 Texture Compression
直接解决内存和带宽问题和缓存问题的一个解决方案是固定速率纹理压缩(Fixed-rate Texture Compression)。通过硬件解码压缩纹理,纹理可以需要更少的纹理内存,从而增加有效的高速缓存大小。至少这样的纹理使用起来更高效,因为他们在访问时消耗更少的内存带宽。
有多种图像压缩方法用于图像文件格式,如JPEG和PNG,但在硬件上对其实现解码会非常昂贵。S3公司开发一种名为S3纹理压缩(S3 Texture Compression,S3TC)的方法,目前已经被选为DirectX中的标准压缩模式,称为DXTC。在DirectX 10中,这种方法称为BC (Block Compression)。其优点是创建了一个固定大小,具有独立的编码片段,并且解码简单,同时速度也很快。每个压缩部分的图像可以独立处理,没有共享查找表(look-up tables)或其他依赖关系,这同样地简化了解码过程。
还有几种S3/DXTC/BC压缩方案的变种存在,他们有一些共同的特征。把纹理按4×4个单元(纹素)大小划分为块。每个块对应一张四色查找表,表中存有两个标准RGB565格式表示的16位颜色,另外使用标准插入算法在插入两个新的颜色值,由此构成四色查找表。4×4大小的纹理块中每个单元(像素点)用两个bit表示,每一个都代表四色查找表中的一种颜色。可以看出,实质上是利用每个单元(像素点)中的两个bit来索引四色查找表中的颜色值。
这些压缩技术可以应用于立方体或体积图,以及二维纹理。而其主要缺点是它们是有损的压缩。 也就是说,原始图像通常不能从压缩版本检索。 仅使用四个或八个内插值来表示16个像素。 如果一个瓦片贴图有更大的数值,相较压缩前就会有一些损失。 在实践中,如果正常使用这些压缩方案,一般需给出可接受的图像保真度。
DXTC的一个问题是用于块的所有颜色都位于RGB空间的直线上。例如,DXTC不能在一个块中同时表示红色,绿色和蓝色。
下面对几种不同纹理压缩变体(S3/DXTC/BC以及ETC)在编码上的异同点分节概述。
6.1 DXT1
DXT1(DirectX 9.0)或BC1(DirectX 10.0及更高版本) – 每个块具有两个16位参考RGB值(5位红,6绿,5蓝)的纹素,而每个纹素具有2位插值因子,以便从一个参考值或两个中间值之间选择。DXT1作为五种变体中最精简的版本,块占用为8个字节,即每个纹素占用4位。 与未压缩的24位RGB纹理相比,有着6:1的纹理压缩率。
6.2 DXT3
DXT3(DirectX 9.0)或BC2(DirectX 10.0及更高版本) – 每个块都具有与DXT1块相同的RGB数据编码。另外,每个纹素都具有单独存储4位alpha值(这是唯一的直接存储数据的形式,而不是用插值的形式)。DXT3块占用16个字节,或每个纹理元素8位。与未压缩的32位RGBA纹理相比,有着4:1的纹理压缩率。
6.3 DXT5
DXT5(DirectX 9.0)或BC3(DirectX 10.0及更高版本) – 每个块都具有与DXT1块相同的RGB数据编码。此外,alpha数据使用两个8位参考值和一个每纹素3位的插值因子进行编码。每个纹素可以选择参考alpha值之一或六个中间值之一作为其值。DXT5块具有与DXT3块相同的存储要求,也就是DXT3块占用16个字节,即每个纹理元素8位。与未压缩的32位RGBA纹理相比,有着4:1的纹理压缩率。
6.4 ATI1
ATI1(ATI公司的特定扩展名)或BC4(DirectX 10.0及更高版本)- 每个块存储单个颜色的数据通道,以与DXT5中的alpha数据相同的方式进行编码。 BC4块占用8个字节,即每个纹素占用4位。与未压缩的8位单通道纹理相比,有着4:1的纹理压缩率。仅在较新的ATI的硬件或任意供应商的DirectX 10.0硬件上才支持此格式。
6.5 ATI2
ATI2(ATI公司的特定扩展名,也称为3Dc)或BC5(DirectX10.0及更高版本) – 每个块存储两个颜色通道的数据,以与BC4块或DXT5中的alpha数据相同的方式进行编码。 BC5块占用16个字节,即每个纹理元素8位。与未压缩的16位双通道纹理相比,有着4:1的纹理压缩率。也仅在较新的ATI的硬件或任意供应商的DirectX 10.0硬件上才支持此格式。
6.6 ETC
对于OpenGL ES,选择了另一种称为ETC(Ericsson texture compression,ETC)的压缩算法。方案与S3TC具有相同的特点,即快速解码,随机访问,无间接查找,速率固定。ETC算法将4×4纹素的块编码为64位,即每个纹理元素4位。基本思想如图12所示。
图12 ETC算法对像素块的颜色进行编码,然后修改每像素的亮度以创建最终的纹理颜色
每个2×4块(或4×2,取决于哪个质量更佳)存储基本颜色。每个块还从一个小的静态查找表中选择一组四个常量,并且块中的每个纹素可以选择在选定的查找表中添加一个值,添加的这个值就可以是每像素的亮度。
也可以这样理解:ETC压缩算法将图像中的chromatic和luminance分开存储的方式,而在解码时使用luminance对chromatic进行调制进而重现原始图像信息。
两个要点:
- ETC的图片压缩的质量和DXTC相当。
- ETC也主要有两种方法:ETC1和改进后的ETC2。
柒 · 程序贴图纹理 Procedural Texturing
程序贴图纹理(Procedural Texturing,也可译为过程纹理)是用计算机算法生成的,旨在创建用于纹理映射的自然元素(例如木材,大理石,花岗岩,金属,石头等)的真实表面或三维物体而创建的纹理图像。通常,会使用分形噪声(fractal noise)和湍流扰动函数(turbulence functions)这类“随机性”的函数来生成程序贴图纹理。
给定纹理空间位置,进行图像查找是生成纹理值的一种方法。另一种方法是对函数进行求值,从而得到一个程序贴图纹理(procedural texture)。
过程纹理主要用于模拟自然界中常见的Marble,Stone,Wood,Cloud等纹理。大多数的过程纹理都是基于某类噪声函数(Noise Function),比如说perlin noise。在过去,由于过程纹理计算量很大,在实时绘制中很少使用。但是GPU的出现,促进了过程纹理在实时渲染中的广泛应用。
图13 程序贴图纹理示例
程序贴图纹理通常用于离线渲染应用程序,而图像纹理在实时渲染中更为常见。这是由于在现代GPU中的图像纹理硬件有着极高效率,其可以在一秒钟内执行数十亿个纹理访问。然而,GPU架构正在朝着更便宜的计算能力和(相对)更昂贵的存储器访问而发展。这将使程序纹理在实时应用程序中更常见,尽管它们不可能完全替代图像纹理。
考虑到体积图像纹理的高存储成本,体积纹理是用于程序贴图纹理是一项特别有吸引力的应用。这样的纹理可以通过各种技术来合成,最常见的是使用一个或多个噪声函数来产生纹理的值。
捌 · 凹凸贴图与其改进
凹凸贴图(Bump Mapping)思想最早是由图形学届大牛中的大牛Jim Blinn提出,后来的Normal Mapping,Parallax Mapping,Parallax Occulision Mapping,Relief Mapping等等,均是基于同样的思想,只是考虑得越来越全面,效果也越来越逼真。
以下是几种凹凸贴图与其改进方法的总结对比。
除了Displacement Mapping方法以外,其他的几种改进一般都是通过修改每像素着色方程来实现,关键思想是访问纹理来修改表面的法线,而不是改变光照方程中的颜色分量。物体表面的几何法线保持不变,我们修改的只是照明方程中使用的法线值。他们比单独的纹理有更好的三维感官,但是显然还是比不上实际的三维几何体。
以下是各个方法分别的原理和特性说明。
8.1 凹凸贴图 Bump Mapping
凹凸贴图是指计算机图形学中在三维环境中通过纹理方法来产生表面凹凸不平的视觉效果。它主要的原理是通过改变表面光照方程的法线,而不是表面的几何法线,或对每个待渲染的像素在计算照明之前都要加上一个从高度图中找到的扰动,来模拟凹凸不平的视觉特征,如褶皱、波浪等等。
Blinn于1978年提出了凹凸贴图方法。使用凹凸贴图,是为了给光滑的平面,在不增加顶点的情况下,增加一些凹凸的变化。他的原理是通过法向量的变化,来产生光影的变化,从而产生凹凸感。实际上并没有顶点(即Geometry)的变化。
表示凹凸效果的另一种方法是使用高度图来修改表面法线的方向。每个单色纹理值代表一个高度,所以在纹理中,白色表示高高度区域,黑色是低高度的区域(反之亦然)。示例如图14。
图14 波浪高度凹凸贴图以及其在材质上的使用
8.2 移位贴图 Displacement Mapping
Displacement Mapping,移位贴图,也有人称为置换贴图,或称高度纹理贴图(Heightfield Texturing)。这种方法类似于法线贴图,移位贴图的每一个纹素中存储了一个向量,这个向量代表了对应顶点的位移。注意,此处的纹素并不是与像素一一对应,而是与顶点一一对应,因此,纹理的纹素个数与网格的顶点个数是相等的。在VS阶段,获取每个顶点对应的纹素中的位移向量,(注意,直到3.0版本的vs才支持纹理数据的获取,之前的版本只有ps才能获取纹理数据),施加到局部坐标系下的顶点上,然后进行世界视点投影变换即可。
8.3 法线贴图 Normal Mapping
法线贴图(Normal mapping)是凸凹贴图(Bump mapping)技术的一种应用,法线贴图有时也称为“Dot3(仿立体)凸凹纹理贴图”。凸凹与纹理贴图通常是在现有的模型法线添加扰动不同,法线贴图要完全更新法线。与凸凹贴图类似的是,它也是用来在不增加多边形的情况下在浓淡效果中添加细节。但是凸凹贴图通常根据一个单独的灰度图像通道进行计算,而法线贴图的数据源图像通常是从更加细致版本的物体得到的多通道图像,即红、绿、蓝通道都是作为一个单独的颜色对待。
简单来说,Normal Map直接将正确的Normal值保存到一张纹理中去,那么在使用的时候直接从贴图中取即可。
图15 基于法线贴图的凹凸映射,每个颜色通道实际上是表面法线坐标。红色通道是x偏差; 红色越多,正常点越多。 绿色是y偏差,蓝色是z。 右边是使用法线贴图生成的图像。 请注意立方体顶部的扁平外观。
8.4 视差贴图 Parallax Mapping
视差贴图Parallax Mapping,又称为 Offset Mapping,以及virtual displacement mapping),于2001年由Kaneko引入,由Welsh进行了改进和推广。视差贴图是一种改进的Bump Mapping技术,相较于普通的凹凸贴图,视差贴图技术得到凹凸效果得会更具真实感(如石墙的纹理将有更明显的深度)。视差贴图是通过替换渲染多边形上的顶点处的纹理坐标来实现的,而这个替换依赖于一个关于切线空间中的视角(相对于表面法线的角度)和在该点上的高度图的方程。简单来说,Parallax Mapping利用Height Map进行了近似的Texture Offset。如图 6.32。
图16 视差贴图
8.5 浮雕贴图 Relief Mapping
关于浮雕贴图(Relief Mapping),有人把它誉为凹凸贴图的极致。我们知道,Parallax Mapping是针对Normal Mapping的改进,利用HeightMap进行了近似的Texture Offset。而Relief Mapping是精确的Texture Offset,所以在表现力上比较完美。
图17 法线贴图和浮雕贴图的对比。法线贴图不发生自遮挡。
图18 相较于视差贴图(左),浮雕贴图(右)可以实现更深的凹凸深度。
Parallax Mapping能够提供比Bump Mapping更多的深度,尤其相比于小视角下,但是如果想提供更深的深度,Parallax Mapping就无能为力了,Relief Mapping则可以很好的胜任。相较于Parallax Mapping,浮雕贴图(Relief Mapping)可以实现更深的凹凸深度。浮雕贴图方法不仅更容易提供更深的深度,还可以做出自阴影和闭塞效果,当然算法也稍稍有点复杂,具体细节可以参考这篇中文文献:Relief mapping:凹凸贴图的极致,而如果要用一句话概括Relief Mapping,将会是:“在Shader里做光线追踪”。
图19 浮雕贴图,使石块看起来更逼真
玖·其他参考
[1] Learn OpenGL, extensive tutorial resource for learning Modern OpenGL
[2] 体绘制(Volume Rendering)概述
[3] 几种主流贴图压缩算法的实现原理 – BugRunner的专栏 – 博客频道 – CSDN.NET
[4] 过程纹理(Procedural Texture) [2005-11-20 update]
[5] zh.wikipedia.org/wiki/%E6%B3%95%E7%BA%BF%E8%B4%B4%E5%9B%BE
[6] Relief mapping:凹凸贴图的极致
[7] Bump Mapping综述 – Just a Programer – 博客园
[8] 题图来自《变形金刚5:最后的骑士》
在计算机图形学中,BRDF(Bidirectional Reflectance Distribution Function,双向反射分布函数)是真实感图形学中最核心的概念之一,它描述的是物体表面将光能从任何一个入射方向反射到任何一个视点方向的反射特性,即入射光线经过某个表面反射后如何在各个出射方向上分布。BRDF模型是绝大多数图形学算法中用于描述光反射现象的基本模型。
这篇文章,将专注于总结和提炼《Real-Time Rendering 3rd》(实时渲染图形学第三版)中第七章“Advanced Shading · 高级着色”的内容,并对这章中介绍BRDF的内容进行适当补充和引申,构成全文,成为一个对BRDF进行近乎系统式总结的文章。
图1 基于BRDF渲染的场景图 ©Disney 2014.《超能陆战队》
一、导读
简而言之,通过阅读这篇总结式文章,你将对BRDF的以下要点有所了解:
- 一、BRDF的前置知识 · 数学篇
- 球面坐标 Spherical Coordinate
- 立体角 Solid Angle
- 投影面积 Foreshortened Area
- 二、BRDF前置知识 · 辐射度量学篇
- 辐射度量学基本参数表格
- 辐射通量/光通量 Radiant Flux
- 辐射强度/发光强度 Radiant Intensity
- 辐射率/光亮度 Radiance
- 辐照度/辉度 Irradiance
- 三、BRDF的定义与理解
- BRDF的定义式
- BRDF的非微分形式
- BRDF与着色方程
- BRDF的可视化表示
- 四、BRDF的性质
- 亥姆霍兹光路可逆性
- 能量守恒性质
- 线性特征
- 五、BRDF模型的分类
- BRDF经验模型
- 数据驱动的BRDF模型
- 基于物理的BRDF模型
- 六、基于物理的BRDF · 前置知识
- 次表面散射 Subsurface Scattering
- 菲涅尔反射 Fresnel Reflectance
- 微平面理论 Microfacet Theory
- 七、基于物理的BRDF · 常见模型
- Cook-Torrance BRDF模型
- Ward BRDF模型
- 八、BRDF与其引申
- BSSRDF
- SBRDF(SVBRDF)
- BTDF与BSDF
二 、BRDF前置知识· 数学篇
在正式了解BRDF的概念之前,有必要先了解数学和辐射度量学相关的前置基础知识。
2.1 球面坐标 SphericalCoordinate
由于光线主要是通过方向来表达,通常用球面坐标表达它们比用笛卡尔坐标系更方便。
如图,球面坐标中的向量用三个元素来指定:
图2 球面坐标
其中:
- r表示向量的长度
- θ表示向量和Z轴的夹角
- Φ表示向量在x-y平面上的投影和x轴的逆时针夹角。
2.2 立体角 Solid Angle
立体角描述了从原点向一个球面区域张成的视野大小,可以看成是弧度的三维扩展。
图3 立体角
我们知道弧度是度量二维角度的量,等于角度在单位圆上对应的弧长,单位圆的周长是2π,所以整个圆对应的弧度也是2π 。立体角则是度量三维角度的量,用符号Ω表示,单位为立体弧度(也叫球面度,Steradian,简写为sr),等于立体角在单位球上对应的区域的面积(实际上也就是在任意半径的球上的面积除以半径的平方ω= s/r2 ),单位球的表面积是4π ,所以整个球面的立体角也是4π 。
图4 立体角
立体角ω有如下微分形式:
其中dA为面积微元。而面积微元dA在球面坐标系下可以写成:
因此:
2.3 投影面积 Foreshortened Area
投影面积描述了一个物体表面的微小区域在某个视线方向上的可见面积。
对于面积微元A,则沿着与法向夹角为θ方向的A的可见面积为:
图5 投影面积
三、BRDF前置知识· 辐射度量学篇
3.1 辐射度量学基本参数表格
如下是截取的wiki(en.wikipedia.org/wiki/Radiometry))上的辐射度量学国际单位制的辐射量参数表格:
下面对几个核心的基本量进行分别介绍。
3.2 辐射通量/光通量 Radiant Flux
辐射通量(Radiant Flux,又译作光通量,辐射功率)描述的是在单位时间穿过截面的光能,或每单位时间的辐射能量,通常用Φ来表示,单位是W,瓦特。
其中的Q表示辐射能(Radiant energy),单位是J,焦耳。
3.3 辐射强度/发光强度 Radiant Intensity
对一个点(比如说点光源)来说,辐射强度表示每单位立体角的辐射通量,用符号I表示,单位 :
概括一下:辐射强度(Radiant intensity,又译作发光强度),表示每单位立体角的辐射通量,通常用符号I表示,单位 ,瓦特每球面度。
3.4 辐射率/光亮度 Radiance
辐射率(Radiance,又译作光亮度,用符号L表示),表示物体表面沿某一方向的明亮程度,它等于每单位投影面积和单位立体角上的辐射通量,单位是W·sr−1·m−2,瓦特每球面度每平方米。在光学中,光源的辐射率,是描述非点光源时光源单位面积强度的物理量,定义为在指定方向上的单位立体角和垂直此方向的单位面积上的辐射通量。光亮度L也可以理解为发光程度I在表面dA上的积分。
一种直观的辐射率的理解方法是:将辐射率理解为物体表面的微面元所接收的来自于某方向光源的单位面积的光通量,因此截面选用垂直于该方向的截面,其面积按阴影面积技术计算。
辐射率的微分形式:
其中:Φ是辐射通量,单位瓦特(W);Ω是立体角,单位球面度(sr)。
另外需要注意的是,辐射率使用物体表面沿目标方向上的投影面积,而不是面积。
概括一下:辐射率(Radiance,又译作光亮度),表示每单位立体角每单位投影面积的辐射通量,通常用符号L表示,单位是 ,瓦特每球面度每平方米。
3.5 辐照度/辉度 Irradiance
辐照度(Irradiance,又译作辉度,辐射照度,用符号E表示),指入射表面的辐射通量,即单位时间内到达单位面积的辐射通量,或到达单位面积的辐射通量,也就是辐射通量对于面积的密度,
用符号E表示,单位 ,瓦特每平方米。
辐照度可以写成辐射率(Radiance)在入射光所形成的半球上的积分:
其中,Ω是入射光所形成的半球。L(ω)是沿ω方向的光亮度。
概括一下:辐照度(Irradiance,又译作辉度,辐射照度),表示单位时间内到达单位面积的辐射通量,也就是辐射通量对于面积的密度,通常用符号E表示,单位 ,瓦特每平方米。
四、BRDF的定义与理解
4.1 BRDF的定义式
可以将给一个表面着色的过程,理解为给定入射的光线数量和方向,计算出指定方向的出射光亮度(radiance)。,在计算机图形学领域,BRDF (Bidirectional Reflectance Distribution Function,译作双向反射分布函数 )是一个用来描述表面如何反射光线的方程。顾名思义,BRDF就是一个描述光如何从给定的两个方向(入射光方向l和出射方向v)在表面进行反射的函数。
BRDF的精确定义是出射辐射率的微分(differential outgoing radiance)和入射辐照度的微分(differential incoming irradiance)之比:
要理解这个方程的含义,可以想象一个表面被一个来自围绕着角度l的微立体角的入射光照亮,而这个光照效果由表面的辉度dE来决定。
表面会反射此入射光到很多不同的方向,在给定的任意出射方向v,光亮度dLo与辐照度dE成一个比例。而两者之间的这个取决于l和v的比例,就是BRDF。
图6 BRDF图示
一个最常见的疑问是,BRDF为什么要取这样的定义。BRDF为什么被定义为辐射率(radiance)和辐照度(irradiance)之比,而不是radiance和radiance之比,或者irradiance和irradiance之比呢?
首先,我们分别重温它们的定义:
- 辐照度(Irradiance,又译作辉度,辐射照度),表示单位时间内到达单位面积的辐射通量,也就是辐射通量对于面积的密度,通常用符号E表示,单位
,瓦特每平方米。
- 辐射率(Radiance,又译作光亮度),表示每单位立体角每单位投影面积的辐射通量,通常用符号L表示,单位是
,瓦特每球面度每平方米。
那么,关于这个问题,我们可以这样理解:因为照射到入射点的不同方向的光,都可能从指定的反射方向出射,所以当考虑入射时,需要对面积进行积分。而辐照度irradiance正好表示单位时间内到达单位面积的辐射通量。所以BRDF函数,选取入射时的辐照度Irradiance,和出射时的辐射率Radiance,可以简单明了地描述出入射光线经过某个表面反射后如何在各个出射方向上分布。而直观来说,BRDF的值给定了入射方向和出射方向能量的相对量。
概括一下:BRDF(Bidirectional Reflectance Distribution Function,译作双向反射分布函数 ),定义为出射辐射率的微分(differential outgoing radiance)和入射辐照度的微分(differential incoming irradiance)之比,描述了入射光线经过某个表面反射后如何在各个出射方向上分布,给定了入射方向和出射方向能量的相对量,单位是 ,每球面度。
4.2 BRDF的非微分形式
这里的讨论仅限于非区域光源,如点光源或方向光源。在这种情况下,BRDF定义可以用非微分形式表示:
其中:
- EL是光源在垂直于光的方向向量L平面测量的辐照度(irradiance)。
- Lo(v)是在视图矢量v的方向上产生的出射辐射率(radiance)。
4.3 BRDF与着色方程
根据上文所了解了BRDF的定义,现在,就很容易得到BRDF是如何用n个非区域光来拟合一般的着色方程的:
其中k是每个光源的索引。使用⊗符号(分段向量乘法),是因为BRDF和辉度(irradiance)都是RGB向量。考虑到入射和出射方向都拥有两个自由度(通常参数化是使用两个角度:相对于表面法线的仰角θ和关于法线的旋转角度φ),一般情况下,BRDF是拥有四个标量变量的函数。
另外,各向同性BRDFs(Isotropic BRDFs)是一个重要的特殊情况。这样的BRDF在输入和输入方向围绕表面法线变化(保持相同的相对夹角)时保持不变。所以,各向同性BRDF是关于三个标量的函数。
4.4 对BRDF的可视化表示
一种理解BRDF的方法就是在输入方向保持恒定的情况下对它进行可视化表示,如下图。对于给定方向的入射光来说,图中显示了出射光的能力分布:在交点附近球形部分是漫反射分量,因此出射光来任何方向上的反射概率相等。椭圆部分是一个反射波瓣(Reflectance Lobe)。它形成了镜面分量。显然,这些波瓣位于入射光的反射方向上,波瓣厚度对应反射的模糊性。根据互易原理,可以将这些相同的可视化形成认为是每个不同入射光方向对单个出射方向的贡献量大小。
图7 BRDF的可视化表示
五、BRDF的性质
5.1 可逆性
BRDF的可逆性源自于亥姆霍兹光路可逆性(Helmholtz Recoprpcity Rule)。
BRDF的可逆性即,交换入射光与反射光,并不会改变BRDF的值:
5.2 能量守恒性质
BRDF需要遵循能量守恒定律。能量守恒定律指出:入射光的能量与出射光能量总能量应该相等。能量守恒方程如下:
由此可知:
因此BRDF必须满足如下的积分不等式,也就是能量守恒性质:
5.3 线性特征
很多时候,材质往往需要多重BRDF计算以实现其反射特性。表面上某一点的全部反射辐射度可以简单地表示为各BRDF反射辐射度之和。例如,镜面漫反射即可通过多重BRDF计算加以实现。
六、BRDF的模型分类
根据BRDF的定义来直接应用,会有一些无从下手的感觉。而为了方便和高效地使用BRDF数据,大家往往将BRDF组织成为各种参数化的数值模型。
有各式各样的BRDF模型,如:
- Phong (1975)
- Blinn-Phong (1977)
- Cook-Torrance (1981)
- Ward (1992)
- Oren-Nayar (1994)
- Schlick (1994)
- Modified-Phong (Lafortune 1994)
- Lafortune (1997)
- Neumann-Neumann (1999)
- Albedo pump-up (Neumann-Neumann 1999)
- Ashikhmin-Shirley (2000)
- Kelemen (2001)
- Halfway Vector Disk (Edwards 2006)
- GGX (Walter 2007)
- Distribution-based BRDF (Ashikmin 2007)
- Kurt (2010)
- etc.
这些BRDF的模型可以分为如下几类:
- 经验模型(Empirical Models):使用基于实验提出的公式对BRDF做快速估计。
- 数据驱动的模型(Data-driven Models):采集真实材质表面在不同光照角度和观察角将BRDF按照实测数据建立查找表,记录在数据库中,以便于快速的查找和计算。
- 基于物理的模型(Physical-based Models):根据物体表面材料的几何以及光学属性建立反射方程,从而计算BRDF,实现极具真实感的渲染效果。
6.1 BRDF经验模型
关于BRDF的经验模型,有如下几个要点:
- 经验模型提供简洁的公式以便于反射光线的快速计算。
- 经验模型不考虑材质特性,仅仅提供一个反射光的粗糙近似。
- 经验模型不一定满足物理定律,比如Helmholtz可逆性或能量守恒定律。
- 经验模型因为其简洁和高效性被广泛运用。
常见的BRDF经验模型有:
- Lambert漫反射模型
- Phong模型
- Blinn-Phong模型
- 快速Phong模型
- 可逆Phong模型
Lambert模型,Phong模型、Blinn-Phong模型和其改进模型都是常见的光照模型,由于篇幅原因,就不展开论述了。
6.2 数据驱动的BRDF模型
数据驱动的BRDF模型可以理解为,度量一个大的BRDF材质集合,并将其记录为高维向量,利用降维的方法从这些数据中计算出一个低维模型,这样基于查表的方式,可以直接找到渲染结果,省去大量的实时计算。代表工作如:A Data-Driven Reflectance Model,ACM SIGGRAPH,2003 http://people.csail.mit.edu/wojciech/DDRM/index.html
另外,MERL等实验室使用各类仪器测量了上多种真实材质表面在不同光照角度和观察角度下的反射数据,并记录在数据库中,如MERL BRDF Database。
图8 一个名为“MERL 100”的BRDF数据库。其中,含50种“光滑材质”(例如金属和塑料),和50种“粗糙材质”(例如纺织物)
需要注意的是,由于这些数据由于采集自真实材质,即便渲染出来的结果很真实,但缺点是没有可供调整效果的参数,无法基于这些数据修改成想要的效果,另外部分极端角度由于仪器限制,无法获取到数据,而且采样点密集,数据量非常庞大,所以并不适合游戏等实时领域,一般可用在电影等离线渲染领域,也可以用来做图形学研究,衡量其他模型的真实程度。
这边提供一些数据库的链接供参考:
- MERL BRDF Database: http://www.merl.com/brdf/
- MITCSAIL: http://people.csail.mit.edu/addy/research/brdf/
- CAVE Database:http://www1.cs.columbia.edu/CAVE/databases/tvbrdf/about.php
6.3 基于物理的BRDF模型
基于物理的渲染(PBR, Physically-based rendering)是计算机图形学中用数学建模的方式模拟物体表面各种材质散射光线的属性从而渲染照片真实图片的技术,是近年来是实时渲染领域的大趋势。
基于物理的BRDF模型通过包含材质的各种几何及光学性质来尽可能精确的近似现实世界中的材料。而一个基于物理的BRDF要必须满足至少如下两条BRDF的特性:能量守恒、亥姆霍兹光路可逆性。
常见的基于物理的BRDF模型有:
- Cook-Torrance BRDF模型
- Ward BRDF模型
下文将先介绍基于物理的BRDF常常用到到的菲涅尔反射,次表面散射和微平面理论等理论,分别概括这两种基于物理的BRDF模型。
七、基于物理的BRDF · 前置知识
7.1 次表面散射 Subsurface Scattering
在真实世界中许多物体都是半透明的,比如皮肤、玉、蜡、大理石、牛奶等。当光入射到透明或半透明材料表面时,一部分被反射,一部分被吸收,还有一部分经历透射。这些半透明的材质受到数个光源的透射,物体本身就会受到材质的厚度影响而显示出不同的透光性,光线在这些透射部分也可以互相混合、干涉。
次表面散射,Subsurface Scattering,简称SSS(又简称3S),就是光射入半透明材质后在内部发生散射,最后射出物体并进入视野中产生的现象,是指光从表面进入物体经过内部散射,然后又通过物体表面的其他顶点出射的光线传递过程。
图9 次表面散射示例1
图10 次表面散射示例2
又如文章开头,贴出的《超能陆战队》中大白的渲染照中,大白的白色身体,略微有些透明的感觉,就是典型的次表面散射。
简而言之:次表面散射,即光射入表面,在材质里散射,然后从与射入点不同的地方射出表面的一种现象。
图11 光与表面的相互作用。左图,可以看到次表面相互作用导致光从入口点重新射出。红色和绿色圆圈代表两个不同尺度下的像素所覆盖的区域。在右边,所有的次表面散射光都是从入口点发出的,忽略了表面之下的细节。
7.2 菲涅尔反射 Fresnel Reflectance
菲涅耳方程(Fresnel equations)是一组用于描述光在两种不同折射率的介质中传播时的反射和折射的光学方程。方程中所描述的反射被称作“菲涅耳反射”。
菲涅尔反射(Fresnel Reflectance)或者菲涅尔效果(Fresnel Effect),即当光入射到折射率不同的两个材质的分界面时,一部分光会被反射,而我们所看到的光线会根据我们的观察角度以不同强度反射的现象。
菲涅尔反射能够真实地模拟真实世界中的反射。在真实世界中,除了金属之外,其它物质均有不同程度的菲涅尔反射效果。
关于菲涅尔反射,一个很好的例子是一池清水。从水池上笔直看下去(也就是与法线成零度角的方向)的话,我们能够一直看到池底。而如果从接近平行于水面的方向看去的话,水池表面的高光反射会变得非常强以至于你看不到池底。
图12 菲涅尔反射效果
简单来说,视线垂直于表面时,反射较弱,而当视线并非垂直表面时,夹角越小,反射越明显。
对于粗糙表面来说,在接近平行方向的高光反射也会增强但不够达到100%的强度.为何如此是因为影响菲涅尔效应的关键参数在于每个微平面的法向量和入射光线的角度,而不是宏观平面的法向量和入射光线的角度。因此我们在宏观层面看到的实际上是微平面的菲涅尔效应的一个平均结果。
根据菲涅尔反射,若你看向一个圆球,那么圆球中心的反射会较弱,而靠近边缘是反射会较强。另外需注意,这种关系也受折射率影响。
图13 基于菲涅尔反射,在Unreal Engine 4中实现的边缘光Shader
7.3 微平面理论 Microfacet Theory
微表面理论假设表面是由不同方向的微小细节表面,也就是微平面(microfacets)组成。每一个微小的平面都会根据它的法线方向在一个方向上反射光线。
表面法线朝向光源方向和视线方向中间的微表面会反射可见光。然而,不是所有的表面法线和半角法线(half normal)相等的微表面都会反射光线,因为其中有些会被遮挡,如下图所示。
图14 微平面理论图示
我们用法线分布函数(Normal Distribution Function,简写为NDF),D(h)来描述组成表面一点的所有微表面的法线分布概率。则可以这样理解:向NDF输入一个朝向h,NDF会返回朝向是h的微表面数占微表面总数的比例,比如有8%的微表面朝向是h,那么就有8%的微表面可能将光线反射到v方向。
图15 由微平面组成的表面。仅红色微平面的表面法线和半矢量h对齐,能参与从入射光线向量l到视线向量v的光线反射
NDF的定义式:
在微观层面上不规则的表面会造成光的漫反射。例如,模糊的反射是由于光线的散射造成的。而反射的光线并不均匀,因此我们得到的高光反射是模糊的。如下图。
图16 模糊的微平面高光反射
八、基于物理的BRDF · 常见模型
8.1 Cook-Torrance BRDF模型
Cook-Torrance模型作为图形学中最早的基于物理的BRDF模型,由Cook和Torrance提出,是Torrance-Sparrow模型的一个应用版本。现今,Cook-Torrance模型已经成为基于物理着色的标准模型之一。Cook-Torrance模型将物理学中的菲涅尔反射引入了图形学,实现了比较逼真的效果。
Cook-Torrance微平面着色模型(Cook-Torrance microfacet specular shading model),即Microfacet Specular BRDF,定义为:
其中:
- F为菲涅尔反射函数( Fresnel 函数 )
- G为阴影遮罩函数(Geometry Factor,几何因子),即未被shadow或mask的比例
- D为法线分布函数(NDF)
篇幅原因,就不展开论述了,若大家有兴趣,可以参考历年的SIGGRAPH Course: Physically Based Shading in Theory and Practice系列与其他相关文章。
如SIGGRAPH 2013 Course: Physically Based Shading in Theory and Practice:
http://blog.selfshadow.com/publications/s2013-shading-course/
具体的课程中的两篇推荐:
- Background:Physics and Math of Shading: http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_slides.pdf
- Physically Based Lighting in Call of Duty: Black Ops :http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_slides_v2.pdf
8.2 Ward BRDF模型
一般情况下,我们可以将BRDF分为两类:
各项同性(Isotropic)的BRDF
- 反射不受与给定表面法向夹角的约束
- 随机表面微结构
各向异性(Anisotropic)的BRDF
- 反射比随着与某个给定的表面法向之间的夹角而变化
- 图案的表面微结构
- 金属丝,绸缎,毛发等
Phong和Cook-Torrance BRDF模型都不能处理各项异性的效果,Ward模型却可以。
Ward模型由Ward于1992年提出[Measuringand Modeling Anissropic Reflection,ACM SIGGRAPH,1992]。Ward模型介绍了更一般的表面法向表达方式:通过椭圆体(ellipsoids)这种允许各向异性反射的形式来表达。
然而,由于没有考虑菲涅耳因子(Fresnel factor)和几何衰减因子(geometric attenuation factor),该模型更像是一种经验模型,但还是属于基于物理的BRDF模型。
各向同性的Ward模型定义为:
九、BRDF与其引申
有不少与BRDF类似的函数:
- BSSRDF:Bidirectional Surface Scattering Reflectance Distribution,双向表面散反射分布函数
- SBRDF(SVBRDF): spatially varying BRDF(spatial BRDF) 空间BRDF
- BTDF:Bidirectional Transmittance Distribution Function 双向透射分布函数
- BSDF : Bidirectional Scattering Distribution Function,双向散射分布函数
下面分别进行介绍。
9.1 BSSRDF
BRDF只是更一般方程的一种近似,这个方程就是BSSRDF(Bidirectional scattering-surface reflectance distribution function,双向表面散反射分布函数)。BSSRDF描述了射出辐射率与入射通量之间的关系,BSSRDF函数通过把入射和出射位置作为函数的输入,从而来包含这些现象,它描述了沿入射方向从物体表面的一点到另外一点,最后顺着出射方向出去的光线的相对量。注意,这个函数还考虑了物体表面的一点到另外一点,最好顺着出射方向出去的光线相对量。注意,这个函数还考虑了物体表面不一致的情况,因为随着位置的变化,反射系数也会发生变化。在实时绘制中,物体表面上的位置可以用来获取颜色纹理、光泽度,以及凹凸纹理图等信息。
图17 BRDF渲染图
图18 BSSRDF渲染图
9.2 SBRDF(SVBRDF)
一个捕获基于空间位置BRDF变化的函数被称为空间变化的BRDF(Spatially Varying BRDF ,SVBRDF)或称空间BRDF,空间双向反射分布函数(Spatial BRDF ,SBRDF)。
9.3 BTDF与BSDF
即使一般的BSSRDF函数,无论其多么复杂,仍然忽略了现实世界中非常重要的一些变量,比如说光的偏振。此外,也没有处理穿过物体表面的光线传播,只是对反射情况进行了处理。为了处理光线传播的问题,对物体表面定义了两个BRDF和两个BTDF(T表示传播“Transmittance”),每侧各有一个,这样就组成了BSDF(S表示散射“Scattering”)。
图19 当用于镜面反射的BRDF和用于镜面透射的BTDF使用菲涅尔公式进行调制渲染时,得到了如真实玻璃视觉上精确的反射和透射的角度变化。来自《Physically Based Rendering, Third Edition》Figure 8.10
而在实践中,这些更复杂的函数很少使用,BRDF和SVBRDF足以胜任一般情况下表面渲染的效果。
十、其他参考
[1] http://graphics.stanford.edu/~henrik/images/subsurf.html
[2] http://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/reflection-refraction-fresnel
[3] http://wiki.nuaj.net/index.php?title=BRDF
[4] https://www.allegorithmic.com/pbr-guide
[5] http://www.icourses.cn/coursestatic/course_2987.html
[6] docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/HowTo/Fresnel/index.html
[7] en.wikipedia.org/wiki/Fresnel_equations
[8] /p/21376124
[9] en.wikipedia.org/wiki/Radiometry
[10] Real Shading in Unreal Engine 4:cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf
[11] SIGGRAPH 2013 Course: Physically BasedShading in Theory and Practice:http://blog.selfshadow.com/publications/s2013-shading-course/
[12] Physically Based Rendering, Third Edition
The end.
全局光照(Global Illumination,简称 GI), 作为图形学中比较酷的概念之一,是指既考虑场景中来自光源的直接光照,又考虑经过场景中其他物体反射后的间接光照的一种渲染技术。
大家常听到的光线追踪,路径追踪等同样很酷的概念,都是全局光照中人气较高的算法流派。
而这篇文章将围绕全局光照技术,介绍的要点有:
- 全局光照的基本概念
- 全局光照的算法主要流派
- 全局光照技术进化编年史
- 光线追踪 Ray Tracing
- 路径追踪 Path Tracing
- 光线追踪、路径追踪、光线投射的区别
- 环境光遮蔽 Ambient Occlusion
一、行文思路说明
阅读过《Real-Time Rendering 3rd》第九章的读者们都会发现,作为一章关于全局光照的章节,作者讲了不少在严格意义上全局光照主线以外的内容,如Reflections、Refractions、Shadow等节,而这些内容在《Real-Time Rendering 2nd》中,其实是放在Chapter 6 Advanced Lighting and Shading一节的。
既然《Real-Time Rendering 3rd》第九章标题就叫全局光照,核心内容也是全局光照,本文即决定脱离原书安排的100来页的多余内容,以全局光照的主线内容为主,构成一篇包含全局光照基本概念,主要算法流派,以及全局光照技术进化编年史,和全局光照算法中人气较高的光线追踪、路径追踪等算法的综述式文章。
二、全局光照
全局光照,(Global Illumination,简称 GI), 或被称为Indirect Illumination, 间接光照,是指既考虑场景中直接来自光源的光照(Direct Light)又考虑经过场景中其他物体反射后的光照(Indirect Light)的一种渲染技术。使用全局光照能够有效地增强场景的真实感。
即可以理解为:全局光照 = 直接光照(Direct Light) + 间接光照(Indirect Light)
图1 Direct illumination
图2 Global illumination = Direct illumination +Indirect illumination
上述两幅图片来自CMU 15-462/15-662, Fall 2015 Slider,Lecture 14: Global Illumination,当然,细心的朋友也可以发现,它也被《Physically Based Rendering,Second Edition From Theory To Implementation》选作封面。
同样可以看到,加入了Indirect illumination的图2,在直接光源(阳光)照射不到的地方,得到了更好的亮度和细节表现,从而使整张渲染效果更具真实感。
虽说实际应用中只有漫反射全局照明的模拟算法被称为全局照明算法,但其实理论上说反射、折射、阴影都属于全局光照的范畴,因为模拟它们的时候不仅仅要考虑光源对物体的直接作用还要考虑物体与物体之间的相互作用。也是因为,镜面反射、折射、阴影一般不需要进行复杂的光照方程求解,也不需要进行迭代的计算。因此,这些部分的算法已经十分高效,甚至可以做到实时。不同于镜面反射,光的漫反射表面反弹时的方向是近似“随机”,因此不能用简单的光线跟踪得到反射的结果,往往需要利用多种方法进行多次迭代,直到光能分布达到一个基本平衡的状态。
三、全局光照的主要算法流派
经过几十年的发展,全局光照现今已有多种实现方向,常见的全局光照主要流派列举如下:
- Ray tracing 光线追踪
- Path tracing 路径追踪
- Photon mapping 光子映射
- Point Based Global Illumination 基于点的全局光照
- Radiosity 辐射度
- Metropolis light transport 梅特波利斯光照传输
- Spherical harmonic lighting 球谐光照
- Ambient occlusion 环境光遮蔽
- Voxel-based Global Illumination 基于体素的全局光照
- Light Propagation Volumes Global Illumination
- Deferred Radiance Transfer Global Illumination
- Deep G-Buffer based Global Illumination
- 等。
而其中的每种流派,又可以划分为N种改进和衍生算法。
如光线追踪(Ray Tracing)派系,其实就是一个框架,符合条件的都可称为光线追踪,其又分为递归式光线追踪(Whitted-style Ray Tracing),分布式光线追踪(DistributionRay Tracing),蒙特卡洛光线追踪(Monte Carlo Ray Tracing)等。
而路径追踪(Path tracing)派系,又分为蒙特卡洛路径追踪(Monte Carlo Path Tracing),双向路径追踪(Bidirectional Path Tracing),能量再分配路径追踪(Energy Redistribution Path Tracing)等。
其中有些派系又相互关联,如路径追踪,就是基于光线追踪,结合了蒙特卡洛方法而成的一种新的派系。
四、全局光照技术进化编年史
这节以光线追踪和路径追踪派系为视角,简单总结一下全局光照技术发展早期(1968-1997)的重要里程碑。
4.1 光线投射 Ray Casting [1968]
光线投射(Ray Casting),作为光线追踪算法中的第一步,其理念起源于1968年,由Arthur Appel在一篇名为《 Some techniques for shading machine rendering of solids》的文章中提出。其具体思路是从每一个像素射出一条射线,然后找到最接近的物体挡住射线的路径,而视平面上每个像素的颜色取决于从可见光表面产生的亮度。
图3 光线投射:每像素从眼睛投射射线到场景
4.2 光线追踪 Ray Tracing [1979]
1979年,Turner Whitted在光线投射的基础上,加入光与物体表面的交互,让光线在物体表面沿着反射,折射以及散射方式上继续传播,直到与光源相交。这一方法后来也被称为经典光线跟踪方法、递归式光线追踪(Recursive Ray Tracing)方法,或 Whitted-style 光线跟踪方法。
光线追踪方法主要思想是从视点向成像平面上的像素发射光线,找到与该光线相交的最近物体的交点,如果该点处的表面是散射面,则计算光源直接照射该点产生的颜色;如果该点处表面是镜面或折射面,则继续向反射或折射方向跟踪另一条光线,如此递归下去,直到光线逃逸出场景或达到设定的最大递归深度。
图4 经典的光线追踪: 每像素从眼睛投射射线到场景,并追踪次级光线((shadow, reflection, refraction),并结合递归
4.3 分布式光线追踪 Distributed Ray Tracing [1984]
Cook于1984年引入蒙特卡洛方法(Monte Carlo method)到光线跟踪领域,将经典的光线跟踪方法扩展为分布式光线跟踪算法(Distributed Ray Tracing),又称为随机光线追踪(stochasticray tracing),可以模拟更多的效果,如金属光泽、软阴影、景深( Depthof Field)、运动模糊等等。
4.4 渲染方程 The Rendering Equation [1986]
在前人的研究基础上,Kajiya于1986年进一步建立了渲染方程的理论,并使用它来解释光能传输的产生的各种现象。这一方程描述了场景中光能传输达到稳定状态以后,物体表面某个点在某个方向上的辐射率(Radiance)与入射辐射亮度等的关系。
可以将渲染方程理解为全局光照算法的基础,Kajiya在1986年第一次将渲染方程引入图形学后,随后出现的很多全局光照的算法,都是以渲染方程为基础,对其进行简化的求解,以达到优化性能的目的。渲染方程根据光的物理学原理,以及能量守恒定律,完美地描述了光能在场景中的传播。很多真实感渲染技术都是对它的一个近似。渲染方程在数学上的表示如下:
图5 渲染方程描述了从x点沿某一方向看的光放射的总额。
4.5 路径追踪 Path Tracing [1986]
Kajiya也于1986年提出了路径追踪算法的理念,开创了基于蒙特卡洛的全局光照这一领域。根据渲染方程, Kajiya 提出的路径追踪方法是第一个无偏(Unbiased)的渲染方法。路径追踪的基本思想是从视点发出一条光线,光线与物体表面相交时根据表面的材质属性继续采样一个方向,发出另一条光线,如此迭代,直到光线打到光源上(或逃逸出场景),然后用蒙特卡洛的方法,计算其贡献,作为像素的颜色值。
4.6 双向路径追踪 Bidirectional Path Tracing [1993,1994]
双向路径追踪(Bidirectional Path Tracing)的基本思想是同时从视点、光源打出射线,经过若干次反弹后,将视点子路径( eye path) 和光源子路径( light path) 上的顶点连接起来(连接时需要测试可见性),以快速产生很多路径。这种方法能够产生一些传统路径追踪难以采样到的光路,所以能够很有效地降低噪声。 进一步的, [Veach 1997]将渲染方程改写成对路径积分的形式,允许多种路径采样的方法来求解该积分。
4.7 梅特波利斯光照传输 Metropolis Light Transport [1997]
Eric Veach等人于1997年提出了梅特波利斯光照传输(Metropolis Light Transport,常被简称为MLT)方法。路径追踪( Path Tracing)中一个核心问题就是怎样去尽可能多的采样一些贡献大的路径,而该方法可以自适应的生成贡献大的路径,简单来说它会避开贡献小的路径,而在贡献大的路径附近做更多局部的探索,通过特殊的变异方法,生成一些新的路径,这些局部的路径的贡献往往也很高。 与双向路径追踪相比, MLT 更加鲁棒,能处理各种复杂的场景。比如说整个场景只通过门缝透进来的间接光照亮,此时传统的路径追踪方法因为难以采样到透过门缝的这样的特殊路径而产生非常大的噪声。
五、光线追踪 Ray Tracing
光线追踪(Ray tracing)是三维计算机图形学中的特殊渲染算法,跟踪从眼睛发出的光线而不是光源发出的光线,通过这样一项技术生成编排好的场景的数学模型显现出来。这样得到的结果类似于光线投射与扫描线渲染方法的结果,但是这种方法有更好的光学效果,例如对于反射与折射有更准确的模拟效果,并且效率非常高,所以当追求高质量的效果时经常使用这种方法。
上文已经提到过,Whitted于1979年提出了使用光线跟踪来在计算机上生成图像的方法,这一方法后来也被称为经典光线跟踪方法、递归式光线追踪方法,或 Whitted-style 光线跟踪方法。其主要思想是从视点向成像平面上的像素发射光线,找到与该光线相交的最近物体的交点,如果该点处的表面是散射面,则计算光源直接照射该点产生的颜色;如果该点处表面是镜面或折射面,则继续向反射或折射方向跟踪另一条光线,如此递归下去,直到光线逃逸出场景或达到设定的最大递归深度。
以下这张图示可以很好的说明光线追踪方法的思路:
图6 Ray Tracing Illustration First Bounce
图7 基于光线追踪渲染出的效果图1
图8 基于光线追踪渲染出的效果图2
图9 基于光线追踪渲染效果图 @Caustic-Graphics,Inc
图10 典型的光线追踪渲染效果图
光线跟踪的一个最大的缺点就是性能,需要的计算量非常巨大,以至于目前的硬件很难满足实时光线追踪的需求。传统的光栅图形学中的算法,利用了数据的一致性从而在像素之间共享计算,而光线跟踪通常是将每条光线当作独立的光线,每次都要重新计算。但是,这种独立的做法也有一些其它的优点,例如可以使用更多的光线以抗混叠现象,并且在需要的时候可以提高图像质量。尽管它正确地处理了相互反射的现象以及折射等光学效果,但是传统的光线跟踪并不一定是真实效果图像,只有在非常近似或者完全实现渲染方程的时候才能实现真正的真实效果图像。由于渲染方程描述了每个光束的物理效果,所以实现渲染方程可以得到真正的真实效果,但是,考虑到所需要的计算资源,这通常是无法实现的。于是,所有可以实现的渲染模型都必须是渲染方程的近似,而光线跟踪就不一定是最为可行的方法。包括光子映射在内的一些方法,都是依据光线跟踪实现一部分算法,但是可以得到更好的效果。
用一套光线追踪的伪代码,结束这一节的内容:
for each pixel of the screen
{
Final color = 0;
Ray = { starting point, direction };
Repeat
{
for each object in the scene
{
determine closest ray object/intersection;
}
if intersection exists
{
for each light inthe scene
{
if the light is not in shadow of anotherobject
{
addthis light contribution to computed color;
}
}
}
Final color = Final color + computed color * previous reflectionfactor;
reflection factor = reflection factor * surface reflectionproperty;
increment depth;
} until reflection factor is 0 or maximumdepth is reached
}
六、路径追踪 Path Tracing
路径追踪(Path Tracing)方法由Kajiya在1986年提出,该方法的基本思想是从视点发出一条光线,光线与物体表面相交时根据表面的材质属性继续采样一个方向,发出另一条光线,如此迭代,直到光线打到光源上(或逃逸出场景),然后用蒙特卡洛方法,计算光线的贡献,作为像素的颜色值。而使用蒙特卡洛方法对积分的求解是无偏的,只要时间足够长,最终图像能收敛到一个正确的结果。
简单来说,路径追踪 = 光线追踪+ 蒙特卡洛方法。
这边有一个用99行代码实现路径追踪算法的一个简易全局光照渲染器,有兴趣的朋友可以进行了解:
http://www.kevinbeason.com/smallpt/
图11 基于路径追踪渲染的效果图
图12 基于路径追踪实现的次表面散射渲染效果图 ©Photorealizer
图13 基于路径追踪渲染的效果图 ©http://www.pathtracing.com
图14 基于路径追踪渲染的效果图 ©NVIDIA
七、Ray Casting ,Ray Tracing,Path Tracing区别
初学者往往会弄不明白光线投射(Ray Casting ),光线追踪(Ray Tracing),路径追踪(Path Tracing)三者的的区别,龚大 @叛逆者 在https://www.zhihu.com/question/29863225这个答案中的回答已经很精辟,本文就直接引用了过来:
- Ray Tracing:这其实是个框架,而不是个方法。符合这个框架的都叫raytracing。这个框架就是从视点发射ray,与物体相交就根据规则反射、折射或吸收。遇到光源或者走太远就停住。一般来说运算量不小。
- Ray Casting:其实这个和volumetric可以脱钩。它就是ray tracing的第一步,发射光线,与物体相交。这个可以做的很快,在Doom 1里用它来做遮挡。
- Path Tracing:是ray tracing + 蒙特卡洛法。在相交后会选一个随机方向继续跟踪,并根据BRDF计算颜色。运算量也不小。还有一些小分类,比如Bidirectional path tracing。
文末,简单聊一下环境光遮蔽,AO。
八、环境光遮蔽 Ambient Occlusion
环境光遮蔽(Ambient Occlusion,简称AO)是全局光照明的一种近似替代品,可以产生重要的视觉明暗效果,通过描绘物体之间由于遮挡而产生的阴影, 能够更好地捕捉到场景中的细节,可以解决漏光,阴影漂浮等问题,改善场景中角落、锯齿、裂缝等细小物体阴影不清晰等问题,增强场景的深度和立体感。
可以说,环境光遮蔽在直观上给玩家的主要感觉体现在画面的明暗程度上,未开启环境光遮蔽特效的画面光照稍亮一些;而开启环境光遮蔽特效之后, 局部的细节画面尤其是暗部阴影会更加明显一些。
Ambient Occlusion的细分种类有:
- SSAO-Screen space ambient occlusion
- SSDO-Screen space directional occlusion
- HDAO-High Definition Ambient Occlusion
- HBAO+-Horizon Based Ambient Occlusion+
- AAO-Alchemy Ambient Occlusion
- ABAO-Angle Based Ambient Occlusion
- PBAO
- VXAO-Voxel Accelerated Ambient Occlusion
一般而言,Ambient Occlusion最常用方法是SSAO,如Unreal Engine 4中的AO,即是用SSAO实现。
最后,贴一些和AO相关的,较经典的渲染效果图,结束这篇文章。
图15 Scene without Ambient Occlusion ©Unreal
图16 Ambient Occlusion Only ©Unreal
图17 Scene with Ambient Occlusion ©Unreal
图18 使用环境光遮蔽制作人物的步骤
图19 一张典型的环境光遮蔽的渲染图
图20 有无环境光遮蔽渲染效果对比图示
九、其他参考
[1] http://15462.courses.cs.cmu.edu/fall2015/lecture/globalillum
[2] docs.unrealengine.com/latest/INT/Engine/Rendering/LightingAndShadows/AmbientOcclusion/
[3] en.wikipedia.org/wiki/Ambient_occlusion
[4] https://www.ics.uci.edu/~gopi/CS211B/RayTracing%20tutorial.pdf
[5] http://www.cnblogs.com/hielvis/p/6371840.html
[6] http://blog.csdn.net/thegibook/article/details/53058206
[7] http://www.di.ubi.pt/~agomes/cig/teoricas/02-raycasting.pdf
[8] ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-837-computer-graphics-fall-2012/
[9] Crytek on DX12, Vulkan, Async Compute, Global Illumination, Ray-tracing, Physically-based Rendering & E3 Demos
这是一篇近万字的总结式文章,关于游戏开发中基于图像的渲染(Image-Based Rendering,简称IBR)技术的方方面面,将总结《RTR3》书中第十章提到的16种常用的IBR渲染技术。
他们包括:
- 渲染谱 The Rendering Spectrum
- 固定视角的渲染 Fixed-View Rendering
- 天空盒 Skyboxes
- 光场渲染 Light Field Rendering
- 精灵与层 Sprites and Layers
- 公告板 Billboarding
- 粒子系统 Particle System
- 替代物 Impostors
- 公告板云 Billboard Clouds
- 图像处理 Image Processing
- 颜色校正 Color Correction
- 色调映射 Tone Mapping
- 镜头眩光和泛光 Lens Flare and Bloom
- 景深 Depth of Field
- 运动模糊 Motion Blur
- 体渲染 Volume Rendering
在过去很多年里,基于图像的渲染(Image-Based Rendering ,简称IBR),已经自成一派,逐渐发展成了一套广泛的渲染理念。正如其字面所表示的,图像是用于渲染的主要数据来源。用图像表示一个物体的最大好处在于渲染消耗与所要绘制的像素数量成正比,而不是几何模型的顶点数量。因此,使用基于图像的渲染是一种有效的渲染模型的方法。除此之外,IBR技术还有其他一些更为广泛的用途,比如云朵,皮毛等很多很难用多边形来表示的物体,却可以巧妙运用分层的半透明图像来显示这些复杂的表面。
OK,下面开始正文,对这16种常见的基于图像的渲染技术,分别进行介绍。
一、渲染谱 The Rendering Spectrum
众所周知,渲染的目的就是在屏幕上渲染出物体,至于如何达到结果,主要依赖于用户的选择,白猫黑猫,抓到老鼠的就是好猫。而用多边形将三维物体显示在屏幕上,并非是进行三维渲染的唯一方法,也并非是最合适的方法。多边形具有从任何视角以合理的方式表示对象的优点,当移动相机的时候,物体的表示可以保持不变。但是,当观察者靠近物体的时候,为了提高显示质量,往往希望用比较高的细节层次来表示模型。与之相反,当物体位于比较远的地方时,就可以用简化形式来表示模型。这就是细节层次技术(Level Of Detail,LOD)。使用LOD技术主要目的是为了加快场景的渲染速度。
还有很多技术可以用来表示物体逐渐远离观察者的情形,比如,可以用图像而不是多边形来表示物体,从而减少开销,加快渲染速度。另外,单张图片可以很快地被渲染到屏幕上,用来表示物体往往开销很小。
如《地平线:黎明》远处的树木,即是采用公告板技术(Billboard)替换3D树木模型进行渲染。(关于公告板技术的一些更具体的总结,详见本文第六节)。
图1 《地平线:黎明》中利用了Billboard进行画面的渲染
Lengyel于1998在《The Convergence of Graphics and Vision》一文中提出了一种表示渲染技术连续性的方法,名为The Rendering Spectrum 渲染谱,如下图所示。
图2 渲染谱 The Rendering Spectrum(RTR3书中版本)
图3 渲染谱 The Rendering Spectrum(Lengyel 1998论文版本)
可以将渲染谱理解为渲染的金字塔。从左到右,由简单到复杂,由二维图像到几何模型,从外观特征到物理渲染。
二、固定视角的渲染 Fixed-View Rendering
固定视角的渲染(Fixed-View Rendering)技术,通过将复杂几何模型转换为可以在多帧中重复使用的一组简单的buffer来节省大量渲染时间与性能。
对于复杂的几何和着色模型,每帧去重新渲染整个场景很可能是昂贵的。可以通过限制观看者的移动能力来对渲染进行加速。 最严格的情况是相机固定在位置和方位,即根本不移动。而在这种情况下,很多渲染可以只需做一次。
例如,想象一个有栅栏的牧场作为静态场景,一匹马穿过它。牧场和栅栏渲染仅一次,存储其颜色和Z缓冲区。每帧将这些buffer复制到可显示的颜色和Z缓冲中。为了获得最终的渲染效果,马本身是需要渲染的。如果马在栅栏后面,存储和复制的z深度值将把马遮挡住。请注意,在这种情况下,马不能投下阴影,因为场景无法改变。可以进行进一步的处理,例如,可以确定出马影子的区域,根据需求进行处理。关键是对于要显示的图像的颜色何时或如何设置这点上,是没有限制的。固定视角的特效(Fixed-View Effects),可以通过将复杂几何模型转换为可以在多帧中重复使用的一组简单的buffer来节省大量时间。
在计算机辅助设计(CAD)应用程序中,所有建模对象都是静态的,并且在用户执行各种操作时,视图不会改变。一旦用户移动到所需的视图,就可以存储颜色和Z缓冲区,以便立即重新使用,然后每帧绘制用户界面和突出显示的元素。 这允许用户快速地注释,测量或以其他方式与复杂的静态模型交互。通过在G缓冲区中存储附加信息,类似于延迟着色的思路,可以稍后执行其他操作。 例如,三维绘画程序也可以通过存储给定视图的对象ID,法线和纹理坐标来实现,并将用户的交互转换为纹理本身的变化。
一个和静态场景相关的概念是黄金线程(Golden Thread)或自适应(Adaptive Refinement)渲染。其基本思想是,当视点与场景不运动时,随着时间的推移,计算机可以生成越来越好的图像,而场景中的物体看起来会更加真实,这种高质量的绘制结果可以进行快速交换或混合到一系列画面中。这种技术对于CAD或其他可视化应用来说非常有用。而除此之外,还可以很多不同的精化方法。一种可能的方法是使用累积缓冲器(accumulation buffer)做抗锯齿(anti- aliasing),同时显示各种累积图像。另外一种可能的方法是放慢每像素离屏着色(如光线追踪,环境光遮蔽,辐射度)的速度,然后渐进改进之后的图像。
在RTR3书的7.1节介绍一个重要的原则,就是对于给定的视点和方向,给定入射光,无论这个光亮度如何计算或和隔生成这个光亮度的距离无关。眼睛没有检测距离,仅仅颜色。在现实世界中捕捉特定方向的光亮度可以通过简单地拍一张照片来完成。
QuickTime VR是由苹果公司在1995年发布的VR领域的先驱产品,基本思路是用静态图片拼接成360度全景图。QuickTime VR中的效果图像通常是由一组缝合在一起的照片,或者直接由全景图产生。随着相机方向的改变,图像的适当部分被检索、扭曲和显示。虽然这种方法仅限于单一位置,但与固定视图相比,这种技术具有身临其境的效果,因为观看者的头部可以随意转动和倾斜。
Kim,Hahn和Nielsen提出了一种有效利用GPU的柱面全景图,而且通常,这种全景图也可以存储每个纹素的距离内容或其他值,以实现动态对象与环境的交互。
如下的三幅图,便是是基于他们思想的全景图(panorama),使用QuickTime VR来渲染出的全景视野范围。其中,第一幅是全景图原图,后两幅图是从中生成的某方向的视图。注意观察为什么这些基于柱面全景图的视图,没有发生扭曲的现象。
图4 全景图原图
图5 通过全景图得到的视图1
图6 通过全景图得到的视图2
三、天空盒 Skyboxes
对于一些远离观众的物体,观众移动时几乎没有任何视差效果。换言之,如果你移动一米,甚至一千米,一座遥远的山本身看起来通常不会有明显的不同。当你移动时,它可能被附近的物体挡住视线,但是把那些物体移开,山本身看起来也依旧一样。天空盒就属于这种类型的物体。
图7 基于天空盒渲染的场景 @mad max
环境贴图(environment map)可以代表本地空间入射光亮度。虽然环境贴图通常用于模拟反射,但它们也可以直接用来表示环绕环境的远处物体。任何独立于视图的环境地图表示都可以用于此目的;立方体贴图(cubic maps)是最为常见的一种环境贴图。环境贴图放置在围绕着观察者的网格上,并且足够大以包含场景中所有的对象。且网格的形状并不重要,但通常是立方体贴图。如下图,在该图所示的室内环境更像是一个QuickTime VR全景的无约束版本。观众可以在任何方向观察这个天空盒,得到很好的真实体验。但同样,任何移动都会破坏这个场景产生的真实感错觉,因为移动的时候,并不存在视差。
图8 一个典型的立方体环境贴图
环境贴图通常可以包含相对靠近反射对象的对象。因为我们通常并没有多精确地去在乎反射的效果,所以这样的效果依然非常真实。而由于视差在直接观看时更加明显,因此天空盒通常只包含诸如太阳,天空,远处静止不动的云和山脉之类的元素。
图9 玻璃球折射和反射效果的一个立方体环境贴图,这个map本身用可作天空盒。
为了使天空盒看起来效果不错,立方体贴图纹理分辨率必须足够,即每个屏幕像素的纹理像素。 必要分辨率的近似值公式:
其中,fov表示视域。该公式可以从观察到立方体贴图的表面纹理必须覆盖90度的视域(水平和垂直)的角度推导出。并且应该尽可能隐藏好立方体的接缝处,最好是能做到无缝的衔接,使接缝不可见。一种解决接缝问题的方法是,使用六个稍微大一点的正方形,来形成一个立方体,这些正方形的每个边缘处彼此相互重叠,相互探出。这样,可以将邻近表面的样本复制到每个正方形的表面纹理中,并进行合理插值。
图10 基于天空盒渲染的场景 @rage
四、光场渲染 Light Field Rendering
所谓光场(Light Field),可以理解为空间中任意点发出的任意方向的光的集合。
而光场渲染(Light Field Rendering),可以理解为在不需要图像的深度信息或相关性的条件下,通过相机阵列或由一个相机按设计的路径移动,把场景拍摄下来作为输出图像集。对于任意给定的新视点,找出该视点邻近的几个采样点进行简单的重新采样和插值,就能得到该视点处的视图。
magic leap公司目前的原型产品,Nvidia 公司的near-eye light field display,Lytro公司发布的光场相机,都是基于Light Field技术。
图11 Lytro公司的光场相机
图12 SIGGRAPH 2014会议上,MIT’s Camera CultureGroup介绍了一种基于开普勒望远镜中投影机和光学技术的无眼镜3D的新方法。 他们提出的“压缩光场投影(Compressive Light Field Projection)”新方法由单个设备组成,并没有机械移动的物件。
五、精灵与层 Sprites and Layers
最基本的基于图像的渲染的图元之一便是精灵(sprite)。精灵(sprite)是在屏幕上移动的图像,例如鼠标光标。精灵不必具有矩形形状,而且一些像素可以以透明形式呈现。对于简单的精灵,屏幕上会显示一个一对一的像素映射。存储在精灵中的每个像素将被放在屏幕上的像素中。可以通过显示一系列不同的精灵来生成动画。
图13 基于Sprite层级制作的《雷曼大冒险》@UBISOFT
更一般的精灵类型是将其渲染为应用于总是面向观看者的多边形的图像纹理。图像的Alpha通道可以为sprite的各种像素提供全部或部分透明度。这种类型的精灵可以有一个深度,所以在场景本身,可以顺利地改变大小和形状。一组精灵也可以用来表示来自不同视图的对象。对于大型物体,这种用精灵来替换的表现效果会相当弱,因为从一个精灵切换到另一个时,会很容易穿帮。也就是说,如果对象的方向和视图没有显着变化,则给定视图中的对象的图像表示可以对多个帧有效。而如果对象在屏幕上足够小,存储大量视图,即使是动画对象也是可行的策略。
考虑场景的一种方法是将其看作一系列的层(layers),而这种思想也通常用于二维单元动画。每个精灵层具有与之相关联的深度。通过这种从前到后的渲染顺序,我们可以渲染出整个场景而无需Z缓冲区,从而节省时间和资源。
图14 基于Sprite层级制作的《雷曼大冒险》@UBISOFT
六、公告板 Billboarding
我们将根据观察方向来确定多边形面朝方向的技术叫做公告板(Billboarding,也常译作布告板)。而随着观察角度的变化,公告板多边形的方向也会根据需求随之改变。与alpha纹理和动画技术相结合,可以用公告板技术表示很多许多不具有平滑实体表面的现象,比如烟,火,雾,爆炸效果,能量盾(Energy Shields),水蒸气痕迹,以及云朵等。如下文中贴图的,基于公告板渲染出的云朵。
图15 一棵由公告板技术渲染出的树木
图16 给定表面的法线向量n和近似向上方向的向量u,通过创建一组由三个相互垂直的向量,就可以确定公告板的方向。其中,左图是互相垂直的u和n。中图是r向量通过u和n的叉乘得到,因此同时垂直于u和n,而在右图中,对固定向量n和r进行叉乘就可以得到与他们都垂直的的向上向量u’
有三种不同类型的Billboard,分别是:
- Screen-Aligned Billboard 对齐于屏幕的公告板
- World-Oriented Billboard 面向世界的公告板
- Axial Billboard 轴向公告板
其中:
- Screen-Aligned Billboard的n是镜头视平面法线的逆方向,u是镜头的up。
- Axial Billboard的u是受限制的Axial, r = u* n,(n是镜头视平面法线的逆方向,或,视线方向的逆方向),最后再计算一次n’ = r * u,即n’才是最后可行的代入M的n,表达了受限的概念。
- World-orientedbillboard就不能直接使用镜头的up做up,因为镜头roll了,并且所画的billboard原本是应该相对世界站立的,按Screen-Aligned的做法就会随镜头旋转,所以此时应该r = u * n(u是其在世界上的up,n是镜头视线方向的逆方向),最后再计算一次u = r * n,即u’才是最后的up,即非物体本身相对世界的up,亦非镜头的up。
所以公告板技术是一种看似简单其实较为复杂的技术,它的实现变种较多。归其根本在于:
- View Oriented / View plane oriented的不同
- Sphere/ Axial的不同
- Cameraup / World up的不同
如View Oriented 和View plane oriented的不同,得到的公告板效果就完全不同:
图17 两种公告板对其技术的顶视图,左图为view plane-aligned(视图平面对齐),右图为viewpoint-oriented(视点对齐),其面向的方向根据算法的不同而有所不同。
图18 使用world-oriented Billboard创建的云层
在Unreal 4 Engine中,使用Axial Billboard作为树木LOD中的一级的一些图示 :
图19 使用Axialbillboard作为树木LOD中的一级 @Unreal 4 Engine
图20 使用Axialbillboard作为树木LOD中的一级 @Unreal 4 Engine
七、粒子系统 Particle System
粒子系统(Particle System)是一组分散的微小物体集合,其中这些微小物体按照某种算法运动。粒子系统的实际运用包括模拟火焰,烟,爆炸,流水,树木,瀑布,泡沫,旋转星系和其他的一些自然现象。粒子系统并不是一种渲染形式,而是一种动画方法,这种方法的思想是值粒子的生命周期内控制他们的产生,运动,变化和消失。
可以用一条线段表示一个实例,另外,也可以使用轴向公告板配合粒子系统,显示较粗的线条。
除了爆炸,瀑布,泡沫以及其他现象以外,还可以使用粒子系统进行渲染。例如,可以使用粒子系统来创建树木模型,也就是表示树木的几何形状,当视点距离模型较近时,就会产生更多的粒子来生成逼真的视觉效果。
以下是一幅用粒子系统渲染树木的示例:
图21 基于粒子系统渲染的树木
八、替代物 Impostors
作为一种公告板技术,替代物(Impostors)是通过从当前视点将一个复杂物绘制到一幅图像纹理上来创建的,其中的图像纹理用于映射到公告板上,渲染过程与替代物在屏幕上覆盖的像素点数成正比,而不是与顶点数或者物体的复杂程度成正比。替代物可以用于物体的一些实例上或者渲染过程的多帧上,从而使整体性能获得提升。
图22 一幅树的视图和一个Impostors(Impostors的黑色背景是透明通道,在渲染时可以处理)
图23 一幅相同的树和Impostors的线框视图
另外,Impostors和Billboard的纹理还可以结合深度信息(如使用深度纹理和高度纹理)进行增强。如果对Impostors和Billboard增加一个深度分量,就会得到一个称为深度精灵(depth sprite)或者nailboard(译作钉板,感觉很奇怪)的相关绘制图元。也可以对Impostors和Billboard的纹理做浮雕纹理映射(relief texture mapping)。
关于Impostors,一篇很好的文章是William Damon的《Impostors Made Easy》,有进一步了解兴趣的朋友可以进行延伸阅读:
software.intel.com/en-us/articles/impostors-made-easy
九、公告板云 Billboard Clouds
使用Imposters的一个问题是渲染的图像必须持续地面向观察者。如果远处的物体正在改变方向,则必须重新计算Imposters的朝向。而为了模拟更像他们所代表的三角形网格的远处物体,D´ecoret等人提出了公告板云(Billboard Clouds)的想法,即一个复杂的模型通常可以通过一系列的公告板集合相互交叉重叠进行表示。我们知道,一个真实物体可以用一个纸模型进行模拟,而公告板云可以比纸模型更令人信服,比如公告板云可以添加一些额外的信息,如法线贴图、位移贴图和不同的表面材质。另外,裂纹沿裂纹面上的投影也可以由公告板进行处理。而D´ecoret等人也提出了一种在给定误差容限内对给定模型进行自动查找和拟合平面的方法。
如下是在UNIGINE Engine(注意这不是虚幻引擎,经常会被看错)中基于Billboard Clouds技术创建云层效果的一个示例:
图24 Billboard Clouds技术创建云层示例图 @UNIGINE Engine
图25 Billboard Clouds技术创建云层的最终效果图 @UNIGINE Engine
十、图像处理 Image Processing
图像处理的过程,一般在像素着色器中进行,因为在像素着色器中,可以很好地将渲染过程和纹理结合起来,而且在GPU上跑像素着色器,速度和性能都可以满足一般所需。
一般而言,首先需要将场景渲染成2D纹理或者其他图像的形式,再进行图像处理,这里的图像处理,往往指的是后处理(post effects)。而下文将介绍到的颜色校正(Color Correction)、色调映射(Tone Mapping)、镜头眩光和泛光(Lens Flare and Bloom)、景深(Depth of Field)、运动模糊(Motion Blur),一般而言都是后处理效果。
图26 使用像素着色器进行图像处理。左上为原始图像;右上角为高斯差分操作的图像,左下为经过边缘检测的图像,右下为边缘检测与原图像的混合。
十一、颜色校正 Color Correction
色彩校正(Color correction)是使用一些规则来转化给定的现有图像的每像素颜色到其他颜色的一个过程。颜色校正有很多目的,例如模仿特定类型的电影胶片的色调,在元素之间提供一致的外观,或描绘一种特定的情绪或风格。一般而言,通过颜色校正,游戏画面会获得更好的表现效果。
图27 左图是准备进行颜色校正的原图。右图是通过降低亮度,使用卷积纹理(Volume Texture),得到的夜间效果。@Valve
颜色校正通常包括将单个像素的RGB值作为输入,并向其应用算法来生成一个新的RGB。颜色校正的另一个用途是加速视频解码,如YUV色彩空间到RGB色彩空间的转换。基于屏幕位置或相邻像素的更复杂的功能也可行,但是大多数操作都是使用每像素的颜色作为唯一的输入。
对于一个计算量很少的简单转换,如亮度的调整,可以直接在像素着色器程序中基于一些公式进行计算,应用于填充屏幕的矩形。
而评估复杂函数的通常方法是使用查找表(Look-Up Table,LUT)。由于从内存中提取数值经常要比复杂的计算速度快很多,所以使用查找表进行颜色校正操作,速度提升是很显著的。
图28 原图和经过色彩校正后的几幅效果图 @Unreal 4 Engine
图29 原图和经过颜色校正的效果图 @Crysis
十二、色调映射 Tone Mapping
计算机屏幕具有特定的亮度范围,而真实图像具有更巨大的亮度范围。色调映射(Tonemapping),也称为色调复制(tone reproduction),便是将宽范围的照明级别拟合到屏幕有限色域内的过程。色调映射与表示高动态范围的HDR和HDRI密切相关:
- HDR,是High-Dynamic Range(高动态范围)的缩写,可以理解为一个CG的概念,常出现在计算机图形学与电影、摄影领域中。
- HDRI是High-Dynamic Range Image的缩写,即HDR图像,高动态范围图像。
- 而实际过程中,HDR和HDRI两者经常会被混用,都当做高动态范围成像的概念使用,这也是被大众广泛接受的。
本质上来讲,色调映射要解决的问题是进行大幅度的对比度衰减将场景亮度变换到可以显示的范围,同时要保持图像细节与颜色等表现原始场景的重要信息。
根据应用的不同,色调映射的目标可以有不同的表述。在有些场合,生成“好看”的图像是主要目的,而在其它一些场合可能会强调生成尽可能多的细节或者最大的图像对比度。在实际的渲染应用中可能是要在真实场景与显示图像中达到匹配,尽管显示设备可能并不能够显示整个的亮度范围。
图30 经过色调映射得到的高动态范围图像 @新西兰惠灵顿圣保罗教堂
十三、镜头眩光和泛光 Lens Flare and Bloom
镜头眩光(Lens flare)是由于眼睛的晶状体或者相机的透镜直接面对强光所产生的一种现象,由一圈光晕(halo)和纤毛状的光环(ciliary corona)组成。光晕的出现是因为透镜物质(如三棱镜)对不同波长光线折射数量的不过而造成的,看上去很像是光周围的一个圆环,外圈是红色,内圈是紫红色。纤毛状的光环源于透镜的密度波动,看起来像是从一个点发射出来的光线。Lens flare是近来较为流行的一种图像效果,自从我们认识到它是一种实现真实感效果的技术后,计算机便开始模拟此效果。
图31 镜头眩光效果 @WatchDogs
泛光(Bloom)效果,是由于眼睛晶状体和其他部分的散光而产生,在光源附近出现的一种辉光。在现实世界中,透镜无法完美聚焦是泛光效果的物理成因;理想透镜也会在成像时由于衍射而产生一种名为艾里斑的光斑。
常见的一个误解便是将HDR和Bloom效果混为一谈。Bloom可以模拟出HDR的效果,但是原理上和HDR相差甚远。HDR实际上是通过映射技术,来达到整体调整全局亮度属性的,这种调整是颜色,强度等都可以进行调整,而Bloom仅仅是能够将光照范围调高达到过饱和,也就是让亮的地方更亮。不过Bloom效果实现起来简单,性能消耗也小,却也可以达到不错的效果。
图32 Bloom效果 @ Battlefield3
图33 《Battlefield 3》中的渲染效果,同时包含镜头眩光(Lens flare),泛光(Bloom)和Dirty Lens
十四、景深 Depth of Field
在光学领域,特别是摄影摄像领域,景深(Depth of field,DOF),也叫焦点范围(focus range)或有效焦距范围(effective focus),是指场景中最近和最远的物体之间出现的可接受的清晰图像的距离。换言之,景深是指相机对焦点前后相对清晰的成像范围。在相机聚焦完成后,在焦点前后的范围内都能形成清晰的像,这一前一后的距离范围,便叫做景深。
图34 摄影中典型的景深效果
虽然透镜只能够将光聚到某一固定的距离,远离此点则会逐渐模糊,但是在某一段特定的距离内,影像模糊的程度是肉眼无法察觉的,这段距离称之为景深。当焦点设在超焦距处时,景深会从超焦距的一半延伸到无限远,对一个固定的光圈值来说,这是最大的景深。
景深通常由物距、镜头焦距,以及镜头的光圈值所决定(相对于焦距的光圈大小)。除了在近距离时,一般来说景深是由物体的放大率以及透镜的光圈值决定。固定光圈值时,增加放大率,不论是更靠近拍摄物或是使用长焦距的镜头,都会减少景深的距离;减少放大率时,则会增加景深。如果固定放大率时,增加光圈值(缩小光圈)则会增加景深;减小光圈值(增大光圈)则会减少景深。
景深的效果在计算机图形学中应用广泛,电影,游戏里面经常会利用景深特效来强调画面重点。相应的,已经有了很多成熟的算法在不同的渲染方法,而光栅化可以很高效的实现现有的景深算法。
图35 景深效果 @Battlefield 4
图36 景深效果 @ Witcher 2
十五、运动模糊 Motion Blur
现实世界中,运动模糊(Motion Blur,或译为动态模糊),是因为相机或者摄影机的快门时间内物体的相对运动产生的。在快门打开到关上的过程中,感光材料因为受到的是物体反射光持续的照射成像。即在曝光的这个微小时间段内,对象依然在画面中移动,感光材料便会记录下这段时间内物体运动的轨迹,产生运动模糊。
我们经常在电影中看到这种模糊,并认为它是正常的,所以我们期望也可以在电子游戏中看到它,以带给游戏更多的真实感。
若无运动模糊,一般情况下,快速移动的物体会出现抖动,在帧之间的多个像素跳跃。这可以被认为是一种锯齿,但可以理解为基于时间的锯齿,而不是基于空间的锯齿。在这个意义上,运动模糊可以理解为是一种时间意义上的抗锯齿。
正如更高的显示分辨率可以减少但不能消除锯齿,提高帧速率并不能消除运动模糊的需要。而视频游戏的特点是摄像机和物体的快速运动,所以运动模糊可以大大改善画面的视觉效果。而事实表明,带运动模糊的30 FPS画面,通常看起来比没有带运动模糊的60 FPS画面更出色。
图37 Motion Blur效果 @GTA5
在计算机绘制中产生运动模糊的方法有很多种。一个简单但有限的方法是建模和渲染模糊本身。
实现运动模糊的方法大致分3种:
1、直接渲染模糊本身。通过在对象移动之前和之后添加几何体来完成,并通过次序无关的透明,避免Alpha混合。
2、基于累积缓冲区(accumulationbuffer),通过平均一系列图像来创建模糊。
3、基于速度缓冲器(velocity buffer)。目前这个方法最为主流。创建此缓冲区,需插入模型三角形中每个顶点的屏幕空间速度。通过将两个建模矩阵应用于模型来计算速度,一个用于最后一个帧,一个用于当前模型。顶点着色器程序计算位置的差异,并将该向量转换为相对的屏幕空间坐标。图10.34显示了速度缓冲器及其结果。
图38 Motion Blur效果 @Battlefield4
运动模糊对于由摄像机运动而变得模糊的静态物体来说比较简单,因为往往这种情况下不需要速度缓冲区。如果需要的是摄像机移动时的运动感,可以使用诸如径向模糊(radial blur)之类的固定效果。如下图。
图39 径向模糊可以增强运动感 @《刺客信条》Ubisoft
十六、体渲染 Volume Rendering
体渲染(Volume Rendering),又称立体渲染,体绘制,是一种用于显示离散三维采样数据集的二维投影的技术。体渲染技术中的渲染数据一般用体素(Volumeric Pixel,或Voxel)来表示,每个体素表示一个规则空间体。例如,要生成人头部的医学诊断图像(如CT或MRI),同时生成256 x256个体素的数据集合,每个位置拥有一个或者多个值,则可以将其看做三维图像。因此,体渲染也是基于图像的渲染技术中的一种。
图40 一个典型的体渲染Pipeline
体渲染技术流派众多,常见的流派有:
- 体光线投射Volume ray casting
- 油彩飞溅技术Splatting
- 剪切变形技术Shear warp
- 基于纹理的体绘制Texture-based volume rendering
- 等。
图41 基于Splatting和voxel在Unreal 4中进行的体渲染
图42 Volume Cloud(体积云)效果 @Unity 5
图43 Volume Fog(体积雾)效果 @CRY ENGINE 3
其他参考
[1] udk-legacy.unrealengine.com/udk/Three/ColorGrading.html
[2] http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=DD633186A6579497B8B1434252979C80?doi=10.1.1.164.7222&rep=rep1&type=pdf
[3] http://blendermama.com/precise-distribution-of-trees-using-particles.html
[4] software.intel.com/en-us/articles/impostors-made-easy
[5] http://lightfield-forum.com/2014/05/mit-compressive-light-field-projection-system-for-new-glasses-free-3d-displays/
[6] bartwronski.com/2014/04/07/bokeh-depth-of-field-going-insane-part-1/
[7] http://blog.csdn.net/silangquan/article/details/17148757
[8] en.wikipedia.org/wiki/Skybox_(video_games)
[9] 胡孔明, 于瀛洁, 张之江. 基于光场的渲染技术研究[J].微计算机应用, 2008, 29(2): 22-27.
[10] forums.unrealengine.com/community/community-content-tools-and-tutorials/82804-free-trees-library
[11] http://unigine.com/cn/articles/procedural-content-generation2
[12] en.wikipedia.org/wiki/Tone_mapping
[13] en.wikipedia.org/wiki/Volume_rendering
本文提供了图形学全网学习资料的“半壁江山”——《Real-Time Rendering 4th》2000多份参考文献合集的开源Github Repo地址,以及更新了RTR4中译版的预期出版时间。
引言
“在游戏开发、实时渲染以及计算机图形学领域,《Real-Time Rendering》系列书籍一直备受推崇。有人说,它是实时渲染的圣经。也有人说,它是绝世武功的目录。”
众所周知,《Real-Time Rendering》之所以是“绝世武功的目录”,除了其精炼、综述式的行文方式,百科大全般的知识体系广度之外,主要在于其引用的丰富而事无巨细的参考文献。这些包含了详细技术细节的参考文献,才是“绝世武功秘籍的本体”所在。
时间来到2018年,《Real-Time Rendering》系列的第四版《Real-Time Rendering 4th》的参考文献的数量已经超过了2000条之多。这些参考文献散落于互联网各地,如果你有查阅过RTR4官网上放出的参考文献的链接(Real-Time Rendering Bibliography – 4th Edition),你会发现其中有不少链接已经失效。如果没有做及时的备份,且对应的文献没有其他提供源,则这些文献会面临着永久失传的风险。
所幸,本人在阅读以及翻译《Real-Time Rendering 4th》期间,花了不少业余时间,几乎详细地完全收集整理了《Real-Time Rendering 4th》2000多条的参考文献,将不少已经失效绝版的参考文献,提前备份保存了下来,构成了具有收藏价值的“绝世武功秘籍的本体”—— RTR4 2000多篇参考文献的典藏合集。
这2000多篇文献与paper,包含了大量近年来SIGGRAPH,GDC等顶会与行业盛会的核心技术paper与技术分享材料,可谓是图形学全网学习资料的“半壁江山”。
孟子有云,“独乐乐不如众乐乐”。
在这篇文章中,本人将个人收集整理的《Real-Time Rendering 4th》2000多条参考文献,即大家熟知的游戏开发与图形学业界“绝世武功秘籍的本体”,以GitHub开源的形式分享给每一位热爱游戏开发与图形学的朋友们,助力大家更好的学习和研究图形学知识,也希望能对游戏开发与图形学业界的蓬勃发展有所帮助。
RTR4参考文献典藏合集下载
首先,直接放出“绝世武功秘籍的本体”, 《Real-Time Rendering 4th》参考文献合集典藏的Github Repo地址:
GitHub – QianMo/Real-Time-Rendering-4th-Bibliography-Collection: Collection of Bibliography | Real-Time Rendering 4th (RTR4) 参考文献合集典藏
以及部分内容的预览:
这份RTR4参考文献典藏合集的特点:
- 几乎完全收集整理了RTR4 26章以及附录章节总计2000多项参考文献的全部内容。
- 其中收录了部分用常规方式无法获取的,几乎已经全网绝版的珍稀资料。
- 已包含《Real-Time Rendering 4th》所引用的部分IEEE,ACM Digital Library等付费文献库中的文献。
- 每条文献已按序号进行清晰地排序和分类,方便快捷地进行检索查阅。
- 每条文献都按照发表年份,以及发表的媒介对文件名进行标注,以方便快捷的辨识文献年份与参考价值。
- 已进行了较为完善的文件尺寸精简,将所有单个文件都控制于100M以内,方便更快地下载与本地存储。
- 已按照原书正文、补充章节第25章、补充章节第26章、附录四个主要部分进行文献的分类,便于查阅。
以下是《Real-Time Rendering 4th》参考文献典藏版的文件构成以及内容统计:
一些说明:
- 互联网的记忆有时十分短暂。随着时间的流逝,越来越多的资料的原始链接会失效。而这个Github Repo会作为一个图形学系列资料留存和备份的大本营。
- 还有极个别文献还未在此Github Repo中收录,也欢迎大家的Pull Request。
- 建议大家下载后离线查阅,当然,Github对pdf等文件也有在线预览功能,也可以方便地进行在线浏览。
- RTR4的行文有一个非常地道的地方,那便是除了第1章和第24之外,每章都提供了“延伸阅读与参考资料 Further Reading and Resources”,如果你希望在某一细分领域专研得比RTR4的某章节正文所讲述的内容更加深入,那这些被重点提名的文献和书籍,将是绝佳的进阶学习材料。对此,此Github Repo也额外分章节专门收集整理了RTR4每章结尾的“延伸阅读与参考资料 Further Reading and Resources”中的书籍和文献,方便大家对RTR4每章的进阶内容进行更深入的学习与研究。具体可见链接:github.com/QianMo/Real-Time-Rendering-4th-Bibliography-Collection/tree/main/Further%20Reading
这一节末尾,为方便大家阅读,这里再一次贴出《Real-Time Rendering 4th》参考文献合集典藏的Github Repo地址:
github.com/QianMo/Real-Time-Rendering-4th-Bibliography-Collection
以及对应的下载链接:
codeload.github.com/QianMo/Real-Time-Rendering-4th-Bibliography-Collection/zip/refs/heads/main
(PS: 如果出现解压错误,请使用7zip解压,或者可以直接git clone到本地)
正如上文提到的,这2000多篇参考资料,可谓是图形学全网学习资料的“半壁江山”。希望这一Github开源版本的《Real-Time Rendering 4th》参考文献合集,能对游戏开发与图形学业界的蓬勃发展有所裨益。
关于RTR4中译版的出版时间的Update
在之前的文章《两件 Big Thing:天美跨平台3A大作全球招聘令 & RTR4中译版出版时间预告》中,有提到过,“如果没有特殊的不可抗因素,《Real-Time Rendering 4th》的中译版会在年底与大家正式见面”。
而目前而言,还真有一些不可抗因素的发生,所以《Real-Time Rendering 4th》中译版可能需要到明年上半年再与大家见面。
最后,同样是感谢大家对《Real-Time Rendering 4th》中译版的热爱与关注。接下来的时间,我们依然会继续努力,将《Real-Time Rendering 4th》中译版的翻译品质在时间与能力范围内做到尽善尽美。
以上。