UE4 Engine Fix-Movable的 SkyLight 导致 SSS 过度曝光的问题

目录:第九艺术-目录

目录

起因问题

Stationary 的SkyLight

Movable 的SkyLight


起因问题

起因问题是 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

  1. LightAccumulator_Add(LightAccumulator, Color + DiffuseColor, DiffuseColor, 1.0f, UseSubsurfaceProfile(GBuffer.ShadingModelID)); 累加计算亮度值
  2. 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 里面计算亮度的后面就好了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值