# 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 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); } ```