Custom 머티리얼 표현식을 사용하면 임의의 입력에서 연산하고 연산 결과를 출력하는 사용자 정의 HLSL 셰이더 코드를 작성할 수 있습니다.
Custom 표현식은 머티리얼 팔레트의 Custom 카테고리에서 삽입하거나 머티리얼 그래프에서 우클릭 검색 메뉴를 통해 삽입할 수 있습니다.
Custom 노드가 선택된 상태에서는 다음과 같은 프로퍼티가 디테일 패널에 나타납니다.
| 프로퍼티 | 설명 |
|---|---|
| Code | 표현식이 실행할 셰이더 코드가 들어갑니다. (아래 경고 참고) |
| Output Type | 표현식의 출력 값 유형을 나타냅니다. |
| Description | 머티리얼 에디터에서 표현식 제목줄에 표시되는 텍스트를 나타냅니다. |
| Inputs | 표현식에 사용되는 입력 배열입니다. |
[REGION:prop_sublist]
Input Name [/REGION] |
[REGION:prop_sublist]
입력의 이름을 나타냅니다. 머티리얼 에디터의 표현식 위에 표시되는 용도는 물론 HSLS 코드 안에서 입력 값을 레퍼런스하는 데 사용되기도 하는 이름입니다. [/REGION] |
| Additional Outputs | 사용자 정의 표현식에 추가적인 출력 핀을 정의할 수 있습니다. 출력을 추가할 때는 배열 요소를 확장하고 해당 요소의 출력 이름 과 출력 유형 프로퍼티룰 지정해야 합니다. |
| Additional Defines | 사용자 정의 HLSL 코드에서 필요한 추가 정의(Defines)를 추가할 수 있게 해줍니다. 배열에 요소를 추가할 때는 정의 이름과 정의 값 프로퍼티를 지정해야 합니다. |
| Include File Paths | 이미 제공되는 일반적인 셰이더 경로 외부의 소스 파일에서 포함시키고자 하는 셰이더 코드의 파일 경로를 지정합니다. |
Custom 머티리얼 표현식 사용하기
Inputs 배열에 필요한 만큼의 입력을 추가하고 이름을 지정합니다. 그런 다음 Code 프로퍼티 필드에 필요한 HLSL 코드를 직접 입력하거나 붙여넣습니다. 예시에서와 같이 함수 본문 전체를 반환문과 함께 입력하거나, Input.bgr 과 같은 간단한 식을 입력할 수 있습니다. 그리고 OutputType에서 출력 데이터 유형을 반드시 지정해야 합니다.
아래 예시는 스칼라 파라미터 값에 기반하여 텍스처 오브젝트를 블러 처리하는 Custom 표현식입니다.
전체 이미지를 보려면 클릭합니다.
위에서 사용된 코드를 여러분이 직접 Custom 노드를 시험해 볼 수 있도록 제공합니다. 아래 텍스트를 복사하여 디테일 패널 프로퍼티의 Code 필드에 붙여넣기하세요.
float3 blur = Texture2DSample(Tex, TexSampler, UV);
for (int i = 0; i < r; i++)
{
blur += Texture2DSample(Tex, TexSampler, UV + float2(i * dist, 0));
blur += Texture2DSample(Tex, TexSampler, UV - float2(i * dist, 0));
}
for (int j = 0; j < r; j++)
{
blur += Texture2DSample(Tex, TexSampler, UV + float2(0, j * dist));
blur += Texture2DSample(Tex, TexSampler, UV - float2(0, j * dist));
}
blur /= 2*(2*r)+1;
return blur;
다음 동영상은 위의 HLSL 코드를 사용하여 Custom 표현식을 생성하고 결과를 보여줍니다.
알려진 문제
다음 섹션에서는 Custom 머티리얼 표현식을 작성할 때 주의해야 할 일반적인 오류 몇 가지를 설명합니다.
입력 인자는 함수 범위 내에서 작동합니다
Custom 표현식은 항상 반환 값이 있어야 합니다. 왜냐하면 이러한 표현식은 다른 함수 내에 래핑되기 때문입니다. 모든 입력 인자(예: 위의 예시에서의 Tex, UV, r 및 dist)는 외부 함수의 매개변수로 선언되며, 그렇기 때문에 이들의 비저빌리티 범위(scope of visibility)는 함수 내부로 제한됩니다.
경우에 따라 개발자들은 멤버 함수로 구조체를 작성하고 해당 구조체 내에서 이러한 파라미터에 액세스하길 원합니다. 하지만 파라미터는 함수 범위 내에서만 액세스할 수 있습니다. 따라서 Custom 표현식 내에서 멤버 함수를 사용할 때는 이러한 파라미터를 수동으로 복사해야 합니다.
아래 예시는 컴파일에 실패할 것입니다(위의 예시와 동일한 상황을 가정한 경우).
struct InnerStruct
{
float4 Run()
{
// ERROR: Tex, TexSampler, and UV is not accessible within InnerStruct
return Texture2DSample(Tex, TexSampler, UV);
}
};
InnerStruct S;
return S.Run();
HLSLcc 컴파일러 사용 시 구문 오류
Some shader backends that use the older HLSLcc compiler report syntax errors on HLSL types such as vector and matrix. Try to be explicit with your data types and use float4 or float4x4 respectively. We keep fixing those bugs but at the same time we are moving our efforts to the new DirectXShaderCompiler (DXC). 오래된 HLSLcc 컴파일러를 사용하는 일부 셰이더 백엔드는 벡터 및 행렬과 같은 HLSL 유형에 대한 문법 오류를 보고할 수 있습니다. 데이터 유형을 명시적으로 지정하고 각각 float4 또는 float4x4 를 사용해 보세요. 에픽은 이러한 버그를 계속 수정하고 동시에 새로운 DirectXShaderCompiler(DXC)를 위해 노력하고 있습니다.
경고
- 커스텀 노드를 사용하면 상수 폴딩을 사용하지 못하게 되어 내장 노드의 동일한 버전보다 인스트럭션 수를 훨씬 많이 사용하게 될 수 있습니다! 상수 폴딩이란 필요한 경우 UE4 내부적으로 셰이더 인스트럭션 수를 줄이는 데 사용되는 최적화입니다. 예를 들어 'Time->Sin->파라미터로 곱(Mul)하고->뭔가에 더(Add)하는' 표현식 체인은 언리얼 엔진에서 최종 Add 하나로 압축 가능하고 또 그렇게 됩니다. 이것이 가능한 이유는, 그 표현식에 있는 (Time, 파라미터 등의) 모든 입력이 전체 드로 콜에 있어서 상수이고, 픽셀별로 달라지지 않기 때문입니다. UE는 커스텀 노드에 있는 것을 압축할 수 없기에, 기존의 노드로 똑같은 기능을 하도록 만든 버전에 비하면 셰이더 효율이 떨어집니다. 결과적으로 기존 노드로는 할 수 없는 기능이 필요할 때만 커스텀 노드를 사용하는 것이 최선입니다.
- 커스텀 노드에 작성된 셰이더 코드는 유효한 HLSL 코드로 되어있어야 합니다.