본문 바로가기

유니티/렌더링

[유니티셰이더]유니티 Surface Shader 작성 메뉴얼

반응형

유니티의 Surface Shader는 조명과 상호작용하는 셰이더를 쉽게 만들어주는 코드 생성 방법입니다. 기능이 제한되어 있는 단점을 가지고 있지만 쉽게 셰이더를 제작할 수 있죠. 오늘은 휴일 첫날을 기념하여 유니티 메뉴얼을 살펴보며 이에 대한 내용을 정리해보도록 하겠습니다.


작동 방식

-필요로 하는 UV 또는 데이터를 입력으로 받는 '표면 함수'를 정의한다.

-이 함수에 사용할 출력 구조를 결정한다. (구조 : SurfaceOutput, SurfaceOutputStandard, SurfaceOutputStandardSpecular)

-SubShader 블록 안에 CGPROGRAM .. ENDCG에 셰이더 코드를 위치시킨다.

-#pragma surface ... 지시자를 사용하여 Surface Shader임을 나타낸다.

파라미터

1. 필수 파라미터

-필수 파라미터는 #pragma surface 선언 뒤에 순서대로 위치시켜야 한다.

-Cg함수 : 표면 셰이더 코드가 있는 함수로, voud surf(Input IN, inout 출력구조 o)형식을 가진다.

-lightModel : 사용할 조명 모델으로, 미리 정의된 조명 모델이나 커스텀 조명 모델을 만들어 사용할 수 있다. 미리 정의된 조명 모델로는 'Standard, StandardSpecular, Lambert, BlinnPhong'이 있다.

필수 파라미터 예시

#pragma surface surf Test
//surf는 우리가 사용할 cg함수의 이름
//Test는 우리가 사용할 lightModel의 이름. 미리 정의된 이름이 아닌 커스텀 조명 모델

struct Input{ // surf(cg) 함수에서 사용할 변수들을 선언함
//사용할 내부 변수 목록
//글 하단에서 자세한 설명!
}

void surf(Input IN, inout SurfaceOutput o){
//cg함수
//위 Input 구조체에서 선언한 변수 목록을 사용
//SurfaceOutput 출력 구조를 사용
}

float4 LightingTest ( SurfaceOutput s, float3 lightDir, float3 viewDir, float atten){
//사용할 lightModel 함수
//라이트모델은 Lighting + '함수명' + 추가옵션 의 구조를 가짐
//이 예시에서는 #pragma에서 lightModel 함수 이름으로 'Test'를 선언함
//surf함수와 마찬가지로 SurfaceOutput 출력 구조를 사용
}

 

2. 선택 파라미터 - 알파

오브젝트의 알파값을 통해 투명도를 결정하는 알파와, 일정 알파값 이하는 이미지를 잘라버리는 알파 테스트는 alpha 및 alphatest 지시문에 의해 제어됩니다. 반투명도를 활성화하면 생성된 표면(Surface)셰이더 코드에 블렌딩 커맨드가 포함되며, 알파 컷아웃을 활성화하면 주어진 변수(값)에 따라 생성된 픽셀 셰이더에서 프래그먼트를 폐기합니다.

-alpha or aplha:auto - 일반적인 조명 함수에 대해서는 알파 블렌딩 효과(alpha:fade), 물리 기반 조명 함수에서는 프리멀티드 블렌딩(alpha:premul)

-alpha:blend - 알파 블렌딩

-alpha:fade - 전통적인 반투명(알파 블렌딩)

-alpha:premul - 프리멀티드 블렌딩 (유리처럼 반투명 표면에서도 반사를 유지할 수 있음)

-alphatest:variableName - 알파 컷아웃 반투명(알파 테스팅)을 만듬. 컷오프되는 값은 변수명으로 지정될 float 변수에 해당되는 수치로 지정됨

-keepalpha - 기본적으로 불투명한 서피드 쉐이더는 조명과 관계없이 알파 채널에 1.0값을 사용하지만, 이 옵션을 사용하면 불투명한 표면 쉐이더에서도 조명 함수의 알파 값을 유지할 수 있음

3. 선택 파라미터 - 커스텀 함수

-vertex:VertexFunction - 커스텀 버텍스 수정 기능. 버텍스 쉐이더가 시작될 때 호출되며, 버텍스 별 데이터를 수정하거나 계산가능

-Finalcolor:ColorFunction - 사용자 정의의 최종 색상 수정자

-Finalgbuffer:ColorFunction - G버퍼를 수정하기 위한 커스텀 디퍼드 패스

-Finalprepass:ColorFuntion - Deferred 렌더링을 위한 커스텀 프리패스 경로

4. 선택 파라미터 - 그림자

-addshadow - 쉐도우 캐스터 패스 추가

-Fullforwardshadows - 포워드 렌더링 패스에서 모든 조명에서 그림자가 생기게 할 때 사용되는 구문. 기본적으로 쉐이더에서는 포워드 렌더링에서 디렉셔널 라이트에 의한 그림자만 생성함. 포워드 렌더링에서 포인트나 스팟 라이트의 그림자가 필요하다면 이 구문을 사용

5. 선택 파라미터 - 코드 생성 옵션

셰이더의 최적화를 위해 필요 없는 시나리오를 건너뛰어 불필요한 연산을 줄일 수 있는 구문

- exclude_path:deferred, exclude_path:forward, exclude_path:prepass - 주어진 렌더링 경로에 대해 패스를 생성하지 않습니다(순서대로 디퍼드 셰이딩, 포워드, 레거시 디퍼드입니다).

- noshadow - 이 셰이더에서 모든 섀도우 리시브 지원을 비활성화합니다.

- noambient - 주변광 또는 라이트 프로브를 적용하지 않습니다.

- novertexlights - 포워드 렌더링에서 모든 라이트 프로브 또는 버텍스당 광원을 적용하지 않습니다.

- nolightmap - 이 셰이더에서 모든 라이트매핑 지원을 비활성화합니다.

- nodynlightmap - 이 셰이더에서 런타임 동적 전역 조명 지원을 비활성화합니다.

- nodirlightmap - 이 셰이더에서 모든 직접광 라이트맵 지원을 비활성화합니다.

- nofog - 모든 내장형 안개 지원을 비활성화합니다.

- nometa - “메타” 패스를 생성하지 않습니다(표면 정보를 추출하기 위해 라이트매핑 및 동적 전역 조명에서 사용함).

- noforwardadd - 포워드 렌더링 추가 패스를 비활성화합니다. 이렇게 하면 셰이더는 하나의 전체 방향 광원을 지원하고 다른 모든 광원은 버텍스/SH당으로 계산됩니다. 셰이더 크기도 작아집니다.

- nolppv - 이 셰이더에서 라이트 프로브 프록시 영역 지원을 비활성화합니다.

- noshadowmask - 이 셰이더에 대한 섀도우 마스크 지원을 비활성화합니다(섀도우 마스크 및 디스턴스 섀도우 마스크).

선택 파라미터 예시

#pragma surface surf Nolight vertex:vert alphatest:_Cutoff noshadow noambient
//surface 구문으로 surface Shader 사용
//cg함수인 surf 선언
//커스텀 라이팅모델인 Nolight 선언
//커스텀 버텍스 함수인 vert 선언
//alphatest:variableName 구문으로 '_Cutoff' 값에 따라 알파테스트를 실시
//코드 생성 옵션에서 noshadow와 noambient구문으로 새도우 리시브와 환경광 비활성화

 

Surface Shader의 Input 구조체

위 필수 파라미터 예시에서 본 Input 구조체에 대한 설명입니다. 입력 구조체 Input에는 일반적으로 셰이더가 필요로 하는 텍스처 좌표가 있습니다. 텍스처 좌표의 이름은 텍스처 이름 앞에 'uv'가 붙는 형식으로 지어야 합니다. 그 외 이 구조체에 추가적으로 입력되는 값은 다음과 같습니다.

-float3 viewDir - 카메라가 바라보는 뷰 방향

-float4 color:COLOR - 보간된 버텍스 컬러

-float4 screenPos - 스크린 스페이스 위치. GrabPass에는 적합하지 않음

-float3 worldPos - 월드 공간 포지션을 포함

-float3 worldRefl - 서피스 셰이더에서 o.Normal에 기록하지 않는 경우 월드 반사 벡터를 포함

-float3 worldNormal - 서피스 셰이더가 o.Normal에 기록하지 않는 경우 월드 노멀 벡터를 포함

-float3 worldRefl; INTERNAL_DATA - 서피스 셰이더가 o.Normal에 기록하는 경우 월드 반사 벡터를 포함. 픽셀당 노멀 맵을 기반으로 반사 벡터를 얻으려면 WorldReflectionVector (IN, o.Normal)를 사용해야 함

float3 worldNormal; INTERNAL_DATA - 서피스 셰이더가 o.Normal에 기록하는 경우 월드 노멀 벡터를 포함. 픽셀당 노멀 맵에 기반한 노멀 벡터를 얻으려면 WorldNormalVector (IN, o.Normal)를 사용해야 함

Input 예시

 struct Input
        {
            // 텍스처 좌표 (uv_텍스처 이름)
            float2 uv_MainTex;
            float2 uv_BumpMap;
            // o.Normal에 기록하는 경우 월드 노멀 벡터
            float3 worldNormal;
            INTERNAL_DATA
        };

 

참고자료

 

표면 셰이더 작성 - Unity 매뉴얼

조명과 상호작용하는 셰이더를 작성하는 일은 복잡합니다. 여러 광원 타입, 여러 섀도우 옵션, 여러 렌더링 경로(포워드 및 디퍼드 렌더링)는 이 복잡한 것을 처리할 수 있습니다.

docs.unity3d.com

 

반응형