Unreal-Unreal是如何渲染一帧画面的(2)
全球图形学领域教育的领先者、自研引擎的倡导者、底层技术研究领域的技术公开者,东汉书院在致力于使得更多人群具备内核级竞争力的道路上,将带给小伙伴们更多的公开技术教学和视频,感谢一路以来有你的支持。我们正在用实际行动来帮助小伙伴们构建一套成体系的图形学知识架构,你在我们这里获得的不止于那些毫无意义的代码,我们这里更多的是代码背后的故事,以及精准、透彻的理解。我们不会扔给人们一本书或者给个思路让人们去自学,我们是亲自来设计出好的课程,让人们明白到底背后还有哪些细节。这里插播一个引擎大赛的消息,感兴趣的同学可以看一眼,这也是东汉书院的立项使命:
原文参考链接
这是第二篇关于分析Unreal如何渲染一帧画面的文章,前一篇请看这里
We continue the exploration of how Unreal renders a frame by looking into light grid generation, g-prepass and lighting.
我们继续通过研究那些光照贴图里的小格子里的玩意是咋生成的、G-Prepass以及光照的情况来探索Unreal如何渲染一帧画面的。
Light assignment
Next, the renderer switches to a compute shader to assign lights to a 3D grid (ComputeLightGrid pass), in a way similar to clustered shading. This light grid can be used to quickly retrieve the lights that affect a surface based on its position.
接下来,渲染器会切换到compute shader去为3D的格子赋予灯光,这个方法跟clusered shading的方式比较相似。这个光照的格子可以被用来快速的去查询在某个位置上的某个面都有哪些光可以影响到它的成像。
As the pass name indicates, the view space light grid is of dimensions 29x16x32. Unreal uses a screen space tile of 64×64 pixels and 32 z-partitions. This means that the actual number of X-Y dimensions of the light grid will depend on the screen resolution. Also according to the name we are assigning 9 lights and 2 reflection probes. A reflection probe is an “entity” with position and radius which captures the environment around it and it is used for reflections on props.
如同这个pass的名字所预示的那样,视口空间下的光照格子的尺寸是29x16x32。Unreal在屏幕空间使用的分块大小是64x64像素大小的并且在z方向上剖分成了32份。这就是说,在x-y平面上光照格子的数量最终是由屏幕的分辨率所决定的。同样的,根据这个名字可以看出,我们赋值了9个灯光和2和反射的probes。一个反射的probe就是指一个有着位置和半径的entity,它会捕获它周围的环境,它是用来计算物体的反射的。
According to the compute shader source (LightGridInjection.usf), the partitioning is exponential, meaning that the z-dimension of each grid cell in view space becomes larger with distance. Also it uses he axis aligned box of each cell to perform light bounding volume intersections. To store the light indices, a linked list is used which is then converted to a contiguous array during the “Compact” pass.
通过compute shader的源码的分析性可以知道,这个分割算法是按指数增长的,也就是说在z方向,视口空间下的这些各自会随着距离的增大的增大。同时,这些用来描述灯光的包围盒的格子还是轴对齐的,后续它们会参与相交检测。Unreal里使用一个链表去存储灯光的索引,这个链表会在后面的Compact阶段转换成为相邻的数组。
This Light grid will later be used during the Volumetric Fog pass to add light scattering to the fog, the environment reflections pass and the translucency rendering pass.
在后续的Volumetric Fog阶段,这些光照的格子会被用来给雾增加散射效果,在环境反射的阶段和半透明渲染的阶段也会用到。
Another interesting thing I noticed is that the CullLights pass begins by clearing the Unordered Access Views for light data, but it uses ClearUnorderedAccessViewUint only for the 2 of the 3 UAVs. For the other one it uses a compute shader that sets the value manually (the first Dispatch in the above list). Apparently the source code, for buffer sizes above 1024 bytes, favours clearing with a compute shader instead of a “clear” API call.
另一个有趣的事情是,我注意到CullLights阶段开始的时候会清理那些光照数据的Unordered Access View,但是它仅仅对3和UAV里面的2个使用了ClearUnorderedAccessViewUnit。对于另一个UAV,它使用了compute shader去对里面的值进行了手动的设置。显然,根据它的源码来看,当缓冲区的大小大于1024字节的时候,会更倾向于使用compute shader去擦除而不是使用相关的“clear”API去擦除缓冲区。
未完待续......
我们核心关注和讨论的领域是引擎的底层技术以及商业化方面的信息,可能并不适合初级入门的同学。官方相关信息主要包括了对市面上的引擎的各种视角的分析以及宏观方面的技术讨论,相关领域感兴趣的同学可以关注东汉书院以及图形之心公众号。
只言片语,无法描绘出整套图形学领域的方方面面,只有成体系的知识结构,才能够充分理解和掌握一门科学,这是艺术。我们已经为你准备好各式各样的内容了,东汉书院,等你来玩。
页:
[1]