Merge remote-tracking branch 'origin/master'

# Conflicts:
#	.obsidian/plugins/various-complements/histories.json
#	03-UnrealEngine/卡通渲染相关资料/渲染功能/阴影控制/ToonShadow.md
This commit is contained in:
BlueRose 2024-12-17 11:05:29 +08:00
commit f4440d36e5
2 changed files with 34 additions and 82 deletions

View File

@ -1 +1 @@
{"SequoiaCamShotEvalTemplate":{"SequoiaCamShotEvalTemplate":{"currentFile":{"count":1,"lastUpdated":1732609264076}}},"c++内存泄漏分析工具":{"c++内存泄漏分析工具":{"internalLink":{"count":1,"lastUpdated":1733137754779}}},"Lights":{"Lights":{"currentFile":{"count":1,"lastUpdated":1733637911876}}},"FShadowProjectionNoTransformVSShadowProjectionNoTransformVS、FShadowVolumeBoundProjectionVSShadowVolumeBoundProjectionVS":{"FShadowProjectionNoTransformVSShadowProjectionNoTransformVS、FShadowVolumeBoundProjectionVSShadowVolumeBoundProjectionVS":{"currentFile":{"count":1,"lastUpdated":1734345863513}}}}
{"SequoiaCamShotEvalTemplate":{"SequoiaCamShotEvalTemplate":{"currentFile":{"count":1,"lastUpdated":1732609264076}}},"c++内存泄漏分析工具":{"c++内存泄漏分析工具":{"internalLink":{"count":1,"lastUpdated":1733137754779}}},"Lights":{"Lights":{"currentFile":{"count":1,"lastUpdated":1733637911876}}},"渲染屏幕空间阴影遮罩,并用于光照计算。":{"渲染屏幕空间阴影遮罩,并用于光照计算。":{"currentFile":{"count":1,"lastUpdated":1734354537396}}}}

View File

@ -210,13 +210,17 @@ void FSceneRenderer::InitDynamicShadows(FRHICommandListImmediate& RHICmdList, FG
1. UnbatchedLights
1. ShadowProjectionOnOpaque
# ShadowDepths
渲染阴影深度贴图与图集。
- FSceneRenderer::RenderShadowDepthMaps()位于CustomDepth之前。
- **RenderVirtualShadowMaps()**
- RenderShadowDepthMapAtlases()
- RenderVirtualShadowMaps()
- ***RenderShadowDepthMapAtlases()***
- SortedShadowsForShadowDepthPass.ShadowMapCubemaps循环。渲染点光源阴影立方体图
- **FProjectedShadowInfo::RenderDepth()**
- **FProjectedShadowInfo::RenderTranslucencyDepths**
RenderShadowDepthMapAtlases() 渲染的图集位于***FSceneRenderer::SortedShadowsForShadowDepthPass.ShadowMapAtlases*** (ShadowMapAtlases.RenderTargets.DepthTarget为深度ShadowMapAtlases.Shadows 为FProjectedShadowInfo)
## RenderDepth
MeshDrawProcessor为***FShadowDepthPassMeshProcessor***。渲染的Shader为***ShadowDepthPixelShader.usf***
```c++
@ -753,84 +757,10 @@ void Main(
#endif
}
```
# Lights
### Shader
ShadowProjectionPixelShader.usf
- TShadowProjectionPS
- TDirectionalPercentageCloserShadowProjectionPS方向光投影
- TSpotPercentageCloserShadowProjectionPSSpotLight
- FOnePassPointShadowProjectionPS(Moible?)
### 相关函数
- FDeferredShadingSceneRenderer::RenderLights()
- FDeferredShadingSceneRenderer::RenderDeferredShadowProjections()
- FSceneRenderer::RenderShadowProjections()
- FProjectedShadowInfo::SetupFrustumForProjection()构建阴影投影4棱椎平面信息。
- FProjectedShadowInfo::SetupProjectionStencilMask()
## 其他
顺序:
RenderCustomDepthPass
FSceneRenderer::CreateDynamicShadows
=>
FSceneRenderer::CreatePerObjectProjectedShadow
```c++
if (!IsForwardShadingEnabled(ShaderPlatform))
{
// Dynamic shadows are synced later when using the deferred path to make more headroom for tasks.
FinishInitDynamicShadows(GraphBuilder, InitViewTaskDatas.DynamicShadows, InstanceCullingManager, ExternalAccessQueue);
}
```
```c++
if (RendererOutput == ERendererOutput::DepthPrepassOnly)
{
RenderOcclusionLambda();
if (bUpdateNaniteStreaming)
{
Nanite::GStreamingManager.SubmitFrameStreamingRequests(GraphBuilder);
}
CopySceneCaptureComponentToTarget(GraphBuilder, SceneTextures, ViewFamilyTexture, ViewFamily, Views);
}
else
{
GVRSImageManager.PrepareImageBasedVRS(GraphBuilder, ViewFamily, SceneTextures);
if (!IsForwardShadingEnabled(ShaderPlatform))
{
// Dynamic shadows are synced later when using the deferred path to make more headroom for tasks.
FinishInitDynamicShadows(GraphBuilder, InitViewTaskDatas.DynamicShadows, InstanceCullingManager, ExternalAccessQueue);
}
// Update groom only visible in shadow
if (IsHairStrandsEnabled(EHairStrandsShaderType::All, Scene->GetShaderPlatform()) && RendererOutput == ERendererOutput::FinalSceneColor)
{
UpdateHairStrandsBookmarkParameters(Scene, Views, HairStrandsBookmarkParameters);
// Interpolation for cards/meshes only visible in shadow needs to happen after the shadow jobs are completed
const bool bRunHairStrands = HairStrandsBookmarkParameters.HasInstances() && (Views.Num() > 0);
if (bRunHairStrands)
{
RunHairStrandsBookmark(GraphBuilder, EHairStrandsBookmark::ProcessCardsAndMeshesInterpolation_ShadowView, HairStrandsBookmarkParameters);
}
}
// NOTE: The ordering of the lights is used to select sub-sets for different purposes, e.g., those that support clustered deferred.
FSortedLightSetSceneInfo& SortedLightSet = *GraphBuilder.AllocObject<FSortedLightSetSceneInfo>();
{
RDG_CSV_STAT_EXCLUSIVE_SCOPE(GraphBuilder, SortLights);
RDG_GPU_STAT_SCOPE(GraphBuilder, SortLights);
ComputeLightGridOutput = GatherLightsAndComputeLightGrid(GraphBuilder, bComputeLightGrid, SortedLightSet);
}
```
# RenderLights
渲染ScreenShadowMask并用于光照计算。
FDeferredShadingSceneRenderer::RenderLights()
=>
RDG_EVENT_SCOPE(GraphBuilder, "UnbatchedLights");//batchedLights为没有LightFunction与没有阴影的灯光。
@ -901,10 +831,14 @@ void FDeferredShadingSceneRenderer::RenderDeferredShadowProjections(
RenderShadowProjections():
1. 取得当前FVisibleLightInfo、FLightSceneProxy创建FProjectedShadowInfoArray DistanceFieldShadows、NormalShadows。
2. 遍历VisibleLightInfo.ShadowsToProject按照阴影特征将每个FProjectedShadowInfo加入DistanceFieldShadows、NormalShadows。
3. 调用Lambda RenderNormalShadows()来渲染ScreenShadowMaskTexture与ScreenShadowMaskSubPixelTexture。
3. 调用Lamda来渲染ScreenShadowMaskTexture与ScreenShadowMaskSubPixelTexture。
4. 遍历DistanceFieldShadows调用FProjectedShadowInfo->RenderRayTracedDistanceFieldProjection()来渲染距离场阴影。
### FSceneRenderer::RenderShadowProjections()
1. 初始化UniformStruct变量。
2. 遍历传入的FProjectedShadowInfo数组并调用**ProjectedShadowInfo->RenderProjection()** 将所有灯光的阴影Mask绘制到一张ScreenShadowMask上。
1. 在TShadowProjectionPS中通过SetParameters() => ProjectionParameters.Set()来设置ShadowDepthTextureValue。`ShadowDepthTextureValue = ShadowInfo->RenderTargets.DepthTarget->GetRHI();`
```c++
void FSceneRenderer::RenderShadowProjections(
FRDGBuilder& GraphBuilder,
@ -986,8 +920,24 @@ void FSceneRenderer::RenderShadowProjections(
- TShadowProjectionFromTranslucencyPS
- TDirectionalPercentageCloserShadowProjectionPS
- TModulatedShadowProjection
- ShadowProjectionCommon.ush
- ShadowDepthTexture
- ShadowDepthCubeTexture
主要步骤:
1. 将SceneDepthScreenSpace =>ShadowSpace
2. 根据过滤方式调用:
1. 不过滤:`Shadow = LightSpacePixelDepthForOpaque < Texture2DSampleLevel(ShadowDepthTexture, ShadowDepthTextureSampler, ShadowPosition.xy, 0).r;`
2. PCSS初始化FPCSSSamplerSettings之后调用DirectionalPCSS()
3. PCF初始化FPCFSamplerSettings之后调用ManualPCF()
3. 调整阴影数值。钳制、模糊、过滤。
4. `OutColor = EncodeLightAttenuation(half4(FadedShadow, FadedSSSShadow, FadedShadow, FadedSSSShadow));`LinearSpace => sRGB 本质为sqrt(input)比pow(x, 1/2.2) 节约性能。
## 总结
1. RenderDepth()渲染完深度贴图之后经过GatherAndSortLights()、ComputeLightGrid()获取到经过剪裁的FSortedLightSetSceneInfo &SortedLightSet之后传递给RenderLights()。
2. BindShadowProjectionShaders() => BindShaderShaders() =>
3. TShadowProjectionPS => ProjectionParameters.Bind(Initializer); => ShadowDepthTexture.Bind(ParameterMap,TEXT("ShadowDepthTexture"));
PS. 向往Blog 以上可知对ScreenShadowMaskTexture执行绘制时是在屏幕空间进行的并且ScreenShadowMask会被叠加多次视光源的阴影实例个数而定不同的通道存储了不同类型的阴影信息。
## RenderLight()
```c++
@ -1060,9 +1010,11 @@ PS.很有可能需要创建2个Atlas。Atlas的创建位于***FSceneRenderer::Al
//此阶段需要屏蔽角色投射到自己的非半程阴影
//和角色投射到场景中会跟随视角移动的阴影
```c++
if(Toon材质,且没有程阴影Flag的阴影
if(Toon材质,且没有程阴影Flag的阴影
&&非Toon材质但有半程阴影Flag的阴影)
{
屏蔽此阴影
}
```
PS.很有可能在FProjectedShadowInfo::RenderProjection()阶段进行判断以此保证合成正确的**ScreenShadowMask**。