图片渲染延迟_老陆(我自己)_向前渲染和延迟渲染的区别

22929d67841340d2eb34d2097bcc96cb.png

本来计划半小时从0到精通学一个shader的

但半小时真的够吗,

现在这个互联网时代,我结果用半小时做了:

1.学习向前渲染和延迟渲染

2.写这个文章

3.看一个游戏主城做的效果,并学习

Forward rendering

e39d7921960d4beac621369902b0e6dd.png


Forward rendering
这是最初始的渲染方式,原理是以mesh为单位进行渲染,在光栅化后,对每个PS进行计算时,根据光照进行着色计算,所以这种方式称为前向着色Forward Rendering 是绝大数引擎都含有的一种渲染方式。要使用 Forward Rendering,一般在 Vertex ShaderFragment Shader 阶段对每个顶点或每个像素进行光照计算,并且是对每个光源进行计算产生最终结果。下面是 Forward Rendering 的核心伪代码:

=====
For each light: For each object affected by the light: framebuffer += object * light

====
比如在 Unity3D 4.x 引擎中,对于下图中的圆圈(表示一个 Geometry),进行 Forward Rendering 处理:

9dcefd3f191b6a233b93cce57fb2ba18.png


Unity3D 4.x 圆圈
将得到下面的处理结果:

5becbadcda8bcff124befc53140741d9.png


Unity3D 4.x 圆圈 着色结果
也就是说,对于 ABCD 四个光源我们在 Fragment Shader 中我们对每个 pixel 处理光照, 对于 DEFG 光源我们在 Vertex Shader 中对每个 vertex 处理光照,而对于 GH 光源,我们采用球调和(SH)函数进行处理。
这种方式存在以下弊端:

  • 如果像素被其他像素遮蔽了,就浪费了宝贵的处理结果
  • 光源多起来后管理很麻烦,Shader也不好写。

因此,Deferred rendering就应运而生了。
(但其实乐乐姐说过,Deferred渲染反而是旧技术,移动互联网时代反而流行)

属于旧瓶装新酒

Deferred rendering

b7393579a0ec632ef25569260df33940.png

b7393579a0ec632ef25569260df33940.png


Deferred Rendering(延迟渲染)顾名思义,就是将光照处理这一步骤延迟一段时间再处理。
具体做法就是将光照放在已经将三维物体生成二维图片之后进行处理。也就是说将物空间的光照处理放到了像空间进行处理。要做到这一步,需要一个重要的辅助工具——G-Buffer。
G-Buffer 主要是用来存储每个像素对应的 Position,Normal,Diffuse Color 和其他 Material parameters。根据这些信息,我们就可以在像空间中对每个像素进行光照处理。
下面是 Deferred Rendering 的核心伪代码。

===================
For each object: Render to multiple targets For each light: Apply light as a 2D postprocess

========
这种渲染方式相比 Forward rendering 就是在渲染mesh时,并不进行光照计算,而是按照以下步骤进行:物空间的光照处理放到了像空间进行处理。要做到这一步,需要一个重要的辅助工具——G-Buffer
G-Buffer 主要是用来存储每个像素对应的 Position,Normal,Diffuse Color 和其他 Material parameters。根据这些信息,我们就可以在像空间中对每个像素进行光照处理。
下面是 Deferred Rendering 的核心伪代码。
For each object: Render to multiple targets For each light: Apply light as a 2D postprocess
这种渲染方式相比 Forward rendering 就是在渲染mesh时,并不进行光照计算,而是按照以下步骤进行:

  • 将深度、法线、Diffuse、Specular等材质属性分别输出到GBuffer里(其实就是几张RT
  • 然后GBuffer里的深度和法线信息,累加所有光照的强度到一张光照强度RT
  • 根据GBuffer里的Diffuse和Specular信息,以及光照强度RT,进行着色计算

名词解释
GBuffer:指Geometry Buffer,亦即“物体缓冲”。区别于普通的仅将颜色渲染到纹理中,G-Buffer指包含颜色、法线、世界空间坐标的缓冲区,亦即指包含颜色、法线、世界空间坐标的纹理。由于G-Buffer需要的向量长度超出通常纹理能包含的向量的长度,通常在游戏开发中,使用多渲染目标技术来生成G-Buffer,即在一次绘制中将颜色、法线、世界空间坐标分别渲染到三张浮点纹理中
下面简单举个例子:
首先我们用存储各种信息的纹理图。比如下面这张 Depth Buffer,主要是用来确定该像 素距离视点的远近的。

4437116a492a661cb7fc2b1e8b805926.png


Depth Buffer
根据反射光的密度/强度分度图来计算反射效果。

16f5888eb36b6155bc7e136d715c876c.png


Specular Intensity/Power
下图表示法向数据,这个很关键。进行光照计算最重要的一组数据。

5ef26a9d517ca984b745f6db260bc873.png


Normal Buffer
下图使用了 Diffuse Color Buffer。

eba250c0a2f0af918d0d36112e945892.png


Diffuse Color Buffer
这是使用 Deferred Rendering 最终的结果。

c969127e46a2dc9f08b8969a588cd2e0.png


Deferred Lighting ResultsDeferred rendering 的最大的优势就是将光源的数目和场景中物体的数目在复杂度层面上完全分开,也就是说场景中不管是一个三角形还是一百万个三角形,最后的复杂度不会随光源数目变化而产生巨大变化。从上面的伪代码可以看出 Deferred rendering 的复杂度为 O(scree

  • 由于硬件限制或者性能限制,GBuffer里保存的材质信息有限,对于特殊材质来说,例如人的皮肤、翡翠等,渲染结果很不好
  • 延迟计算光照会大幅增加纹理带宽和帧缓冲区带宽的开销
  • 当光源数量很多时,光源会不断对光照强度RT进行累加,也会大幅增加帧缓冲区带宽开销
  • 由于硬件限制或者性能限制,不能使用硬件支持的MSAA,只能使用类似后期处理的FXAA或者Temporal AA

名词解释
MSAA、FXAA、Temporal AA都是抗锯齿(Anti-Aliasing)技术,锯齿的来源是因为场景的定义在三维空间中是连续的,而最终显示的像素则是一个离散的二维数组。所以判断一个点到底没有被某个像素覆盖的时候单纯是一个“有”或者“没有"问题,丢失了连续性的信息,导致锯齿。
具体区别可见FXAA、FSAA与MSAA有什么区别?

总结:

无论向前还是延迟渲染,这2者都有优点,和局限性,半个小时学不完,学了也做不到,后面优化的时候再详细说

最终的效果是这个:

487661b62fb30978c586578e59893842.png

需要知识点:

场景的深度图

模型+场面

水面反光

(基于webgl,一开始我也没想过,有点没学会走路就被逼搭飞机和建造飞机内味,但应该只关注每一个实现原理,unity shader都能用)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值