2023-06-29 11:55:02 +08:00
BasePassPixelShader.usf中的FPixelShaderInOut_MainPS(), 为BasePass阶段Shader的主要逻辑。会被PixelShaderOutputCommon.usf的MainPS(),即PixelShader入口函数中被调用。
该阶段会取得材质编辑器各个引脚的计算结果, 在一些计算下最终输出GBuffer, 以备后续光照计算。可以认为是“紧接”材质编辑器的下一步工作。相关的c++逻辑位于FDeferredShadingSceneRenderer::Render()的RenderBasePass()中。
但因为个人能力与时间所限,只能写一篇杂乱笔记作为记录,以供后续使用。
<!-- more -->
### 780~889: 计算变量并且填充FMaterialPixelParameters MaterialParameters。BaseColor、Metallic、Specular就位于867~877。
### 915~1072: 计算GBuffer或者DBuffer
- 915~942:计算贴花相关的DBuffer
- 954~1028: 按照ShaderModel来填充GBuffer。( 983~1008 Velocity、1013~1022 使用法线来调整粗糙度, 在皮肤以及车漆ShaderModel中有用到)
- 1041: GBuffer.DiffuseColor = BaseColor - BaseColor * Metallic;
- 1059~1072: 使用法线( 清漆ShaderModel还会计算的底层法线) 计算BentNormal以及GBufferAO。( 使用SphericalGaussian)
### 1081~1146:
#### 1086~1116: 计算DiffuseColorForIndirect
DiffuseColorForIndirect( DiffuseDir只在Hair中计算)
- 次表面与皮肤: DiffuseColorForIndirect += SubsurfaceColor;
- 布料: DiffuseColorForIndirect += SubsurfaceColor * saturate(GetMaterialCustomData0(MaterialParameters));
- 头发: DiffuseColorForIndirect = 2*PI * HairShading( GBuffer, L, V, N, 1, TransmittanceData, 0, 0.2, uint2(0,0);
#### 1118~1120: 计算预间接光照结果
GetPrecomputedIndirectLightingAndSkyLight:
采样对应的预结算缓存:
1. PRECOMPUTED_IRRADIANCE_VOLUME_LIGHTING: 根据TRANSLUCENCY_LIGHTING_VOLUMETRIC_PERVERTEX_NONDIRECTIONAL来判断是进行读取顶点AO值还是采样体积关照贴图来作为IrradianceSH的值。最后累加到OutDiffuseLighting上。
2. CACHED_VOLUME_INDIRECT_LIGHTING: 采样IndirectLightingCache, 最后累加到最后累加到OutDiffuseLighting上。
3. 采样HQ_TEXTURE_LIGHTMAP或者LQ_TEXTURE_LIGHTMAP, 最后累加到OutDiffuseLighting上。
调用GetSkyLighting()取得天光值并累加到OutDiffuseLighting上。最后计算OutDiffuseLighting的亮度值最后作为OutIndirectIrradiance输出。
#### 1138: 计算DiffuseColor
DiffuseColor=Diffuse间接照明 * Diffse颜色 + 次表面间接光照 * 次表面颜色+AO
```c#
DiffuseColor += (DiffuseIndirectLighting * DiffuseColorForIndirect + SubsurfaceIndirectLighting * SubsurfaceColor) * AOMultiBounce( GBuffer.BaseColor, DiffOcclusion );
```
#### 1140~1146: SingleLayerWater 覆盖颜色操作
```c#
GBuffer.DiffuseColor *= BaseMaterialCoverageOverWater;
DiffuseColor *= BaseMaterialCoverageOverWater;
```
### 1148~1211
1. 使用ForwardDirectLighting的DiffuseLighting与SpecularLighting累加, Color, THIN_TRANSLUCENT Model则为 DiffuseColor与ColorSeparateSpecular。
2. SIMPLE_FORWARD_DIRECTIONAL_LIGHT: 调用GetSimpleForwardLightingDirectionalLight()计算方向光结果。
根据光照模式累加, 最后累加到Color上:
```c#
#if STATICLIGHTING_SIGNEDDISTANCEFIELD
DirectionalLighting *= GBuffer.PrecomputedShadowFactors.x;
#elif PRECOMPUTED_IRRADIANCE_VOLUME_LIGHTING
DirectionalLighting *= GetVolumetricLightmapDirectionalLightShadowing(VolumetricLightmapBrickTextureUVs);
#elif CACHED_POINT_INDIRECT_LIGHTING
DirectionalLighting *= IndirectLightingCache.DirectionalLightShadowing;
#endif
Color += DirectionalLighting;
```
```c#
float3 GetSimpleForwardLightingDirectionalLight(FGBufferData GBuffer, float3 DiffuseColor, float3 SpecularColor, float Roughness, float3 WorldNormal, float3 CameraVector)
{
float3 V = -CameraVector;
float3 N = WorldNormal;
float3 L = ResolvedView.DirectionalLightDirection;
float NoL = saturate( dot( N, L ) );
float3 LightColor = ResolvedView.DirectionalLightColor.rgb * PI;
FShadowTerms Shadow = { 1, 1, 1, InitHairTransmittanceData() };
FDirectLighting Lighting = EvaluateBxDF( GBuffer, N, V, L, NoL, Shadow );
// Not computing specular, material was forced fully rough
return LightColor * (Lighting.Diffuse + Lighting.Transmission);
}
```
### 1213~1273: 渲染雾效果
包括VertexFog、PixelFog、体积雾, 以及体积光效果( lit translucency)
体积雾只要使用View.VolumetricFogGridZParams中的值计算UV, 调用Texture3DSampleLevel采样FogStruct.IntegratedLightScattering, 最后的值为float4(VolumetricFogLookup.rgb + GlobalFog.rgb * VolumetricFogLookup.a, VolumetricFogLookup.a * GlobalFog.a);。
### 1283~1310: 取得材质中自发光值得计算结果并且累加到Color上
```c#
half3 Emissive = GetMaterialEmissive(PixelMaterialInputs);
#if !POST_PROCESS_SUBSURFACE && !MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
// For skin we need to keep them separate. We also keep them separate for thin translucent.
// Otherwise just add them together.
Color += DiffuseColor;
#endif
#if !MATERIAL_SHADINGMODEL_THIN_TRANSLUCENT
Color += Emissive;
```
### 1312~1349: SingleLayerWater光照计算
计算SunIlluminance、WaterDiffuseIndirectIlluminance、Normal、ViewVector、EnvBrdf( 预积分G F * 高光颜色, 位于BRDF.ush) 后根据设置采用对应的方式(前向渲染与延迟渲染方式)
```c#
const float3 SunIlluminance = ResolvedView.DirectionalLightColor.rgb * PI; // times PI because it is divided by PI on CPU (=luminance) and we want illuminance here.
const float3 WaterDiffuseIndirectIlluminance = DiffuseIndirectLighting * PI;// DiffuseIndirectLighting is luminance. So we need to multiply by PI to get illuminance.
```
### 1352~1372: 超薄透明物体光照计算
### 1375~1529: GBuffer相关
1. BlendMode处理
2. GBuffer.IndirectIrradiance = IndirectIrradiance;
3. 调用LightAccumulator_Add()累加关照对BaseColor的影响。Out.MRT[0]=FLightAccumulator.TotalLight
4. 调用EncodeGBuffer(),填充GBuffer12345数据。
5. Out.MRT[4] = OutVelocity;
6. Out.MRT[GBUFFER_HAS_VELOCITY ? 5 : 4] = OutGBufferD;
7. Out.MRT[GBUFFER_HAS_VELOCITY ? 6 : 5] = OutGBufferE;
8. Out.MRT[0].rgb *= ViewPreExposure;
### 1553: FinalizeVirtualTextureFeedback
2024-02-28 17:33:14 +08:00
# UE5
## Lumen相关
- GetSkyLighting()
- Lumen
- GetTranslucencyGIVolumeLighting()
- SkyLighting
- GetEffectiveSkySHDiffuse()
- GetVolumetricLightmapSkyBentNormal()
- GetSkyBentNormalAndOcclusion()
**GetSkyLighting()** 演示了采样SkyLight与Lumen的方法。
### SkyLighting
GetEffectiveSkySHDiffuse()是一个宏, 会根据平台指向下面2个函数:
```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);
}
/**
* 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"
* Only does the first 3 components for speed.
*/
float3 GetSkySHDiffuseSimple(float3 Normal)
{
float4 NormalVector = float4(Normal, 1);
float3 Intermediate0;
Intermediate0.x = dot(SkyIrradianceEnvironmentMap[0], NormalVector);
Intermediate0.y = dot(SkyIrradianceEnvironmentMap[1], NormalVector);
Intermediate0.z = dot(SkyIrradianceEnvironmentMap[2], NormalVector);
// max to not get negative colors
return max(0, Intermediate0);
}
```