即:Color = 0 * srcColor destAlpha * destColor
经此一步之后,不管是移动端还是非移动端,其生成的Cubemap中被判为天空的部分已经全部为0,所以在反射球为移动端存储编码为RGBM时,早已没有了这部分颜色信息……
上文说到使用同一张Cubemap作为Skylight和Reflection Capture输入时,得到的结果亮度不一致,于是乎TA提了一个BUG单。
没过多久,场景美术发现无论是接受CSM实时阴影或是烘焙的ShadowMask,金属物体上的阴影总是比非金属上的阴影来得更黑一些,于是乎场景美术不光提了一个BUG单,还抱怨说UE4怎么这么多乱七八糟的问题,比隔壁另一个U字头的引擎还不如?
Skylight和Reflection Capture亮度不一样的问题,是因为Skylight的cubemap在渲染时直接使用的是cubemap的原始亮度,而Reflection Capture在渲染时亮度经过了缩放(大部分时候,这个缩放值都是小数,也就是说:它都会变暗)。具体的实现在MobileBasePassPixelShader.usf的GetImageBasedReflectionLighting函数中。
可以看到在Reflection Capture的情况下,SpecularIBL会乘以缩放值。这个值是通过MobileComputeMixingWeight函数计算出来的——如果你用的UE4版本在4.23之前,那么这个函数是不带Mobile的ComputeMixingWeight,Mobile版本只是简单的把ComputeMixingWeight的所有数据类型,由float改为了half*,算法完全一致。
接下来我们详细拆一拆MobileComputeMixingWeight的算法,先看看这函数的全貌(因为源代码中的注释有很强的误导性,所以注释去被我去掉了,同时我也简化了一下代码的布局)。
算法分为这几步:
1. 计算一个0~1之间的MIxingAlpha值。
这个值由ReflectionEnvironmentRoughnessMixingScaleBiasAndLargestWeight的x、y及当前像素的Roughness值来确定。Ref*Weight参数的计算过程。