314 lines
11 KiB
Markdown
314 lines
11 KiB
Markdown
# 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);
|
||
}
|
||
``` |