본문 바로가기
UE5

[UE5]Custom Shader : PART4_Custom Material Ouput

by kaynine 2023. 10. 16.

시작하며

셰이더 도메인을 보면 베이스 컬러, 노말, 탄젠트 등 여러 입력을 받는 핀들이 있고 앞선 글에서 커스텀 데이터 핀을 활성화 시켜서 커스텀 데이터 입력을 받을 수 있도록 했는데 만약에 작성 중인 커스컴 셰이딩 모델이 더 많은 입력을 필요로 한다면 도메인의 핀을 새로 만들어주는 작업이 필요합니다. 하지만 도메인에 직접 핀을 생성하는 건 엔진 코드를 생각보다 많이 수정 해야하니 이를 피하기 위해 커스텀 머티리얼 아웃풋을 만들어서 커스텀 셰이딩 모델의 입력을 추가해 볼게요.


엔진 코드 수정하기

MaterialExpressionMabiLitMaterialOutput.h

추가할 핀을 선언할 헤더 파일을 작성합니다

// [ CUSTOM ] Expanding Material Output
#pragma once

#include "CoreMinimal.h"
#include "Materials/MaterialExpressionCustomOutput.h"
#include "UObject/ObjectMacros.h"
#include "MaterialExpressionCustomLitMaterialOutput.generated.h"

UCLASS(MinimalAPI, collapsecategories, hidecategories = Object)
class UMaterialExpressionCustomLitMaterialOutput : public UMaterialExpressionCustomOutput
{
	GENERATED_UCLASS_BODY()

	UPROPERTY()
	FExpressionInput CustomOutput01;
	
	UPROPERTY()
	FExpressionInput CustomOutput02;
	 
	UPROPERTY()
	FExpressionInput CustomOutput03;

public:
#if WITH_EDITOR
	virtual int32 Compile(class FMaterialCompiler* Compiler, int32 OutputIndex) override;
	virtual void GetCaption(TArray<FString>& OutCaptions) const override;
#endif

	virtual int32 GetNumOutputs() const override;
	virtual FString GetFunctionName() const override;
	virtual FString GetDisplayName() const override;
};

MaterialExpressions.cpp

위에서 선언한 대로 구현해 줍니다. 컴파일 됐을 때 데이터 형식과 이름 등이에요

// [ CUSTOM ] Expanding Material Ouput
#include "Materials/MaterialExpressionCustomLitMaterialOutput.h"

// [ CUSTOM ] Expanding Material Ouput
///////////////////////////////////////////////////////////////////////////////
// UMaterialExpressionCustomLitMaterialOutput
///////////////////////////////////////////////////////////////////////////////
UMaterialExpressionCustomLitMaterialOutput::UMaterialExpressionCustomLitMaterialOutput(const FObjectInitializer& ObjectInitializer)
	:Super(ObjectInitializer)
{
	// Structure to hold one-time initialization
	struct FConstructorStatics
	{
		FText NAME_CustomLit;
		FConstructorStatics()
			: NAME_CustomLit(LOCTEXT("CustomLit", "CustomLit"))
		{
		}
	};
	static FConstructorStatics ConstructorStatics;

#if WITH_EDITORONLY_DATA
	MenuCategories.Add(ConstructorStatics.NAME_CustomLit);
#endif

#if WITH_EDITOR
	Outputs.Reset();
#endif
}

#if WITH_EDITOR

int32 UMaterialExpressionCustomLitMaterialOutput::Compile(class FMaterialCompiler* Compiler, int32 OutputIndex)
{
	int32 CodeInput = INDEX_NONE;

	const bool bStrata = Strata::IsStrataEnabled();

	if (OutputIndex == 0)
	{
		CodeInput = CustomOutput01.IsConnected() ? CustomOutput01.Compile(Compiler) : Compiler->Constant4(0.f, 0.f, 0.f, 0.f);
	}
	else if (OutputIndex == 1)
	{
		CodeInput = CustomOutput02.IsConnected() ? CustomOutput02.Compile(Compiler) : Compiler->Constant3(0.f, 0.f, 0.f);
	}
	else if (OutputIndex == 2)
	{
		CodeInput = CustomOutput03.IsConnected() ? CustomOutput03.Compile(Compiler) : Compiler->Constant3(0.f, 0.f, 0.f);
	}

	return Compiler->CustomOutput(this, OutputIndex, CodeInput);
}

void UMaterialExpressionCustomLitMaterialOutput::GetCaption(TArray<FString>& OutCaptions) const
{
	OutCaptions.Add(FString(TEXT("CustomLit Material")));
}

#endif // WITH_EDITOR

int32 UMaterialExpressionCustomLitMaterialOutput::GetNumOutputs() const
{
	return 3;
}

FString UMaterialExpressionCustomLitMaterialOutput::GetFunctionName() const
{
	return TEXT("GetCustomLitMaterialOutput");
}

FString UMaterialExpressionCustomLitMaterialOutput::GetDisplayName() const
{
	return TEXT("CustomLit Material");
}

결과

 

노드 검색을 통해 작업 화면에 불러와서 사용하면 돼요


마치며

셰이더 코드를 살펴보면 알게 되겠지만 커스텀 머티리얼 아웃풋은 BasePassPixelShader.usf를 벗어나 다른 셰이더에서 쓰려면 버텍스 정보를 인수로 받아서 픽셀 셰이더를 구현한 다음에 값을 받아올 수 있는데 상황에 따라서는 여의치 않을 수 있어요. 그래서 다음 글에서는 이 값들을 GBuffer를 통해 다른 셰이더에 전달해 보도록 할게요.


참고

https://dev.epicgames.com/community/learning/tutorials/2R5x/unreal-engine-new-shading-models-and-changing-the-gbuffer

 

New shading models and changing the GBuffer | Community tutorial

Implementing a Celshading model directly into UE5.1 source. This celshading use a linear color curve atlas to drive all the values. Learn how to set you...

dev.epicgames.com