目录:第九艺术-目录
目录
起因问题
起因问题是 Movable SkyLight 的情况下,Character会整体泛白,基本看不出来原本的颜色
而 Stationary 下 是正常的
UE4 是使用的 SSSS,可分离的次表面散射算法,具体是在 下图 SubsurfaceScattering 的 Pass
过程对比
Stationary 的SkyLight
计算SkyLight是在 BasePass里的 GetSkyLighting() 计算天空光,计算 Out.MRT[0].rgb
除了SkyVisibility,核心就这两句,OutDiffuseLighting 就是 rgb
// Compute the preconvolved incoming lighting with the bent normal direction
float3 DiffuseLookup = GetEffectiveSkySHDiffuse(SkyLightingNormal) * ResolvedView.SkyLightColor.rgb;
// Apply AO to the sky diffuse
OutDiffuseLighting += DiffuseLookup * (SkyVisibility * GeometryTerm);
然后 使用 次表面的话,累加 Color 和 DiffuseColor 计算亮度,=计算 Out.MRT[0].a
- LightAccumulator_Add(LightAccumulator, Color + DiffuseColor, DiffuseColor, 1.0f, UseSubsurfaceProfile(GBuffer.ShadingModelID)); 累加计算亮度值
- LightAccumulator_GetResult(LightAccumulator); 赋值给 Out.MRT[0].alpha值存储亮度,用于之后 在 需要的时候,通过这张RT上rgb的Color 和alpha 的亮度值 ReconstructLight
在basepass 的最后,还会调整一次预曝光,*= View.PreExposure,注意这里只调整了 xyz
#if !MATERIALBLENDING_MODULATE && USE_PREEXPOSURE
Out.MRT[0].xyz *= View.PreExposure;
#endif
Movable 的SkyLight
计算SkyLight是在 ReflectionEnvironmentAndSky 里的 SkyLightDiffuse()
除了SkyVisibility,还考虑了 AO,因为这个pass靠后,但核心还是那几句,Lighting 就是rgb
// Compute the preconvolved incoming lighting with the bent normal direction
float3 DiffuseLookup = GetSkySHDiffuse(SkyLightingNormal) * View.SkyLightColor.rgb;
// Apply AO to the sky diffuse and account for darkening due to the geometry term
// apply the Diffuse color to the lighting (including OcclusionTintAndMinOcclusion as it's considered another light, that fixes SubsurfaceProfile being too dark)
Lighting += ((ScalarFactors * DotProductFactor) * DiffuseLookup + (1 - SkyVisibility) * OcclusionTintAndMinOcclusion.xyz) * DiffuseColor;
Lighting += DiffuseIrradiance * GBuffer.DiffuseColor * (GBuffer.GBufferAO * AmbientOcclusion);
#if USE_PREEXPOSURE
Lighting *= View.PreExposure;
#endif
可以看到这里输出rgb之后,直接就在这里做了预曝光,
然后出来在 ReflectionEnvironmentSkyLighting 才做亮度计算,赋值alpha值
LightAccumulator_Add(LightAccumulator, SkyLighting, SkyLighting, 1.0f, bNeedsSeparateSubsurfaceLightAccumulation);
OutColor = LightAccumulator_GetResult(LightAccumulator);
所以这里的alpha亮度就和 basepass不一样了
而在使用的地方,也就是ReconstructLight的时候,会有如下计算
float DiffuseLuminance = CenterSample.a * View.PreExposure;
也就是之后 alpha通道会再乘PreExposure,所以动态天光下相当于alpha通道乘了两次,所以会偏白
解决方法也很简单,把 SkyLightDiffuse 里的计算预曝光的部分移到 ReflectionEnvironmentSkyLighting 里面计算亮度的后面就好了