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

11 KiB
Raw Blame History

Yivanlee 添加Pass与GBuffer笔记

给BaseScalability.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。

//h
DECLARE_CYCLE_STAT_EXTERN(TEXT("ToonData pass drawing"), STAT_ToonDataPassDrawTime, STATGROUP_SceneRendering, RENDERCORE_API);

//cpp
DEFINE_STAT(STAT_ToonDataPassDrawTime);

BasePassRendering.cpp里定义渲染状态宏。

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

//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()添加

if (StaticMeshRelevance.bUseToonData)
{
    DrawCommandPacket.AddCommandsForMesh(PrimitiveIndex, PrimitiveSceneInfo, StaticMeshRelevance, StaticMesh, Scene, bCanCache, EMeshPass::ToonDataPass);
}

在ComputeDynamicMeshRelevance()中添加

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