지난 포스팅에서 셰이더 코드는 유니티 전용 셰이더 언어인 ShaderLab과 HLSL언어를 사용해 작성할 수 있다고 하였다.
이번 포스팅에서는 간단한 예시를 통해 실제 코드가 어떻게 작성이 되는지 나타내었다.
Built-in 파이프라인의 경우 Legacy가 될 예정이기 때문에 URP를 기준으로 글을 작성하였다.
셰이더 생성
유니티의 프로젝트 창에서 Create - Shader - Unit Shader를 눌러 파일을 생성한다.
생성된 셰이더 코드를 열어보면 다음과 같다.
참고로 이 기본 Unlit 셰이더 코드는 Cg로 작성되어있다. 유니티에서는 HLSL을 사용한 셰이더 제작을 권장하기 때문에 해당 구조를 HLSL로 변경하여 아래에 다시 작성하며 포스팅을 이어나간다.
우리는 위 코드에서 셰이더의 뼈대만 살펴보면 된다. 전체적인 구조는 같기 때문이다.
크게 Shader - (Properties / SubShader) - (Tags / Pass) - xxPROGRAM으로 되어있다는 것을 기억하자.
Shader "Custom/JslandDevlog"
{
Properties
{
...
}
SubShader
{
Pass
{
...
}
}
}
HLSL 셰이더 프로그래밍
이제 HLSL코드를 보며 각 문장이 의미하는 바가 무엇인지 살펴보고자 한다.
ShaderLab
우선 시작하기 전에 알아두어야 할 것은, 우리는 셰이더 파일에 셰이더 언어를 통해 작성하려 하고 있으며 이것의 올바른 이름은 셰이더 오브젝트이다. 그리고 이러한 셰이더 오브젝트는 셰이더 랩(ShaderLab)을 사용해야 한다.
그렇다면 ShaderLab은 어떻게 사용할 수 있을까?
아래는 예시 코드이며, 이 셰이더는 Unlit 색상을 나타낸다.
Shader "Custom/JslandDevlog"
{
Properties
{
_BaseColor("Base Color", Color) = (1,1,1,1)
}
SubShader
{
Tags
{
"Render Type" = "Opaque"
"RenderPipeline" = "UniversalPipeline"
"Queue" = "Geometry"
}
Pass
{
Tags
{
"LightMode" = "UniversalForward"
}
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct appdata
{
float4 positionOS : POSITION;
};
struct v2f
{
float4 positionCS : SV_POSITION;
};
float4 _BaseColor;
v2f vert(appdata v)
{
v2f o;
o.positionCS = TransformObjectToHClip(v.positionOS);
return o;
}
float4 frag(v2f i) : SV_TARGET
{
return _BaseColor;
}
ENDHLSL
}
}
}
셰이더 키워드 (Shader"name")
여기서 첫 줄 Shader"파일이름"은 머테리얼에서 표시될 파일의 이름을 나타낸다.
위 예시처럼 '/'를 사용하여 폴더로 묶을 수도 있다.
프로퍼티 (Properties)
일반적인 프로그래밍에서 사용되는 프로퍼티와 동일하다. 이곳에 작성하는 변수는 머테리얼에서 노출되기 때문에 쉽게 변경할 수 있다.
여기 사용된 변수 선언 방식은 우리가 기존에 사용하던 사뭇 다르다.
_BaseColor("Base Color", Color) = (1,1,1,1)
각 단어는 어떤 의미를 갖고 있을까?
_BaseColor | Computer readable name이며 _(언더바)로 시작 |
"Base Color" | Human readable name이며 "(쌍따옴표)사이에 작성 |
Color | 변수의 타입 |
(1,1,1,1) | 변수 초기값 |
서브셰이더 (SubShader)
SubShader의 특징은 다음과 같다.
- 하나의 파일에 여러 개의 서브셰이더를 작성할 수 있다.
- 유니티는 셰이더를 로드할 때 서브셰이더의 리스트 중에서 기기가 지원하는 가장 위에 것을 선택한다.
- 만약 어떠한 서브셰이더도 지원하지 않는다면 FallBack 셰이더를 사용한다.
- 모든 서브셰이더가 실패하고 FallBack도 없다면 컴파일에 실패하고 마젠타색으로 나타난다.
이를 요약하면 다음과 같이 나타낼 수 있다.
Shader "something"
{
Properties {...}
SubShader {...}
SubShader {...}
Fallback "Unlit/Color"
}
(Pass와 Tags, HLSLPROGRAM, struct, #pragma 등은 다음 포스팅에서 이어서 작성됩니다.)
'유니티 > 셰이더 및 VFX' 카테고리의 다른 글
[Unity] 셰이더 코드 (1) - 셰이더 언어 (Cg, GLSL and HLSL) (0) | 2024.01.17 |
---|---|
[Unity] 버텍스와 프래그먼트 (Vertex & Fragment) (0) | 2023.02.23 |
[Unity] 셰이더란 무엇인가? (0) | 2023.02.15 |