来源:https://blog.csdn.net/poem_qianmo
第八章 全局光照:光线追踪、路径追踪与GI技术进化编年史
常见的全局光照主要流派列举如下:
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
等。
这里有一个用99行代码实现路径追踪算法的一个简易全局光照渲染器,有兴趣的朋友可以进行了解:
http://www.kevinbeason.com/smallpt/
Ray Tracing:这其实是个框架,而不是个方法。符合这个框架的都叫raytracing。这个框架就是从视点发射ray,与物体相交就根据规则反射、折射或吸收。遇到光源或者走太远就停住。一般来说运算量不小。
Ray Casting:其实这个和volumetric可以脱钩。它就是ray tracing的第一步,发射光线,与物体相交。这个可以做的很快,在Doom 1里用它来做遮挡。
Path Tracing:是ray tracing + 蒙特卡洛法。在相交后会选一个随机方向继续跟踪,并根据BRDF计算颜色。运算量也不小。还有一些小分类,比如Bidirectional path tracing。
环境光遮蔽(Ambient Occlusion,简称AO)
是全局光照明的一种近似替代品,可以产生重要的视觉明暗效果,通过描绘物体之间由于遮挡而产生的阴影, 能够更好地捕捉到场景中的细节,可以解决漏光,阴影漂浮等问题,改善场景中角落、锯齿、裂缝等细小物体阴影不清
第九章 游戏开发中基于图像的渲染技术总结
渲染谱 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
第十章 非真实渲染(NPR)
非真实感渲染(Non-Photorealistic Rendering,NPR)
亦被称为风格化渲染(Stylistic Rendering),是致力于为数字艺术提供多种表达方式的一种渲染流派。与传统的追求照片真实感的真实感渲染(Photorealistic Rendering)计算机图形学不同,非真实感渲染旨在模拟艺术式的绘制风格,也用于尝试新的绘制风格。
卡通渲染
轮廓描边的几种实现流派
1)基于视点方向的描边
2)基于过程几何方法的描边
3)基于图像处理生成的描边
4)基于轮廓边缘检测的描边
5)混和轮廓描边
其他风格的NPR渲染技术
1)纹理调色板(Palette of Textures)
2)色调艺术图(Tonal Art Maps,TAM)
3)嫁接(Graftals)
水彩风格的NPR
第十一章 游戏开发中渲染加速算法
常用空间数据结构(Spatial Data Structures)
层次包围盒(BVH ,Bounding Volume Hierarchies)
BSP树(Binary Space Partitioning Trees)
八叉树(Octrees)
场景图(Scene Graphs)
![](https://i-blog.csdnimg.cn/blog_migrate/4879595624b9986c5c496e7d048a9b77.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/65aab3aba3a481ee69e9c8648e6d35f3.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/101df5f69a8e993992f9e2f4677e4e37.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/16c8723475e9245d6fce5a62df69f398.jpeg)
各种裁剪技术(Culling Techniques)
背面裁剪(Backface Culling)
视锥裁剪(View Frustum Culling)
遮挡剔除(Occlusion Culling)
层次视锥裁剪(Hierarchical View Frustum Culling)
入口裁剪(Portal Culling)
细节裁剪(Detail Culling)
各种层次细节(LOD,Level of Detail)技术
几种LOD切换技术(Discrete Geometry LODs、Blend LODs、Alpha LODs、CLODs and Geomorph LODs)
几种LOD的选取技术(Range-Based、Projected Area-Based、Hysteresis)
大型模型的渲染(Large Model Rendering)
点渲染(Point Rendering)
第十二章 渲染管线优化方法论:从瓶颈定位到优化策略
光栅化阶段的瓶颈定位
光栅化操作:测试帧缓冲带宽是否是瓶颈所在,比较好的办法是改变颜色缓冲的位深度,或深度缓冲的位深度(也可以同时改变两者)。另外,帧缓冲带宽也与GPU显存频率(GPU memory clock)有关,因此,修改该频率也可以帮助识别瓶颈。
纹理带宽:比较推荐使用大量正等级mipamap细节层次(LOD)的偏差,让纹理获取访问非常粗糙的mipmap金字塔级别,来有效地减小纹理尺寸。纹理带宽也与GPU显存频率相关。
片元着色:调整分辨率使得性能改变,片元着色就可能是瓶颈所在。片元着色的速度与GPU核心频率有关。
几何阶段的瓶颈定位
顶点与索引传输:可以通过调整顶点格式的大小,来确定得到顶点或索引传输是否是应用程序的瓶颈。如果数据放在系统内存内,得到顶点或索引的性能与AGP或PCI Express总线传输速率有关;如果数据位于局部缓冲内存,则与内存频率有关。
顶点变换:对于可编程的顶点变换,只要简单地改变顶点程序的长度,就能确定顶点处理是否是瓶颈。对于固定功能的顶点变换,判定瓶颈则有点麻烦。试着通过改变顶点的工作,例如修改镜面光照或纹理坐标生成的状态来修改负载。顶点处理的速度与GPU核心频率有关。
应用程序阶段的瓶颈定位
可以用Profiler工具查看CPU的占用情况。主要是看当前的程序是否使用了接近100%的CPU占用。比如AMD出品的Code
Analyst代码分析工具,可以对运行在CPU上的代码进行分析和优化。Intel也出品了一个称为Vtune的工具,可以分析在应用程序或驱动器(几何处理阶段)中时间花费的位置情况。
一种巧妙的方法是发送一些其他阶段工作量极小甚至根本不工作的数据。对于某些API而言,可以通过简单地使用一个空驱动器(就是指可以接受调用但不执行任何操作)来取代真实驱动器来完成。这就有效地限制了整个程序运行的速度,因为我们没有使用图形硬件,因此CPU始终是瓶颈。通过这个测试,我们可以了解在应用阶段没有运行的阶段有多大的改进空间。也就是说,请注意,使用空驱动程序还隐藏了由于驱动程序本身和阶段之间的通信所造成的瓶颈。
另一个更直接的方法是对CPU 进行降频( Underclock)。如果性能与CPU速率成正比,则应用程序的瓶颈与CPU相关。但需要注意,降频的方法可以帮助识别瓶颈,也有可能导致一个之前不是瓶颈的阶段成为瓶颈。
另外,则是排除法,如果GPU阶段没有瓶颈,那么CPU就一定是瓶颈所在。
对CPU的优化策略
减少资源锁定:可以尝试避免访问渲染期间GPU正在使用的资源。
批次的尺寸最大化:
若使用了三角形带(Triangle Strips),则使用退化三角形(Degenerate Triangles)将不相交的条带拼接起来。
使用纹理页(Texture Pages)。
使用Shader分支来增加单个批次大小从而合批。
将顶点着色器常量内存(vertex shader constant memory)作为矩阵查找表(Lookup Table of matrices)使用。
尽可能远地往管线下端推迟决策。
应用程序阶段的优化策略
内存层面的优化:
在代码中连续访问的存储内容在内存中也应保持连续存储。尽量避免指针的间接、跳转,以及函数调用,因为它们很容易显著降低CPU中缓冲的性能。
某些系统中,默认的内存分配和删除功能可能比较慢,因此,在启动时最好为相同大小的对象分配一个大的内存池,然后使用自己分配或空闲部分来处理该池的内存。
尽量尝试去避免在渲染循环中分配或释放内存。
对数据结构尝试用不同的组织形式。
4.2.2 代码层面的优化
善用SIMD。单指令多数据流(Single Instruction Multiple Data,SIMD)。
使用float转long转换在奔腾系列处理器上速度较慢。如果可以请尽量避免。
尽可能避免使用除法。
许多数学函数,如sin、cos、tan、exp、arcsin等,计算开销较高,使用的时候必须小心。
条件分支会有一定的开销,Shader中的条件分支开销尤甚。
对于经常调用的小函数使用内联(Inline)。
在合理的情况下减少浮点精度,比如用float代替double。
尽可能使用低精度数据,让发送到图形管线的数据量更少。
虚函数方法、动态转换、(继承)构造,以及按值传递结构体(passing structs by value)都会对效率造成一定影响。
API调用的优化策略
一种减少API调用的方法是使用某种形式的实例(Instance)
进行批处理(batching)。
可以用不同的颜色来合并对象,例如,通过用标识符对每个对象的顶点进行标记。
多人同屏的场景很适合使用实例进行渲染,其中每个角色都拥有独特的一套外表。
提高性能的另一种方法是通过将具有类似渲染状态的对象(顶点和像素着色器、纹理、材质、光照、透明度等)分组并将它们按顺序渲染,从而最小化状态更改。
具有使用共享材质(shared material)的节点可以进行分组,以获得更好的性能,而用共享纹理(shared texture)绘制多边形可以减小纹理缓存的抖动
理解对象缓冲(object buffer)在渲染时的分配和存储方式也同样重要。
几何阶段的优化策略
变换、光照、裁剪、投影,以及屏幕映射操作可以使用较低精度的数据,以减小开销。
合理地使用索引和顶点缓冲区可以帮助几何阶段减小计算量。
可以简化模型来减小整个管线的顶点和绘制图元的数量,以降低顶点数据传输和顶点变换成本。而诸如视锥裁剪和遮挡剔除之类的技术避免了将全部的图元发送到管线。
可以使用缓存感知(cache-oblivious)布局算法,其中顶点以某种形式排列,以最大限度地提高缓存重用性,从而节省处理时间。(具体可见RTR3原文 12.4.4节)
同理,为了节省内存和访问时间,尽可能在顶点、法线、颜色和其他着色参数上,选择更低精度的数据格式。有时我们会在half、single、double。float精度之间做选择,需要注意,除了其中因为精度更低带来的速度提升外,有些格式也会因为是硬件内部使用的原生格式(native format)而更快。
减少内存使用的另一种方法是将顶点数据存储在压缩格式中。
光照计算的优化策略
首先,应该考虑使用的光源类型,以及可以考虑是否所有的多边形都需要光照。
如果光源是静态的,且照明对象是几何体,那么漫反射光照和环境光可以预先计算并存储在顶点颜色中。
控制光源的数量。
一种常见的优化方法是根据光源的距离来进行剔除,只渲染受本地光源影响的对象。
另一种减少工作的方法是禁用光源,取而代之的是使用环境贴图(environment map)
如果场景拥有大量光源,可以使用延迟着色技术来限制计算量和避免状态的变化。
光栅化阶段的优化策略
善用背面裁剪。
一种光栅化阶段的优化技术是在特定时期关闭Z缓冲(Z-buffering)。
值得一提的是,如果在使用Z缓冲,在一些系统上使用模板缓冲不需要额外的时间开销。
优先使用原生的纹理和像素格式。
另一种适用于光栅化阶段的优化技术是进行合适的纹理压缩。
另一种有用的相关优化技术是基于物体和观察者之间的距离,使用不同的像素着色器。
理解光栅化阶段的行为。为了很好地理解光栅阶段的负荷,可以对深度复杂度进行可视化,所谓的深度复杂度就是指一个像素被接触的次数。生成深度复杂度图像的一种简单方法就是,使用一种类似于OpenGL的glBlendFunc(GL ONE,GL ONE)调用,且关闭Z缓冲。首先,将图像清除成黑色;然后,对场景中所有的物体,均使用颜色(0,0,1)进行渲染。而混合函数(blend function)设置的效果即是对每个渲染的图元来说,可以将写入的像素值增加(0,0,1)。那么,深度复杂度为0的像素是黑色,而深度复杂度为255的像素为全蓝色(0, 0, 255)。
可以通过计数得到通过Z缓冲与否的像素的数量,从而确定需进一步优化的地方
加速片元着色:
优先渲染深度。
帮助early-z优化(即Z缓冲优化),来避免多余片元处理 。=
在纹理中存储复杂功能。
将更多每片元的工作移到顶点着色器。
使用必需的最低精度。
避免过度归一化(Normalization)。
考虑使用片元着色器的LOD层次细节。
在不必要的地方禁用三线性过滤。
使用尽可能简单的Shader类型。
减少纹理带宽:
减少纹理尺寸。
压缩所有的彩色纹理。
避免没必要的昂贵纹理格式。
优化帧缓冲带宽:
首先渲染深度。
减少alpha混合。
尽可能关闭深度写入。
避免无关的颜色缓冲区清除。
默认大致上从前向后进行渲染。
优化天空盒的渲染。天空盒经常是帧缓冲带宽的瓶颈,因此必须决定如何对其进行优化,以下有两种策略:
(1)最后渲染天空盒,读取深度,但不写入深度,而且允许和一般的深度缓冲一起进行早期early-z优化,以节省带宽。
(2)首先渲染天空盒,而且禁用所有深度读取和写入。
以上两种策略,究竟哪一种会节省更多开端,取决于目标硬件的功能和在最终帧中有多大部分的天空盒可见。如果大部分的天空盒被遮挡,那么策略(1)更好,否则,策略(2)可以节省更多带宽。
仅在必要时使用浮点帧缓冲区。
尽可能使用16为的深度缓冲区。
尽可能使用16位的颜色。