BlueRoseNote/03-UnrealEngine/Rendering/RenderingPipeline/Yivanlee 添加Pass与GBuffer笔记.md
2023-06-29 11:55:02 +08:00

314 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Yivanlee 添加Pass与GBuffer笔记
### 给BaseScalability.ini 添加渲染质量命令行
```ini
[EffectsQuality@0]
[EffectsQuality@1]
r.ToonDataMaterials=0
[EffectsQuality@2]
[EffectsQuality@3]
[EffectsQuality@Cine]
r.ToonDataMaterials=1
```
### 增加bUsesToonData选项
1. MaterialRelevance.h的FMaterialRelevance
2. HLSLMaterialTranslator.h与HLSLMaterialTranslator.cpp的FHLSLMaterialTranslator类
3. MaterialInterface.cpp的UMaterialInterface::GetRelevance_Internal
4. PrimitiveSceneInfo.cpp的FBatchingSPDI.DrawMesh()
5. SceneCore.h的FStaticMeshBatchRelevance类
### 定义Stat宏
RenderCore.cpp与RenderCore.h里定义ToonDataPass渲染Stat。
```c#
//h
DECLARE_CYCLE_STAT_EXTERN(TEXT("ToonData pass drawing"), STAT_ToonDataPassDrawTime, STATGROUP_SceneRendering, RENDERCORE_API);
//cpp
DEFINE_STAT(STAT_ToonDataPassDrawTime);
```
BasePassRendering.cpp里定义渲染状态宏。
```c#
DECLARE_CYCLE_STAT(TEXT("ToonDataPass"), STAT_CLM_ToonDataPass, STATGROUP_CommandListMarkers);
DECLARE_CYCLE_STAT(TEXT("AfterToonDataPass"), STAT_CLM_AfterToonDataPass, STATGROUP_CommandListMarkers);
```
### 添加渲染用的RT
SceneRenderTargets.h与SceneRenderTargets.cpp
```c++
//h
TRefCountPtr<IPooledRenderTarget> ToonBufferA;
//cpp
FSceneRenderTargets::FSceneRenderTargets(const FViewInfo& View, const FSceneRenderTargets& SnapshotSource)
: LightAccumulation(GRenderTargetPool.MakeSnapshot(SnapshotSource.LightAccumulation))
···
, ToonBufferA(GRenderTargetPool.MakeSnapshot(SnapshotSource.ToonBufferA))
```
修改SetupSceneTextureUniformParameters(),在GBuffer代码段中增加`SceneTextureParameters.ToonBufferATexture = bCanReadGBufferUniforms && EnumHasAnyFlags(SetupMode, ESceneTextureSetupMode::GBufferF) && SceneContext.ToonBufferA ? GetRDG(SceneContext.ToonBufferA) : BlackDefault2D;`
在SceneTextureParameters.h与SceneTextureParameters.cpp中将新增加的RT添加到FSceneTextureParameters中并且在GetSceneTextureParameters中注册RT,并在另一个同名函数中添加`Parameters.ToonBufferATexture = (*SceneTextureUniformBuffer)->ToonBufferATexture;`。
在FSceneTextureUniformParameters中添加`SHADER_PARAMETER_RDG_TEXTURE(Texture2D, ToonBufferATexture)`
### 添加SceneVisibility中的ToonDataPass定义
在SceneVisibility.h中的MarkRelevant()添加
```c#
if (StaticMeshRelevance.bUseToonData)
{
DrawCommandPacket.AddCommandsForMesh(PrimitiveIndex, PrimitiveSceneInfo, StaticMeshRelevance, StaticMesh, Scene, bCanCache, EMeshPass::ToonDataPass);
}
```
在ComputeDynamicMeshRelevance()中添加
```c#
if (ViewRelevance.bUsesToonData)
{
PassMask.Set(EMeshPass::ToonDataPass);
View.NumVisibleDynamicMeshElements[EMeshPass::ToonDataPass] += NumElements;
}
```
#### 修改DecodeGBufferData()以及相关函数
- 修改RayTracingDeferredShadingCommon.ush的DecodeGBufferData()
- 修改DeferredShadingCommon.ush中的FGBufferData添加ToonDataA变量并修改DecodeGBufferData()、GetGBufferDataUint()、GetGBufferData()、
- 修改SceneTextureParameters.ush中的ToonData变量声明`Texture2D ToonBufferATexture;`、`#define ToonBufferATextureSampler GlobalPointClampedSampler`以及`GetGBufferDataFromSceneTextures()`;SceneTexturesCommon.ush中的`#define SceneTexturesStruct_ToonBufferATextureSampler SceneTexturesStruct.PointClampSampler`
### 增加ToonDataPass MeshDrawPass已实现增加GBuffer
- 在MeshPassProcessor.h增加ToonDataPass MeshDrawPass定义。
- 在DeferredShadingRenderer.h添加渲染函数声明。
- 在新添加的ToonDataRendering.h与ToonDataRendering.cpp中添加MeshDrawPass声明与定义。
- 在ToonDataPassShader.usf中实现
```
// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
AnisotropyPassShader.usf: Outputs Anisotropy and World Tangent to GBufferF
=============================================================================*/
#include "Common.ush"
#include "/Engine/Generated/Material.ush"
#include "/Engine/Generated/VertexFactory.ush"
#include "DeferredShadingCommon.ush"
struct FToonDataPassVSToPS
{
float4 Position : SV_POSITION;
FVertexFactoryInterpolantsVSToPS Interps;
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
float3 PixelPositionExcludingWPO : TEXCOORD7;
#endif
};
#if USING_TESSELLATION
struct FAnisotropyPassVSToDS
{
FVertexFactoryInterpolantsVSToDS FactoryInterpolants;
float4 Position : VS_To_DS_Position;
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
float3 PixelPositionExcludingWPO : TEXCOORD7;
#endif
OPTIONAL_VertexID_VS_To_DS
};
#define FVertexOutput FAnisotropyPassVSToDS
#define VertexFactoryGetInterpolants VertexFactoryGetInterpolantsVSToDS
#else
#define FVertexOutput FToonDataPassVSToPS
#define VertexFactoryGetInterpolants VertexFactoryGetInterpolantsVSToPS
#endif
#if USING_TESSELLATION
#define FPassSpecificVSToDS FAnisotropyPassVSToDS
#define FPassSpecificVSToPS FToonDataPassVSToPS
FAnisotropyPassVSToDS PassInterpolate(FAnisotropyPassVSToDS a, float aInterp, FAnisotropyPassVSToDS b, float bInterp)
{
FAnisotropyPassVSToDS O;
O.FactoryInterpolants = VertexFactoryInterpolate(a.FactoryInterpolants, aInterp, b.FactoryInterpolants, bInterp);
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
TESSELLATION_INTERPOLATE_MEMBER(PixelPositionExcludingWPO);
#endif
return O;
}
FToonDataPassVSToPS PassFinalizeTessellationOutput(FAnisotropyPassVSToDS Interpolants, float4 WorldPosition, FMaterialTessellationParameters MaterialParameters)
{
FToonDataPassVSToPS O;
O.Interps = VertexFactoryAssignInterpolants(Interpolants.FactoryInterpolants);
O.Position = mul(WorldPosition, ResolvedView.TranslatedWorldToClip);
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
O.PixelPositionExcludingWPO = Interpolants.PixelPositionExcludingWPO;
#endif
return O;
}
#include "Tessellation.ush"
#endif
/*=============================================================================
* Vertex Shader
*============================================================================*/
void MainVertexShader(
FVertexFactoryInput Input,
OPTIONAL_VertexID
out FVertexOutput Output
#if USE_GLOBAL_CLIP_PLANE && !USING_TESSELLATION
, out float OutGlobalClipPlaneDistance : SV_ClipDistance
#endif
#if INSTANCED_STEREO
, uint InstanceId : SV_InstanceID
#if !MULTI_VIEW
, out float OutClipDistance : SV_ClipDistance1
#else
, out uint ViewportIndex : SV_ViewPortArrayIndex
#endif
#endif
)
{
#if INSTANCED_STEREO
const uint EyeIndex = GetEyeIndex(InstanceId);
ResolvedView = ResolveView(EyeIndex);
#if !MULTI_VIEW
OutClipDistance = 0.0;
#else
ViewportIndex = EyeIndex;
#endif
#else
uint EyeIndex = 0;
ResolvedView = ResolveView();
#endif
FVertexFactoryIntermediates VFIntermediates = GetVertexFactoryIntermediates(Input);
float4 WorldPos = VertexFactoryGetWorldPosition(Input, VFIntermediates);
float4 WorldPositionExcludingWPO = WorldPos;
float3x3 TangentToLocal = VertexFactoryGetTangentToLocal(Input, VFIntermediates);
FMaterialVertexParameters VertexParameters = GetMaterialVertexParameters(Input, VFIntermediates, WorldPos.xyz, TangentToLocal);
// Isolate instructions used for world position offset
// As these cause the optimizer to generate different position calculating instructions in each pass, resulting in self-z-fighting.
// This is only necessary for shaders used in passes that have depth testing enabled.
{
WorldPos.xyz += GetMaterialWorldPositionOffset(VertexParameters);
}
#if USING_TESSELLATION
// Transformation is done in Domain shader when tessellating
Output.Position = WorldPos;
#else
{
float4 RasterizedWorldPosition = VertexFactoryGetRasterizedWorldPosition(Input, VFIntermediates, WorldPos);
#if ODS_CAPTURE
float3 ODS = OffsetODS(RasterizedWorldPosition.xyz, ResolvedView.TranslatedWorldCameraOrigin.xyz, ResolvedView.StereoIPD);
Output.Position = INVARIANT(mul(float4(RasterizedWorldPosition.xyz + ODS, 1.0), ResolvedView.TranslatedWorldToClip));
#else
Output.Position = INVARIANT(mul(RasterizedWorldPosition, ResolvedView.TranslatedWorldToClip));
#endif
}
#if INSTANCED_STEREO && !MULTI_VIEW
BRANCH
if (IsInstancedStereo())
{
// Clip at the center of the screen
OutClipDistance = dot(Output.Position, EyeClipEdge[EyeIndex]);
// Scale to the width of a single eye viewport
Output.Position.x *= 0.5 * ResolvedView.HMDEyePaddingOffset;
// Shift to the eye viewport
Output.Position.x += (EyeOffsetScale[EyeIndex] * Output.Position.w) * (1.0f - 0.5 * ResolvedView.HMDEyePaddingOffset);
}
#elif XBOXONE_BIAS_HACK
// XB1 needs a bias in the opposite direction to fix FORT-40853
// XBOXONE_BIAS_HACK is defined only in a custom node in a particular material
// This should be removed with a future shader compiler update
Output.Position.z -= 0.0001 * Output.Position.w;
#endif
#if USE_GLOBAL_CLIP_PLANE
OutGlobalClipPlaneDistance = dot(ResolvedView.GlobalClippingPlane, float4(WorldPos.xyz - ResolvedView.PreViewTranslation.xyz, 1));
#endif
#endif
#if USING_TESSELLATION
Output.FactoryInterpolants = VertexFactoryGetInterpolants( Input, VFIntermediates, VertexParameters );
#else
Output.Interps = VertexFactoryGetInterpolants(Input, VFIntermediates, VertexParameters);
#endif // #if USING_TESSELLATION
#if INSTANCED_STEREO
#if USING_TESSELLATION
Output.Interps.InterpolantsVSToPS.EyeIndex = EyeIndex;
#else
Output.Interps.EyeIndex = EyeIndex;
#endif
#endif
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
Output.PixelPositionExcludingWPO = WorldPositionExcludingWPO.xyz;
#endif
OutputVertexID( Output );
}
/*=============================================================================
* Pixel Shader
*============================================================================*/
void MainPixelShader(
in INPUT_POSITION_QUALIFIERS float4 SvPosition : SV_Position,
FVertexFactoryInterpolantsVSToPS Input
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
, float3 PixelPositionExcludingWPO : TEXCOORD7
#endif
OPTIONAL_IsFrontFace
OPTIONAL_OutDepthConservative
, out float4 ToonBufferA : SV_Target0
#if MATERIALBLENDING_MASKED_USING_COVERAGE
, out uint OutCoverage : SV_Coverage
#endif
)
{
#if INSTANCED_STEREO
ResolvedView = ResolveView(Input.EyeIndex);
#else
ResolvedView = ResolveView();
#endif
// Manual clipping here (alpha-test, etc)
FMaterialPixelParameters MaterialParameters = GetMaterialPixelParameters(Input, SvPosition);
FPixelMaterialInputs PixelMaterialInputs;
#if USE_WORLD_POSITION_EXCLUDING_SHADER_OFFSETS
float4 ScreenPosition = SvPositionToResolvedScreenPosition(SvPosition);
float3 TranslatedWorldPosition = SvPositionToResolvedTranslatedWorld(SvPosition);
CalcMaterialParametersEx(MaterialParameters, PixelMaterialInputs, SvPosition, ScreenPosition, bIsFrontFace, TranslatedWorldPosition, PixelPositionExcludingWPO);
#else
CalcMaterialParameters(MaterialParameters, PixelMaterialInputs, SvPosition, bIsFrontFace);
#endif
#if OUTPUT_PIXEL_DEPTH_OFFSET
ApplyPixelDepthOffsetToMaterialParameters(MaterialParameters, PixelMaterialInputs, OutDepth);
#endif
#if MATERIALBLENDING_MASKED_USING_COVERAGE
OutCoverage = DiscardMaterialWithPixelCoverage(MaterialParameters, PixelMaterialInputs);
#endif
//float Anisotropy = GetMaterialAnisotropy(PixelMaterialInputs);
//float3 WorldTangent = MaterialParameters.WorldTangent;
ToonBufferA = float4(0.2, 0.1, 0.8, 1.0);
}
```