3D渲染技术 探索

本人同意他人对我的文章引用,但请在引用时注明出处,谢谢.作者:蒋志强

多年未更新技术BLOG,这次系统的谈一下3D渲染技术

目录

1.三维渲染 软硬件的历史

2.图形学的挑战与对策-真实感

  DOF/Texture/Dynamic Shadow/Texture Mapping/Bloom/Flame,Fog/GI-3S/Volumetric Lighting/GI-RayTracing etc.

3.图形学的未来发展


1.三维渲染 软硬件的历史

80年代3D显卡还没有出现(已经有2D显卡),但图形学已经发展很久了,人们已经在计算机如何可视化三维空间物体方面 有了完备的理论;线性代数,几乎就是为三维图形学 私人定制的表达和计算基础。相对于当时的PC较弱硬件的能力,三维渲染还停留在服务器计算 影视作品中;(像现在游戏界很火的光线追踪等技术,在当时就已经有很深入的研究了)

这样的情况直到90年代初期,3DFX,MATROX,S3,Nvidia,SiS,ATI等公司的努力下,专门针对3D图形学计算的3D硬件显卡出现,并推动了三维渲染的巨大发展,让三维渲染的应用推向了普及;

是三维渲染发展有两个常态:

1. 理论等待工程(软件&硬件)发展

2. 效率是关键

硬件上

通过线性代数描述三维的物体,需要X,Y,Z三个量,线性代数上要线性独立需要第4个维度,实际上三维的基础计算单元是4维向量,所以当时显卡的物理硬件计算单元是4元向量(现在也是);

三维表达的大小/位置不在乎绝对值,而取决于相对值,浮点更合适三维计算,所以显卡芯片的浮点计算能力强于定点(现在也是);

为了快,大量顶点传入进入显卡后,线性代数的几何变换计算相互独立并行进行,直至显示到屏幕,数据不再出显卡,所以在硬件架构上循环/判断是GPU的弱项,数据CPU/GPU间传递效率是弱项(现在也是);

软件上

硬件上的变革,需要软件的协同以便高效的控制底层,Glide(3DFX),DirectX(MS),OpenGL(Khronos)成为了主流3D接口;

 

它们专门为编写软件三维渲染而生,天然的面向渲染硬件管线;(由于3DFX后来垮掉了,DX/GL成了现在软件标准)

DX/GL的上层描述实际上是面向硬件的描述,以现代GL为例(DX是一样的),软件层描述的简化硬件管线如下

类似于工厂加工的流水线结构,数据一旦进入,一路向前 直到显示,相应3D处理运行在硬件指令级别;

(黄色是硬件级计算单元:着色器)

插播GPGPU广告

2007年前后发展起来的GPGPU应用,本质上是搭渲染链路GPU的顺风车。图中我圈红的Vertex/Fragment着色器是最古老的着色器,在GPU最早阶段就存在。Vertex的X/Y/Z/W是4元向量计算,Fragment的R/G/B/A也是4元像素计算,很多的矩阵操作也很类似,所以NVIDIA在与MS合作第一代XBOX时,将两类着色器在硬件层统一起来,相当程度上可以互换,称为统一着色器

统一着色器克服了某些应用下顶点计算单元不够而像素计算单元空闲,或者顶点计算单元空闲而像素计算单元不够的窘境。

而显卡中的矩阵计算 A*B ,

其中包含了加法/乘法,而且计算的元素是浮点数,乘以一个大于0的小于1的数,等效于除法,加上一个负数,等效于减法;

实际上这基于浮点运算的矩阵乘法已经是在硬件级别具备了加/减/乘/除的基本运算能力,所有更高阶的计算都可以拆解为加减乘除;所以渲染链路中的着色器在硬件级别具备通用计算的全部能力

由于在XBOX上非常成功,PC端的GPU架构也做了这样的改变,这在硬件层面扫清了GPGPU的最后一个困难,所以才有了CUDA/OpenCL的发展。对于存做GPGPU的朋友,往往简化理解GPU内部是compute unit或是CUDA core,实际上后面是各类渲染链路中的着色器;

我们需要清楚:

1. 凡是渲染管线GPU面临的问题,GPGPU都逃不掉;(当你当顺风车时,你也需要接受别人车上的具体问题)

2. 3D渲染方面,若能做成渲染管线的方式,效率胜过GPGPU;(GPU硬件毕竟是为3D渲染“私人定制”的)

建议:做3D渲染,首先考虑做进渲染管线,太难做进渲染管线的部分,以GPGPU方式配合渲染管线;

广告结束


2.图形学的挑战与对策-真实感

什么是真实感?

一种主观感觉 还是 客观量化的成分。什么因素让我们觉得计算机渲染的结果 真实 或 不真实?

我的理解是:人对可见光的各种物理规律的主观经验印像。它与两个方面相关

1. 它与外界客观物理规律相关;

2. 它与人的生理结构相关;

下面是两幅计算机渲染场景(左:极品飞车2渲染截图;右:CryEngine渲染截图)

   

我如果说左图不真实,右图很真实,大部分朋友应该会同意;造成这样的感受

1.物理相关:

左图中:白车后的尾气与常识印象不符;汽车表面反射与印象不符;地面图像成方块状与印象不符;雨水形态与印象不符

周边树木形态和光照与印象不符;环境中光照生硬与印象不符等等... ...

2.生理相关:

左图中:运动中物体无运动的模糊速度感,与印象不符;远处物体变淡,而不是变模糊,与印象不符;天空中没有耀眼的感觉,与印象不符;等等... ...

人眼一扫,只需要不到半秒,大脑就能发现左图中如此多的与物理规律和生理感知的问题,让我们不仅惊叹,这些问题也成为了图形学发展中的挑战;

下面来看看历史上图形学的工程师们的努力和解决方案

景深DOF

     

人的眼睛,摄像机的镜头 本质上 是凸透镜,当我们调整眼球晶状体形态 或 相机镜头焦距时,能把相应距离的物体清晰的落在视网膜 或者 摄像机的CCD上,而偏离这个距离的物体将逐渐模糊,这就是景深Depth of Field,虚化是DOF的典型效果;

在3D渲染中,常见方式是把渲染物体先计算其成像距离,根据距离远近设置模糊的程度,以近似的模拟DOF;

 

左边是最终效果,右边是深度图,根据深度图分批多次渲染,远离焦区的物体逐渐加强模糊,然后按先远后近的的次序合并(以确保遮挡关系正确)。

这是近似模拟,我自己也尝试不用深度图模糊,而从人眼聚焦原理上来实现,如下图(左图是不考虑人眼透镜效应,右图是根据人眼聚焦成像)

  

动态阴影

有光照就会有阴影,特别是渲染场景中有运动物体或运动光源,总会造成阴影的动态变化于交互,这就是动态阴影;

是否考虑动态阴影的差别如下

一般来说,动态阴影需要在渲染管线里走两次或多次;常规思路有shadow map, shadow volume等等;

我以shadow map为例解释,如图所示渲染一些在单个点光源下的小球;

  

首先从光源方向进行成像,获得一幅渲染结果,只取渲染结果中物体距离光源的远近,留做后续渲染备用

变换至观察位置后,进行第二轮常规渲染,判断观察面中的任意点距离光源的位置,是否比之前的距离光源的远近大,从而进行不同策略的渲染;

我自己也写程序试了试,效果如下(我很懒,第二轮渲染时,什么酷的效果都没做)

纹理贴图

纯色的物体与真实情况差距很大,工程师们创造了纹理的概念去表达细节。最简单的情况,纹理贴图是贴在几何多边形上映射位图,用以伪造实际的物品。我写了程序,用多边形画个球,给些基本光照,看上去如下左图。看上去也不知道是什么东西,我打算伪造成地球,所以找张地球的二维投影位图(如下图中间),把它映射到到相应球面的点上,效果如下图右侧,似乎像个地球仪了

PS:感兴趣的朋友,可以看看OpenGL中的光照_Z_Jiang的博客-CSDN博客 (太古老,仅供概念了解一下)

           

这样做问题很多,虽然它多了纹理像素信息,但它是平的,没有影响到光照。所以工程师们创造了新的纹理技术 叫做

Bumpping Texture Map.让映射到的表面结构,看上去发生了变化。Bumpping Map第一种思路,是Normal Map,多创造一层纹理,叫做NormalMap,它存储法向量调整信息一种。对于物体上的点,先计算基本法向量,再用NormalMap调整,再计算光照。让物体的光照效果受到影响,让人感觉表面似乎凹凸不平,反应出更多细节。

  

Normal Map以一张纹理的代价,换来了三角形个数的大幅减少的同时,让其达到高三角形模型的细腻效果。Normal Map一般是通过专业建模软件生成,先做一个低三角形的模型,再做一个多三角形的模型,两者几何法向量做差得到Normap Map以纹理格式存储(R/G/B分量表达X/Y/Z的几何法向量),渲染时使用低三角形模型,配合Normal Map对低模的法向量调整,以达到少花钱(资源)多办事(近似高模的细节信息)。

但Normap Map只是操纵了光线的法向量,没有改变实际几何形态和纹理位置,所以只可远观,近看漏洞百出,特别是平行与三角形平面时,几何关系的错误暴露明显。如下图的Normal Map,其凸出的砖块的纹理位置是不变的。

如下图,由于凹凸的关系,观察者看到的应该是a点,但实际情况下看到的是b点,解决方式是在这个位置把a处的纹理坐标调整到b处,修正其假像,如何计算修正值,所以工程师们引入了高度图,创造了Parallax Map

   

下图是Parallax Map的效果

Parallax Map并没有增加顶点/三角形个数,但计算量已经比较大了,需要逐像素计算其纹理偏移量,Fragment着色器压力已经较大,寻找合适偏移位置往往绕不开循环查找,GPU痛恨while语句,反复纹理采样,访问显存,GPU痛恨访问显存,工程师需要好好衡量。

Parallax Map也有一些问题,比如几何上还是没有真正创造出更复杂的细节结构,比如光照下阴影的问题,工程师们总是喜欢挑战,又创造出带自阴影的Relief Map(浮雕贴图)技术,双深度Relif Map技术等。但后续这些技术,往往都伴随一些side effect或者计算过于复杂了。(感觉成本比做高三角形模型的成本还高)

补充

以上这些方式基本上都是为了在减少三角形个数的情况下,还尽力模拟其效果。另一类思路是分形,在减少三角形输入个数的情况下,在显卡内部链路中细分出更多的三角形,这也就是细分控制,细分评估着色器的专长,本质上就是做分形,如下图

左图:分形前,右图:分形后

Light Baking 光照烘培

光照的计算成本是很高的,特别是高质量的光照,所以图形学的工程师创造了Light Baking的思路。先由3DS MAX, Maya,Unreal,Unity等工具进行离线计算,然后将计算结果生成场景的纹理贴图,大部分固定光源的效果由纹理贴图表现;

如下图左(Unity离线烘培光照),下图右(Maya离线烘培)

  

在实际渲染中,基础光照全由离线烘培提供,运动人物,光源再进行实时计算;由于离线烘培不占用实时资源,我们有可能使用高复杂度,高度物理准确的光照模型,例如复杂材质情况下的光线追踪,如下图(UnReal的Ray Tracing级别离线烘培)

3D游戏中一般是烘培基本场景,如下图

AO环境遮挡

Ambient Occlusion是另一种讨巧的光照技术思路,基本思路是计算:物体的直接/间接光照被周边几何结构的遮挡

可以实时计算,也可以提前烘培至纹理。它是一种很便宜的GI方式,在合适的情况下效果不错,价格便宜。

如下示意,AO值是在空间上做积分,计算特定点有多少光线被遮挡。

如下图(左:原始渲染NO AO, 中:AO计算图,右:原始渲染+AO)

AO可以离线做成纹理,也可以在屏幕空间实时计算(SSAO,最早由CryTek公司创造),是一种性价比 比较高的

GI间接光照的解决方案;

Bloom晕光

当我们的眼睛观察较强的光照物体时,由于光照过强在视网膜成像位置周边有较强的散射,会感觉晕开,亮瞎了我的狗眼。

这就是晕光效果;

常规的处理思路是,再进行一轮渲染,只提取较高亮度的区域(如果你需要加强效果,可以把这一部分亮度更加强一些)

多该内容离线BLUR

screen_bp_5x5.jpg

然后于原渲染图混合;

烟雾及火焰

烟雾/火焰 是3D渲染的短板,因为3D显卡内部的基础处理元素是顶点,三角形,平面等离散的几何单元,而烟雾是一堆?一坨?

所以烟雾很不好表达,图形学的兄弟们创造出了点精灵(Point Sprite),在现代显卡的硬件都能支持。它只是一个点,抽象单个点无法映射二维纹理,点精灵的妙处就是它可以有尺寸大小,所以可以给它进行二维纹理映射,并且它始终面向视线;把一大堆点精灵聚集在一起,就能创造出烟雾,火焰,粒子等效果,下图就是众多的点精灵呈现的云雾;

点精灵呈现的火焰

其实没有点精灵也能做,但Point Sprite专为粒子系统而生,传1个点顶4四个用,而且始终朝向摄像机,是效率最高的。研究图形学的朋友一定还知道,Geometry Shader也能做类似的事情,传1个点给它,它可以创造N个点;

下面是我自己写了个小程序,只输入了4个顶点,本来只能做1个四边形,但却绘制了15个四边形,多出来的四边形都是在管线内部创造出来的。

建议做烟雾,火焰还是用Point Sprit,因为它是仍是效率之王。在Geeks3D上有朋友做过效率PK,结果如下

更真实的光照SSS

前面提到的光照阴影,其实有不少瑕疵,例如光线只有照到或没有照到的明暗,实际上很多物体是半透明的,阴影不是实的,有的物体挡住光后,光还能通过它,只是变弱变暗,同时变弱的光还会反射透回来,同时光在传播过程中还会发生各种变化,这属于GI(Global illumination)中高大上的SSS光照效果(Sub Surface Scattering)的范畴。

下面这幅stanford dragon的渲染就是这样的例子

我们注意到这个dragon没有绝对生硬的黑色阴影,这更符合我们对光的主观经验印象,所以我们感觉更真实

类似的效果是shadow map,shadow volume等都做不到的,所以我们需要创造新的思路。自然界中本就不存在阴影,所谓阴影不过是那个地方的光相对较弱。

所以我以此为思路,写了个程序,找了个CT的人头数据,渲染效果如下

效果已进步不少,但比dragon差些(主要是我程序里只处理了单色而不是彩色的);

如下左图(照片)是真实的光照效果,我自己把前面做DOF的数据拿来,写了GI SSS的程序,渲染效果如下右图

  

目前,医疗彩超3D成像暂时停留在这个层面,下图是商用超声3D成像中的渲染效果;

在3D影视特效的渲染中,为了达到真实感,在渲染人物皮肤时运用GI中的SSS只是初级要求;

(其实全局的Ray Tracing,也是基本标配,我们后面会提到)

Volumetric Lighting 体光照

光照会产生体散射的效果,如下图所示。

本质上,这是由于大气环境中,存在很多小的灰尘颗粒,这些颗粒产生散射。我自己写了程序模拟,做得不好,但原理是相同的,如下图所示:

商业级渲染引擎中(如UnReal/Unity/Crysis Engine/etc...)帮大家都做完了,打个勾就行了。

PS: 目前像UnReal, Unity等引擎都已开源,是个宏大的图形学宝库,可以好好学习。

光线追踪 Ray Tracing

光线追踪是图形学里很老的概念,属于Global illumination范畴中经典的解决方案,它研究光线直接照射到物体上后,间接反射到其它物体上,产生间接光照,间接光照又产生间接光照,如此反复循环。理论上,它是无限的递归,计算复杂度是 无穷大。它向实际物理光照迈进了一步(实际物理光照还有衍射效应,菲尼尔现象,波动性,色散等),所以能产生较强的真实感,下图是典型的光线追踪效果

注意白光照到墙壁后产生二次反射,让立方体物体带上颜色,立方体再次反射,其倒影也带有颜色,光滑的球体的镜面反射又映射出房间的影子。对间接光照,需要其颜色,强度,方向等特性随着与不同的反射面交换持续的发生变化,营造出很高的真实感。下图是Cry Engine的RAY TRACING示例

良好的Ray Tracing在GI体系中扮演着关键角色,因为它实现之前有提到的众多的光学特性,One Solution For Many Effects !吃一片,顶多片。例如景深DOF,漫/镜面反射,环境光融入,软阴影,运动模糊等都可以通过RT来实现。

Soft Shadow

Reflection

DOF

Motion Blur

目前的工程做法是进行各种不同的蒙地卡罗积分,有的是从视点平面做积分,有的是从发光源做积分,有的积分域增加了时间维度,有的考虑更多的积分域,大家的共同挑战是计算量极大,在硬件上底层渲染流水线不支持这样的计算,导致很慢,都是离线计算完成。

在这个基础问题上Nvidia勇敢的迈出重要了一步,在硬件上重新设计计算内核,新的RTX显卡最重要的革命之一就是增加了专门RT内核(另外一个是AI加入专门针对Deep Learing的Tensor内核),从架构上打下了让光线追踪的实时的基础。

(真不是打广告,这的确对图形学是很基础很重要的进步)

硬件级别的改变,让Real Time Ray Tracing商业化推开,如战地5等游戏已经支持实时光线追踪

我们需要特别关注,因为2018年NV的CEO Jesen Huang已经在DEMO医疗CT Real Time Ray Tracing 的3D成像了

(如下右侧图像)

在三角形体系的Ray Casting比较普遍,体数据上完成Monte Carlo Ray Tracing并且同时处理漫反射和镜面反射有

一定的挑战,但目前已经越来越多,如下图(体渲染中光线追踪 并同时处理漫反射与镜面反射)

虽然光线追踪已经越来越普及,但不同于可以使用商用渲染引擎,医疗中的渲染还是需要专门设计编写程序(私人订制),

考虑医学图像本身的特点,所以还是有一定难度的。由于CT的数据场比超声数据场大不少,所以超声的实时光线追踪应该会比CT普及得更早

电影《星际穿越》中的 卡冈图雅 黑洞渲染,为了符合物理规律(因为一般光线追踪假设光沿直线传播,但由于黑洞

实际上会扭曲时空,光路也会扭曲),重新设计编写了新的光线追踪渲染,所以难度与成本陡然提升;

PS:为了视觉效果,有些基础规则做了修改,仍不如1979年的模拟准确,人类目前最真实的基准还是EHT(事件视界望远镜)产生的图像;

(左:星际穿越渲染的黑洞,中:1979年按天文学家给定的规则渲染的黑洞,右:2019年4月EHT发布的首张黑洞照片)

对比之下,商用医疗3D的渲染进步的空间还很大。

Others

我们已经谈了很多图形学上技术,只是抛砖引玉,有很多没有展开: 如HDR, 光的衍射,运动拖影处理,折射(色散),菲尼尔,BDRF, Phase Function, Deferred Render(延迟渲染), 三角形体素化,体数据三角形化,物理引擎计算... ...等等。要接近真实,图形学依旧任重而道远。


3. 图形学的未来发展

最开始我们有提到,3D图形学的两个基本常态:

1. 理论等待工程(软件&硬件)发展

2. 效率是关键

快,更快一直是不变的主题。

硬件上

硬件层面上无止境的提升不会停下,更重要的是架构级,底层级的变动,RT内核的加入是一个勇敢的尝试,市场会用脚投票告诉我们去往何方。但任何让硬件更快的努力,都是潜在的方向。

软件上

更快依然是主题,接管底层驱动级的控制是重大且艰难的一步,DXR对光线追踪的支持,DX12Vulkan代表的方向是重大的进步。但从上层算法到中层框架设计,再到底层驱动级控制 对图形学工程师提出了全栈能力的要求。

工程师自己

图形学的发展要靠 算法硬件软件的提升, 工程师能力的提升也很重要。有不少朋友总把GPU/GPGPU当万能解药,我做了对比实验,以CUDA的SDK自带的 DEMO中BOX Filter例子做比对基准,我自己写了个BOX Filter 的程序,同样的图像,运行在同样硬件上,同样滤波器尺寸,效率对比如下图(左:CUDA SDK自带的BOX Filter FPS 500+,右: 我自己在GL上的BOX Filter FPS 3500+)

这个例子非常特殊,未必都能产生这么巨大的差距;

我想表达的是,像我这样的业余3D爱好者都有可能做出这样的差别;这么多聪明的专业的3D工程师,如果深入专研,对效率上造成的改变将会是无法忽视的;提升工程师自身的能力,也是非常核心的因素;

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值