Version: 5.6
셰이더 레퍼런스
표면 셰이더 예제

표면 셰이더 작성

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

Unity의 Surface Shader 는 로우레벨 버텍스/픽셀 셰이더 프로그램을 사용하는 것에 비해 릿 셰이더 작성을 훨씬 쉽게 만들어주는 코드 생성 방법입니다. 표면 셰이더에는 어떠한 커스텀 언어나 마법 따위도 없다는 점을 기억해야 합니다. 표면 셰이더는 단지 손으로 일일이 작성했어야 할 모든 반복적 코드를 대신 생성해 줄 뿐입니다. 셰이더 코드는 여전히 HLSL로 직접 작성해야 합니다.

예제를 살펴보려면 표면 셰이더 예제표면 셰이더 커스텀 조명 예제를 참조하십시오.

작동 방식

우선 필요로 하는 UV 또는 데이터를 입력으로 받는 “표면 함수”를 정의합니다. 그리고 출력 구조 SurfaceOutput을 채워 넣습니다. SurfaceOutput은 기본적으로 _표면의 프로퍼티_를 기술합니다(알베도 컬러, 노멀, 이미션, 반사도 등). 이 코드는 HLSL로 작성합니다.

그 다음 어떤 입력이 필요한지, 어떤 출력이 채워졌는지 등을 표면 셰이더 컴파일러가 알아내고, 실제 버텍스/픽셀 셰이더 및 포워드/디퍼드 렌더링을 처리할 렌더링 패스를 생성합니다.

표면 셰이더의 표준 출력 구조는 다음과 같습니다.

struct SurfaceOutput
{
    fixed3 Albedo;  // diffuse color
    fixed3 Normal;  // tangent space normal, if written
    fixed3 Emission;
    half Specular;  // specular power in 0..1 range
    fixed Gloss;    // specular intensity
    fixed Alpha;    // alpha for transparencies
};

Unity 5에서 표면 셰이더는 물리 기반 조명 모델을 사용할 수도 있습니다. 내장된 Standard 및 StandardSpecular 조명 모델(아래 참조)은 각각 아래와 같은 출력 구조를 사용합니다.

struct SurfaceOutputStandard
{
    fixed3 Albedo;      // base (diffuse or specular) color
    fixed3 Normal;      // tangent space normal, if written
    half3 Emission;
    half Metallic;      // 0=non-metal, 1=metal
    half Smoothness;    // 0=rough, 1=smooth
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // alpha for transparencies
};
struct SurfaceOutputStandardSpecular
{
    fixed3 Albedo;      // diffuse color
    fixed3 Specular;    // specular color
    fixed3 Normal;      // tangent space normal, if written
    half3 Emission;
    half Smoothness;    // 0=rough, 1=smooth
    half Occlusion;     // occlusion (default 1)
    fixed Alpha;        // alpha for transparencies
};

샘플

표면 셰이더 예제, 표면 셰이더 커스텀 조명 예제표면 셰이더 테셀레이션 페이지를 참조하십시오.

표면 셰이더 컴파일 지시자

다른 셰이더와 마찬가지로 표면 셰이더는 CGPROGRAM..ENDCG 내에 위치합니다. 차이는 다음과 같습니다.

  • Pass 대신 SubShader 블록 안에 위치해야 합니다. 표면 셰이더는 멀티플 패스로 컴파일됩니다.
  • #pragma surface ... 지시자를 사용하여 표면 셰이더임을 나타냅니다.

#pragma surface 지시자는 다음과 같습니다.

# pragma surface surfaceFunction lightModel [optionalparams]

필요한 파라미터

  • surfaceFunction - 표면 셰이더 코드가 있는 Cg 함수. 이 함수는 void surf (Input IN, inout SurfaceOutput o)의 형식이어야 하며, 여기에서 Input은 사용자가 정의한 구조입니다. Input에는 표면 함수에 요구되는 추가 자동 변수 및 텍스처 좌표를 포함해야 합니다.
  • lightModel - 사용할 조명 모델. 빌트인 모델은 물리 기반의 StandardStandardSpecular, 물리 기반이 아닌 단순한 Lambert (디퓨즈) 및 BlinnPhong (스페큘러)입니다. 직접 조명 모델을 작성하는 방법에 대해서는 커스텀 조명 모델 페이지를 참조하십시오.
    • Standard 조명 모델은 SurfaceOutputStandard 출력 구조를 사용하며 Unity의 표준(메탈릭 워크플로) 셰이더에 매치됩니다.
    • StandardSpecular 조명 모델은 SurfaceOutputStandardSpecular 출력 구조를 사용하며 Unity의 표준(스페큘러 셋업) 셰이더와 매치됩니다.
    • LambertBlinnPhong 조명 모델은 물리 기반이 아닙니다(Unity 4.x부터 제공). 그러나 이 모델을 사용하는 셰이더는 로우엔드 하드웨어에서 렌더링 시 더 빠를 수 있습니다.

선택적 파라미터

투명도 및 알파 테스트alphaalphatest 지시문에 의해 제어됩니다. 투명도는 일반적으로 두 종류가 있으며, 오브젝트의 페이드아웃에 사용하는 기존 알파 블렌딩과 물리적으로 보다 그럴 듯한 “미리 곱해진 블렌딩”(반투명한 표면을 허용하여 적절한 스페큘러 반사를 유지)입니다. 반투명도를 활성화하면 생성된 표면 셰이더 코드에 블렌딩 커맨드가 포함되며, 알파 컷아웃을 활성화하면 주어진 변수에 따라 생성된 픽셀 셰이더에서 프래그먼트를 폐기합니다.

  • alpha 또는 alpha:auto - 단순 조명 함수용으로 페이드-투명도(alpha:fade와 동일)를, 물리 기반 조명 함수용으로 미리 곱해진 투명도(alpha:premul과 동일)를 선택합니다.
  • alpha:blend - 알파 블렌딩을 사용합니다.
  • alpha:fade - 전통적인 페이드-투명도를 사용합니다.
  • alpha:premul - 미리 곱해진 알파 투명도를 사용합니다.
  • alphatest:VariableName - 알파 컷아웃 투명도를 사용합니다. 컷오프 값은 VariableName이라는 플로트형 변수에 있습니다. 또한 addshadow 지시자를 사용하면 적절한 섀도우 캐스터 패스를 생성할 수 있습니다.
  • keepalpha - 디폴트로 불투명 표면 셰이더는 출력 구조의 Alpha 안의 출력이 무엇이건, 또는 조명 함수가 무엇을 반환하건 간에 1.0(흰색)을 알파 채널에 씁니다. 이 옵션을 사용하면 불투명 표면 셰이더에도 조명 함수의 알파 값을 유지할 수 있습니다.
  • decal:add - 추가 데칼 셰이더(예: 터레인 AddPass)입니다. 이 셰이더는 다른 표면 위에 놓이는 오브젝트에 사용하기 위한 것으로 추가 블렌딩을 사용합니다. 표면 셰이더 예제를 참조하십시오.
  • decal:blend - 반투명 데칼 셰이더입니다. 이 셰이더는 다른 표면 위에 놓이는 오브젝트에 사용하기 위한 것으로 알파 블렌딩을 사용합니다. 표면 셰이더 예제를 참조하십시오.

커스텀 수정 함수는 인입되는 버텍스 데이터를 변경 또는 계산하거나, 계산된 최종 프래그먼트 컬러를 변경할 때 사용할 수 있습니다.

  • vertex:VertexFunction - 커스텀 버텍스 수정 함수입니다. 이 함수는 생성된 버텍스 셰이더가 시작될 때 호출되며 버텍스당 데이터를 수정 또는 계산할 수 있습니다. 표면 셰이더 예제를 참조하십시오.
  • finalcolor:ColorFunction - 커스텀 최종 컬러 수정 함수입니다. 표면 셰이더 예제를 참조하십시오.
  • finalgbuffer:ColorFunction - gbuffer 콘텐츠를 변경하기 위한 커스텀 디퍼드 경로입니다.
  • finalprepass:ColorFunction - 커스텀 프리패스 베이스 경로입니다.

섀도우 및 테셀레이션 - 추가 지시자를 통해 섀도우 및 테셀레이션을 처리하는 방법을 제어할 수 있습니다.

  • addshadow - 섀도우 캐스터 패스를 생성합니다. 일반적으로 커스텀 버텍스 수정에 사용하여 섀도우 캐스팅이 순차적 버텍스 애니메이션이 되도록 합니다. 때로는 셰이더가 폴백(fallback)에서 섀도우 캐스터 패스를 사용할 수 있기 때문에 별도로 섀도우 처리가 전혀 필요하지 않을 경우도 있습니다.
  • fullforwardshadows - 모든 광원 섀도우 타입을 포워드 렌더링 경로에서 지원합니다. 기본적으로 셰이더는 포워드 렌더링에서 하나의 방향 광원으로부터 만들어진 섀도우만을 지원합니다(내부 셰이더 배리언트 카운트를 절약하기 위해). 포워드 렌더링에서 포인트 또는 스폿 광원 섀도우가 필요하면 이 지시자를 사용해야 합니다.
  • tessellate:TessFunction - DX11 GPU 테셀레이션을 사용합니다. 이 함수는 테셀레이션 팩터를 계산합니다. 자세한 내용은 표면 셰이더 테셀레이션을 참조하십시오.

코드 생성 옵션 - 디폴트로 생성된 표면 셰이더 코드가 가능한 모든 조명/섀도우/라이트맵 시나리오를 처리하려고 하나 이러한 시나리오 중 일부는 필요 없는 경우가 있습니다. 또한 생성된 코드를 조정하여 일부 시나리오를 건너뛸 수도 있습니다. 이렇게 하면 로드 시간이 짧은 작은 셰이더가 사용됩니다.

  • exclude_path:deferred, exclude_path:forward, exclude_path:prepass - 주어진 렌더링 경로에 대해 패스를 생성하지 않습니다(순서대로 디퍼드 셰이딩, 포워드, 레거시 디퍼드입니다).
  • noshadow - 이 셰이더에서 모든 섀도우 리시브 지원을 비활성화합니다.
  • noambient - 주변광 또는 라이트 프로브를 적용하지 않습니다.
  • novertexlights - 포워드 렌더링에서 모든 라이트 프로브 또는 버텍스당 광원을 적용하지 않습니다.
  • nolightmap - 이 셰이더에서 모든 라이트매핑 지원을 비활성화합니다.
  • nodynlightmap - 이 셰이더에서 런타임 동적 전역 조명 지원을 비활성화합니다.
  • nodirlightmap - 이 셰이더에서 모든 직접광 라이트맵 지원을 비활성화합니다.
  • nofog - 모든 내장형 안개 지원을 비활성화합니다.
  • nometa - “메타” 패스를 생성하지 않습니다(표면 정보를 추출하기 위해 라이트매핑 및 동적 전역 조명에서 사용함).
  • noforwardadd - 포워드 렌더링 추가 패스를 비활성화합니다. 이렇게 하면 셰이더는 하나의 전체 방향 광원을 지원하고 다른 모든 광원은 버텍스/SH당으로 계산됩니다. 셰이더 크기도 작아집니다.
  • nolppv - 이 셰이더에서 라이트 프로브 프록시 영역 지원을 비활성화합니다.
  • noshadowmask - 이 셰이더에 대한 섀도우 마스크 지원을 비활성화합니다(섀도우 마스크디스턴스 섀도우 마스크).

기타 옵션

  • softvegetation - 소프트 베지테이션이 켜져 있을 경우에만 표면 셰이더가 렌더링되도록 합니다.
  • interpolateview - 픽셀 셰이더 대신 버텍스 셰이더상 뷰 방향을 계산하고 보간합니다. 이렇게 하면 픽셀 셰이더 속도가 빨라지지만 텍스처 인터폴레이터를 하나 더 사용하게 됩니다.
  • halfasview - 뷰-방향 대신 하프-디렉션 벡터를 조명 함수에 넘깁니다. 하프-디렉션은 버텍스마다 계산 및 정규화됩니다. 속도가 더 빠르지만 아주 정확하지는 않습니다.
  • approxview - Unity 5.0에서 제거되었습니다. interpolateview를 대신 사용해야 합니다.
  • dualforward - 포워드 렌더링 경로에서 듀얼 라이트맵을 사용합니다.

위의 옵션을 사용했을 때 어떤 점이 정확히 다른지 알아보려면 셰이더 인스펙터의 “생성된 코드 보기” 버튼을 사용하면 됩니다.

표면 셰이더 입력 구조

입력 구조 Input에는 일반적으로 셰이더가 필요로 하는 텍스처 좌표가 있습니다. 텍스처 좌표의 이름은 텍스처 이름 앞에 “uv”가 붙는 형식으로 지어야 합니다(또는 두 번째 텍스처 좌표 세트를 사용하려면 “uv2”로 시작해야 합니다).

다음 값을 입력 구조에 추가할 수 있습니다.

  • float3 viewDir - 뷰 방향을 포함합니다. 패럴랙스 이펙트, 림 조명 등의 컴퓨팅에 사용합니다.
  • float4COLOR 시맨틱 - 보간된 버텍스당 컬러를 포함합니다.
  • float4 screenPos - 반사 또는 스크린 공간 효과를 위한 스크린 공간 포지션을 포함합니다. GrabPass에는 적합하지 않습니다. ComputeGrabScreenPos 함수를 사용하여 커스텀 UV를 직접 계산해야 합니다.
  • float3 worldPos - 월드 공간 포지션을 포함합니다.
  • float3 worldRefl - 표면 셰이더가 o.Normal에 기록하지 않는 경우 월드 반사 벡터를 포함합니다. 예를 들어 리플렉트-디퓨즈(Reflect-Diffuse) 셰이더가 있습니다.
  • float3 worldNormal - 표면 셰이더가 o.Normal에 기록하지 않는 경우 월드 노멀 벡터를 포함합니다.
  • float3 worldRefl; INTERNAL_DATA - 표면 셰이더가 o.Normal에 기록하는 경우 월드 반사 벡터를 포함합니다. 픽셀당 노멀 맵을 기반으로 반사 벡터를 얻으려면 WorldReflectionVector (IN, o.Normal)를 사용해야 합니다. 예를 들어 리플렉트-범프드(Reflect-Bumped) 셰이더가 있습니다.
  • float3 worldNormal; INTERNAL_DATA - 표면 셰이더가 o.Normal에 기록하는 경우 월드 노멀 벡터를 포함합니다. 픽셀당 노멀 맵에 기반한 노멀 벡터를 얻으려면 WorldNormalVector (IN, o.Normal)를 사용해야 합니다.

표면 셰이더 및 DirectX 11 HLSL 구문

현재 표면 셰이더 컴파일 파이프라인의 일부분은 DirectX 11별 HLSL 구문을 인식하지 못합니다. StructuredBuffers, RWTextures 및 다른 비DX9 구문 등의 HLSL 기능을 사용하는 경우 DX–11 전용 전처리기 매크로로 래핑해야 합니다.

자세한 내용은 플랫폼 별 차이셰이딩 언어 페이지를 참조하십시오.


셰이더 레퍼런스
표면 셰이더 예제