본문 바로가기
Computer Graphics/ShaderLab, HLSL

[ShaderLab] 서피스 쉐이더 구조 및 기초 작업

by 진현개발일기 2024. 2. 15.

■ ShaderLab

유니티 쉐이더는 ShaderLab이라고 부리는 자체 스크립트 언어를 갖고있다.

ShaderLab의 작성 방법이 아래와 같이 크게 세 가지로 나뉜다

 

(1) ShaderLab으로만 작성하기

(2) Surface Shader(서피스 셰이더)로 작성하기

(3) Vertex & Fragment Shader [Pixel Shader] (버텍스 & 프래그먼트 셰이더)로 작성하기

종류 특징
ShaderLab 매우 가볍고 하드웨어 호환성이 높지만 기능이 부족함.
요즈음 지원을 안하는 추세이기에 아래 두 가지 방식으로 보통 제작함
Surface Shader ShaderLab스크립트와 같이 CG쉐이더 코드를 사용하는 방법.
픽셀 쉐이더 부분만 가볍게 작성하면 됨. 하지만 최적화를 원하는만큼 하기에는 한계가 있을 뿐더러 고급 기능을 구현하기 어려움.

하지만 서피스 쉐이더로 작성한 쉐이더는 여러 플랫폼에 맞는 쉐이더를 자동으로 제작해줌
Vertex & Fragment Shader 버텍스 좌표 변환(Vertex Shader)부터 픽셀 셰이더 (Fragment Shader)부분까지 처리해줘야함. 완전히 수동 제어이기 때문에 고급기능 구현과 최적화를 원하는대로 할 수 있지만 어려움.

모바일, PC, 콘솔 등 여러 플랫폼과 사양에 맞게 분기를 나눠 맞춤 제작해줘야함. 

■ 구조

 

위 세 가지로 나뉜다

 

(1) Properties : 쉐이더의 인터페이스이다. 외부에서 변수 확인 및 설정 가능

 

(2) SubShader : 각각의 플랫폼 지시어를 사용하여 특정 플랫폼에 대한 쉐이더 코드를 정의하는 구간. 예로 DirectX11과 DirectX9에 대한 두 가지 서브쉐이더 작성 가능. SubShader는 전반적인 쉐이더의 버전 및 지원 플랫폼을 정의한다.

 

(3) CGPROGRAM ~ ENDCG : CG언어를 이용해 쉐이더를 직접 작성하는 부분이다. 

 

* CG(C for Graphics)는 그래픽 어플리케이션의 셰이딩에 특화된 언어이고 Unity에서 오래 전부터 사용되어왔다. CGPROGRAM은 Unity가 표준 Cg 셰이더를 지원하기 위해 제공하는 지시어다. 

 

만약 HLSL을 사용하여 작성하고 싶다면 HLSLPROGRAM을 사용해야한다. 하지만 기본적으로 유니티 내부에서는 쉐이더 코드를 HLSL로 처리하기 때문에 CGPROGRAM으로 작성해도 HLSL로 변환하여 처리하기 때문에 CGPROGRAM으로 작성해도 무방하다.

 

그러면 왜 CGPROGRAM과 HLSLPROGRAM을 나눠 사용하는가?
[CGPROGRAM을 사용하는 이유]

1. 크로스 플래솜 호환성 및 편리성
 : OpenGL 및 DirectX와 같은 여러 그래픽 API와 범용적으로 호환 가능. 그리고 C언어 기반이기에 여러 개발자에게 익숙함

2. 통합된 개발 환경 : 다른 Unity 컴포넌트와 통합이 원할함. 예로 Unity 셰이더 에디터에는 CGPROGRAM을 지원하고 Unity의 C# 스크립트와 통합도 쉽다.

3. 커뮤니티 및 문서 : CGPROGRAM을 사용하는 셰이더 예제와 튜토리얼이 많이 제공된다. 또한 온라인에 자료와 자원이 많기 때문에 쉽게 공부할 수 있음


[HLSLPROGRAM을 사용하는 이유]

1. DirectX에 최적화 : DirectX에 최적화된 High-Level Shader Language(HLSL)을 사용하기 때문에 DirectX에 특화된 기능을 사용해야할 때 HLSLPROGRAM이 더 적합함. 이로 인해 고급 쉐이더 코드를 작성할 수 있음
 
2. DirectX 전용 기능 사용 : DirectX에만 해당하는 특별한 셰이더 기능 활용가능


[요약]
CGPROGRAM은 통합된 개발 환경 속에서 범용적으로 동작하는 기능을 작성하고 쉽게 공부하고 싶을 때 활용한다. 또한, 온라인에 방대한 자료의 존재 덕분에 초보자들이 쉽게 접근할 수 있는 장점이 있다. 유니티는 꽤 오래전부터 CGPROGRAM을 Default 값으로 사용하고 있다.

HLSLPROGRAM은 DirectX에 특화된 플랫폼인 게임이나 어플리케이션에서 고급 쉐이더 기술을 작성하고 싶을 때 사용한다.
주로 PC플랫폼에서 고사양의 쉐이더를 작성하고 싶을 때 HLSLPROGRAM을 사용하고 모바일 등 저사양 플랫폼에도 작동하게끔 쉐이더를 사용하고 싶다면 CGPROGRAM을 작성한다.

[추가 내용]

(1)
Unity 내부에서 쉐이더코드를 HLSL로 변환하여 사용하기 때문에 CGPROGRAM 또한 컴파일 시 HLSL로 변환하여 처리된다. 즉, CGPROGRAM으로 작성된 쉐이더 코드는 내부적으로 HLSL로 컴파일되어 그래픽 카드에서 실행되어지는 것이다.
여기서 궁금했던 점은 '어차피 HLSL로 변환되어 사용되어진다면 왜 HLSLPROGRAM과 성능 차이가 나는 것인가?' 이다.
자료 조사를 해보니 Unity에서 내부적으로 CGPROGRAM을 HLSL로 변환할 때 자동으로 저사양 플랫폼에 대한 최적화 및 하드웨어 호환성을 고려하면서 변환한다고 한다. 

(2)
HLSLPROGRAM, CGPROGRAM을 사용하는 SubShader가 다수 존재할 경우 Unity 내부에서 자동으로 플랫폼 사양에 맞게 골라 사용하도록 되어있다. 

 

■ 서피스 쉐이더 작성 및 기초적인 머테리얼 구현

 

 

 

스니핏(Snippet) 부분에서 서피스 함수에 관하여 처리 중 noambient 키워드를 추가했다. 이는 나중에 주변광(ambient light)이나 라이트 프로브에 영향을 받지 않도록 하기 위함이다.

 

 

[Tip]

color range는 보통 0~1이 정상이다. 이 범위를 벗어나면 값은 저장하지만 디스플레이에 출력이 안되는데
이를 출력되게끔 표현해줄 수 있는 상태를 HDR(High Dynamic Range)이라고 한다.

즉, HDR상태는 1보다 밝은 색이 있고 0보다 어두운 색이 존재한다는 상태이다.

728x90