

虚幻引擎有着一套复杂的灯光系统,我们常常会疑惑整个渲染框架下画面的一个像素的最终亮度到底怎么来的,下面我就带着这个疑问进行探索。

这是我们在UnrealEngine中的灯光面板,最基础的两个功能是Intensity和LightColor

UnrealEngine内部首先会把Intensity和LightColor在CPU阶段就合并,合并计算非常简单,直接相乘就好了,最后在Shader里使用的LightColor是经过Intensity缩放的。但是这个数据缩放并不是简单的Color * Intensity,因为我们还要注意它们的单位


我们可以注意到方向光的单位和点光源或者聚光灯的单位是不同的,方向光的单位是lux,聚光灯的单位是cd我们可以在UPointLightComponent::ComputeLightBrightness()中找到答案。

这个ComputeLightBrightness()是一个虚函数,不同的灯光有自己的计算版本。
我们可以在如下堆栈中找到计算过程





我们再来明确一下概念
流明:lm 描述光通量
坎德拉:cd = lm/sr (sr为球面度) 描述光强
勒克斯:lx = lm/m^2 描述照度
结合代码我们可以得出,在UE中是使用勒克斯(照度)在计算,且单位是平方米。所以聚光灯和点光源需要做一次转换,把坎德拉转换未勒克斯,而平行光一开始就是勒克斯,所以不需要转换单位。
最后在数据传入Shader计算的时候还会做一个矫正,不过这个GetLightExposureScale大部分情况下值都为1.0

完成了灯光的数据传入的研究以后,我们下一步就是要看这个灯光能量打到物体身上会做怎么样的处理,这部分就是Unreal的GPU上具体执行渲染的具体逻辑了。虚幻官方文档里给了一个具体的公式

一个物体渲染出来以后的亮度,跟灯光当然是直接相关的,灯光打到物体上以后,渲染到屏幕上形成的最后的值还需要跟曝光度进行一个相乘最后得到的才是该像素的最后亮度,然后再走一次Tonemapping得到我们最后的渲染结果。

Enjoy it.



2023/3/16
Auto Exposure (Eye Adaptation): https://link.zhihu.com/?target=https%3A//docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/PostProcessEffects/AutomaticExposure/
[2]能不能生动形象解说下坎德拉,流明,勒克斯之间的关系?: https://www.zhihu.com/question/50491794
鸣谢:感谢作者的授权转载,欢迎大家投稿,一起分享交流游戏开发技术。
作者:YivanLee
原文:https://zhuanlan.zhihu.com/p/614439083
关注【游戏开发技术教程】
游戏开发技术、技巧、教程和资源,答疑解惑,内推面试
