저자: Levent
서론
SceneViewExtension에 대해서는 온라인에 이미 많은 소개 자료가 있으므로, 본문에서는 기본 개념을 다시 설명하지 않고 구현 방법과 핵심 아이디어에 중점을 두겠습니다.
관심 있는 독자들은 언리얼 엔진의 내장 플러그인을 참고할 수 있습니다.
이 플러그인 코드의 대부분을 이해하면 기본적으로 SceneViewExtension을 마스터할 수 있습니다. 저도 초보자이며, 이 글은 주로 개인 노트용으로 작성했지만 비슷한 요구사항을 가진 분들에게 도움이 되길 바랍니다. 오류가 있다면 언제든 지적해 주세요.
시작하기
SceneViewExtension을 사용하면 플러그인에서 커스텀 Pass를 추가하여 렌더링 파이프라인을 확장할 수 있습니다. 먼저 플러그인을 생성해야 합니다. 시간을 절약하기 위해 여기서는 오픈소스 템플릿을 직접 사용하겠습니다:
GitHub - A57R4L/SceneViewExtensionTemplate: Unreal Engine 5 plugin template for adding custom rendering pass to the engine with
Unreal Engine 5 plugin template for adding custom rendering pass to the engine with a SceneViewExtension - A57R4L/SceneViewExtensionTemplate
github.com
(오픈소스에 감사드립니다)
이 플러그인은 Compute Shader를 사용하여 SceneColor 데이터를 수정합니다. 완전히 이해한다면, 계산량이 많거나 초대형 해상도 RT를 처리해야 하는 시나리오에서 이 방식으로 RT 데이터를 계산할 수 있습니다. 물론 능력이 있는 분들은 직접 만들 수도 있습니다. 본문은 이 플러그인에 크게 의존하지 않으며, 단지 준비 코드를 줄이기 위해 사용합니다.
핵심 목표
우리의 목표는 Gbuffer 데이터를 수정하는 것입니다. 먼저 Gbuffer가 어느 단계에서 값이 할당되는지 명확히 해야 합니다.
답은 BasePass (BasePassPixelShader.usf)입니다. 따라서 BasePass 이후에 커스텀 Pass를 삽입해야 합니다.
ISceneViewExtension 클래스에서 다음을 찾습니다.
가상 함수를 찾습니다: PostRenderBasePassDeferred_RenderThread
복사하세요!
플러그인 디렉토리의 Private 아래에서 CustomSceneViewExtension.h를 찾아 public 선언을 추가합니다.
PostRenderBasePassDeferred_RenderThread
이제 이 가상 함수를 구현합니다:
SceneViewExtensionTemplate\Source\SceneViewExtensionTemplate\Private\CustomSceneViewExtension.cpp
IMPLEMENT_GLOBAL_SHADER(FGbufferModifyShaderPS, "/Plugins/SceneViewExtensionTemplate/GBufferModifyShader.usf", "MainPS", SF_Pixel);
IMPLEMENT_GLOBAL_SHADER(FGbufferModifyShaderVS, "/Plugins/SceneViewExtensionTemplate/GBufferModifyShader.usf", "MainVS", SF_Vertex);
void FCustomSceneViewExtension::PostRenderBasePassDeferred_RenderThread(FRDGBuilder& GraphBuilder, FSceneView& InView, const FRenderTargetBindingSlots& RenderTargets, TRDGUniformBufferRef<FSceneTextureUniformParameters> SceneTextures)
{
// 간단한 스위치
if (CVarGbufferModifyPassOn.GetValueOnRenderThread() == 0)
{
return;
}
// 입력 RT 준비
// 메탈릭, 스페큘러, 러프니스(MSRI) 가져오기
FRDGTexture* MSRI_RT = RenderTargets[2].GetTexture();
FGlobalShaderMap* GlobalShaderMap = GetGlobalShaderMap(InView.GetFeatureLevel());
const FIntRect ScreenViewRect = InView.UnscaledViewRect;
FRDGTextureRef OutputTexture = GraphBuilder.CreateTexture(MSRI_RT->Desc, TEXT("OutPutMSRI"));
FScreenPassRenderTarget OutputRenderTarget = FScreenPassRenderTarget(OutputTexture,ERenderTargetLoadAction::EClear);
const FScreenPassTextureViewport ScreenPassTextureViewport(MSRI_RT, ScreenViewRect);
FRHIBlendState* DefaultBlendState = FScreenPassPipelineState::FDefaultBlendState::GetRHI();
TShaderMapRef<FGbufferModifyShaderPS> GbufferModifyShaderPS(GlobalShaderMap);
TShaderMapRef<FGbufferModifyShaderVS> GbufferModifyShaderVS(GlobalShaderMap);
FGbufferModifyShaderPS::FParameters* PassParameters = GraphBuilder.AllocParameters<FGbufferModifyShaderPS::FParameters>();
PassParameters->InputRT = MSRI_RT;
PassParameters->RenderTargets[0] = OutputRenderTarget.GetRenderTargetBinding();
PassParameters->InputRTSampler = TStaticSamplerState<SF_Bilinear, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
// ScreenPass 추가
AddDrawScreenPass(
GraphBuilder,
RDG_EVENT_NAME("GbufferModifyPass"),
InView,
ScreenPassTextureViewport,
ScreenPassTextureViewport,
GbufferModifyShaderVS,
GbufferModifyShaderPS,
PassParameters,
EScreenPassDrawFlags::None
);
// RT를 수정하는 동시에 값을 할당할 수 없으므로, 임시 텍스처를 사용하여 MSRI 버퍼를 수정
AddCopyTexturePass(GraphBuilder, OutputRenderTarget.Texture, FRDGTextureRef(MSRI_RT));
}
헤더 파일은 다음과 같습니다:
SceneViewExtensionTemplate\Source\SceneViewExtensionTemplate\Private\CustomSceneViewExtension.h
class SCENEVIEWEXTENSIONTEMPLATE_API FGbufferModifyShaderPS : public FGlobalShader
{
public:
DECLARE_GLOBAL_SHADER(FGbufferModifyShaderPS);
SHADER_USE_PARAMETER_STRUCT(FGbufferModifyShaderPS, FGlobalShader);
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
return !IsMobilePlatform(Parameters.Platform);
}
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER_RDG_TEXTURE(Texture2D<float4>, InputRT)
SHADER_PARAMETER_SAMPLER(SamplerState, InputRTSampler)
RENDER_TARGET_BINDING_SLOTS()
END_SHADER_PARAMETER_STRUCT()
};
class SCENEVIEWEXTENSIONTEMPLATE_API FGbufferModifyShaderVS : public FGlobalShader
{
public:
DECLARE_GLOBAL_SHADER(FGbufferModifyShaderVS);
FGbufferModifyShaderVS() = default;
FGbufferModifyShaderVS(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FGlobalShader(Initializer)
{
}
};
이상이 PostRenderBasePassDeferred_RenderThread의 간단한 구현입니다. 부적절한 부분이 있다면 언제든 지적해 주세요.
셰이더
다음은 셰이더 구현입니다. 간단한 곱셈 연산을 작성하여 Roughness를 0으로 설정합니다(검은색으로 표시됨):
SceneViewExtensionTemplate\Shaders\GBufferModifyShader.usf
#include "/Engine/Public/Platform.ush"
#include "/Engine/Private/Common.ush"
#include "/Engine/Private/ScreenPass.ush"
void MainVS(
in float4 InPosition : ATTRIBUTE0,
in float2 InTexCoord : ATTRIBUTE1,
out float4 OutUVAndScreenPos : TEXCOORD0,
out float4 OutPosition : SV_POSITION)
{
DrawRectangle(InPosition, InTexCoord, OutPosition, OutUVAndScreenPos);
}
Texture2D InputRT;
SamplerState InputRTSampler;
void MainPS(
in float4 UVAndScreenPos : TEXCOORD0,
out float4 OutputRT : SV_Target0
)
{
float2 UV = UVAndScreenPos.xy;
float4 result = Texture2DSample(InputRT, InputRTSampler, UV);
OutputRT = result*float4(1, 1, 0, 1);
}
코드는 주로 Unreal 내장 플러그인을 참고했으며, 차이점은 입력과 출력이 모두 RT라는 점입니다.
모든 것이 순조롭다면, 컴파일 후 플러그인을 열고 명령줄을 통해 입력하면 효과를 볼 수 있습니다.
GbufferModifyPass Off
GbufferModifyPass On
RenderDoc으로 한 프레임을 캡처하여 확인:
효과가 정확합니다.
끝.
…
그렇지 않습니다. 현재 예제는 출력만 있고 입력이 없어서 효과가 고정되어 있습니다. 효과를 조정하려면 셰이더를 직접 수정해야 할까요?
이것은 분명히 현실적이지 않습니다. 가장 좋은 방법은 씬에 Actor를 생성하여 매개변수를 조정하는 것입니다.
바로 실행합시다:
MyActor:
Subsystem:
SceneViewExtension:
Shader:
이번에는 Roughness 대신 Metallic을 수정하며, 효과는 다음과 같습니다.
코드는 비교적 간단하며, 고려가 충분하지 않은 부분도 있습니다.
원문
(41 封私信 / 29 条消息) [UE5]使用SceneViewExtension修改Gbuffer数据 - 知乎
'TECH.ART.FLOW.IO' 카테고리의 다른 글
[번역] PredictFootIK 구현 (0) | 2025.10.15 |
---|---|
"Advanced Horse IK Solution" related of tech for Study lists. (0) | 2025.10.13 |
[번역] UE5 Virtual Assets 가용성 분석 (0) | 2025.10.12 |
[번역] UE 리소스 컴플라이언스 검사 툴 ResScannerUE (0) | 2025.10.12 |
[YOUTUBE] 컴퓨터 그래픽의 선구자들. (0) | 2025.10.02 |