--- title: 未命名 date: 2025-03-27 17:37:02 excerpt: tags: rating: ⭐ --- # Toon Lumen 抹平法线思路: 在`LumenScreenProbeGather.usf`中对法线进行抹平处理。其Pass位于 - DiffuseIndirectAndAO - LumenScreenProbeGather - Integrate - SimpleDiffuse/SupportImportanceSampleBRDF?/SupportAll? 在如下位置添加代码: ```c++ if (IsValid(Material)) { const float2 ScreenUV = (Coord.SvPosition + 0.5f) * View.BufferSizeAndInvSize.zw; const float3 WorldPosition = GetWorldPositionFromScreenUV(ScreenUV, Material.SceneDepth); const float3 WorldNormal = Material.WorldNormal; //BlueRose Modify if (Material.ShadingID == SHADINGMODELID_TOONSTANDARD) { //使用Yu-ki016的方法“抹平法线” float3 V = normalize(LWCHackToFloat(PrimaryView.WorldCameraOrigin) - WorldPosition); const uint ToonDataAssetID = GetToonDataAssetIDFromGBuffer(Material.GBufferData); float DiffuseIndirectLightingFlatten = GetDiffuseIndirectLightingFlatten(ToonDataAssetID); Material.WorldNormal = normalize(lerp(WorldNormal, V, DiffuseIndirectLightingFlatten)); } //BlueRose Modify End ... } } ``` 该方法存在一些问题:**当相机围绕角色旋转时,角色身上的 GI变化会比较明显**。 # Spherical Harmonics UE5中采样球谐贴图方法(ReflectionEnvironmentShared.ush): ```c++ /** * Computes sky diffuse lighting from the SH irradiance map. * This has the SH basis evaluation and diffuse convolution weights combined for minimal ALU's - see "Stupid Spherical Harmonics (SH) Tricks" */ float3 GetSkySHDiffuse(float3 Normal) { float4 NormalVector = float4(Normal, 1.0f); float3 Intermediate0, Intermediate1, Intermediate2; Intermediate0.x = dot(SkyIrradianceEnvironmentMap[0], NormalVector); Intermediate0.y = dot(SkyIrradianceEnvironmentMap[1], NormalVector); Intermediate0.z = dot(SkyIrradianceEnvironmentMap[2], NormalVector); float4 vB = NormalVector.xyzz * NormalVector.yzzx; Intermediate1.x = dot(SkyIrradianceEnvironmentMap[3], vB); Intermediate1.y = dot(SkyIrradianceEnvironmentMap[4], vB); Intermediate1.z = dot(SkyIrradianceEnvironmentMap[5], vB); float vC = NormalVector.x * NormalVector.x - NormalVector.y * NormalVector.y; Intermediate2 = SkyIrradianceEnvironmentMap[6].xyz * vC; // max to not get negative colors return max(0, Intermediate0 + Intermediate1 + Intermediate2); } ```