70 lines
2.3 KiB
Markdown
70 lines
2.3 KiB
Markdown
---
|
||
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);
|
||
}
|
||
```
|
||
|