UE5 渲染源码学习 - 添加描边后处理 Shader

UE5 渲染源码学习 - 添加描边后处理 Shader

Zh-Hui Programmer

效果对比

纯 HTML 实现滑动对比
Before After

添加描边 Shader:EdgePsShaders.usf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "../Common.ush"

Texture2D SceneColorTexture;
SamplerState SceneColorSampler;

void MainPS(
noperspective float4 UVAndScreenPos : TEXCOORD0,
float4 SvPosition : SV_POSITION,
out float4 OutColor : SV_Target0)
{
float2 UV = UVAndScreenPos.xy;
float3 FinalColor = float3(0.0,0.0,0.0);
const int edgeSize = 1;

for(int x = -edgeSize; x<=edgeSize; ++x)
{
for(int y = -edgeSize; y <= edgeSize; ++y)
{
float2 SampleUV = UV + (float2(x,y) * View.BufferSizeAndInvSize.zw);
float3 SampleColor = Texture2DSample(SceneColorTexture, SceneColorSampler, SampleUV).rgb;

if(x == 0 && y == 0)
{
FinalColor += (8 * SampleColor);
}
else
{
FinalColor += (-1 * SampleColor);
}
}
}

FinalColor = dot(FinalColor, float3(0.299, 0.587, 0.114));
OutColor = float4(FinalColor, 1.0);
}

添加 Renderer 以及 Shader 声明

DrawEdgePsRendering.h

1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once

#include "RenderGraphFwd.h"
#include "Engine/World.h"
#include "GlobalShader.h"
#include "PipelineStateCache.h"
#include "RHIStaticStates.h"
#include "SceneUtils.h"
#include "../SceneRendering.h"
#include "SceneInterface.h"
#include "ShaderParameterUtils.h"

void RenderEdgePs(FRDGBuilder& GraphBuilder, const FViewInfo& View, FRDGTextureRef InputColorTexture, FRDGTextureRef ViewTexture);

DrawEdgePsRendering.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include "DrawEdgePsRendering.h"
#include "GlobalShader.h"
#include "ShaderParameterStruct.h"
#include "Engine/World.h"
#include "PipelineStateCache.h"
#include "RHIStaticStates.h"
#include "SceneUtils.h"
#include "SceneInterface.h"
#include "ShaderParameterUtils.h"
#include "../SceneRendering.h"
#include "../Public/ScreenPass.h"

class FEdgePsPS : public FGlobalShader
{
public:
DECLARE_SHADER_TYPE(FEdgePsPS, Global);

SHADER_USE_PARAMETER_STRUCT(FEdgePsPS, FGlobalShader);

BEGIN_SHADER_PARAMETER_STRUCT(FParameters,)
SHADER_PARAMETER_STRUCT_REF(FViewUniformShaderParameters, View)
SHADER_PARAMETER_RDG_TEXTURE(Texture2D, SceneColorTexture)
SHADER_PARAMETER_SAMPLER(SamplerState, SceneColorSampler)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
};

IMPLEMENT_SHADER_TYPE(, FEdgePsPS, TEXT("/Engine/Private/DrawEdge/EdgePsShaders.usf"), TEXT("MainPS"), SF_Pixel)

void RenderEdgePs(FRDGBuilder& GraphBuilder, const FViewInfo& View, FRDGTextureRef InputColorTexture, FRDGTextureRef ViewFamilyTexture)
{
FRDGTextureRef CopiedViewFamilyTexture = GraphBuilder.CreateTexture(ViewFamilyTexture->Desc, TEXT("CopiedViewFamilyTexture"));
AddCopyTexturePass(GraphBuilder, ViewFamilyTexture, CopiedViewFamilyTexture);

TShaderMapRef<FEdgePsPS> PixelShader(View.ShaderMap);
FEdgePsPS::FParameters* PassParameters = GraphBuilder.AllocParameters<FEdgePsPS::FParameters>();
PassParameters->View = View.ViewUniformBuffer;
PassParameters->SceneColorSampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
PassParameters->SceneColorTexture = CopiedViewFamilyTexture;
PassParameters->RenderTargets[0] = FRenderTargetBinding(ViewFamilyTexture, ERenderTargetLoadAction::ENoAction);

AddDrawScreenPass(GraphBuilder, RDG_EVENT_NAME("Edge Pass"), View,
FScreenPassTextureViewport(ViewFamilyTexture),
FScreenPassTextureViewport(ViewFamilyTexture),
PixelShader, PassParameters);
}

在延迟渲染管线的最后调用描边渲染Pass

DeferredShadingSceneRenderer.cppRender() 函数中添加代码:

1
2
3
4
5
6
7
8
if (ViewFamily.bResolveScene && ViewFamilyTexture)
{
for (int32 i = 0; i < Views.Num(); i++)
{
const FViewInfo& View = Views[i];
RenderEdgePs(GraphBuilder, View, nullptr, ViewFamilyTexture);
}
}

引用

7 UE5.1 修改引擎源码 新增屏幕特效

  • 标题: UE5 渲染源码学习 - 添加描边后处理 Shader
  • 作者: Zh-Hui
  • 创建于 : 2025-03-10 19:36:56
  • 更新于 : 2025-03-28 14:01:25
  • 链接: https://hui1520.top/2025/03/10/UE5AddPostShader/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论