유니티 셰이더 기초 가이드

본 가이드는 유니티 셰이더의 기본 개념, 생성 및 사용 방법, 그리고 간단한 예제를 통해 셰이더 개발에 대한 이해를 돕습니다.

셰이더란 무엇인가?

셰이더는 그래픽 렌더링에서 오브젝트 표면의 외관을 정의하는 프로그램입니다. 이는 GPU가 조명, 색상, 텍스처 정보를 어떻게 처리할지 지시합니다. 셰이더는 일반적으로 두 가지 유형으로 나뉩니다:

  1. 버텍스 셰이더(Vertex Shader): 각 정점의 속성(위치, 법선, 텍스처 좌표 등)을 처리합니다.
  2. 프래그먼트 셰이더(Fragment Shader): 각 픽셀의 색상과 다른 속성을 처리합니다.

유니티의 셰이더 유형

유니티에서 일반적으로 사용되는 셰이더 유형은 다음과 같습니다:

  • 표면 셰이더(Surface Shader): 조명과 그림자 처리를 단순화하며, 대부분의 일반적인 재질에 적합합니다.
  • 언리트 셰이더(Unlit Shader): 조영 영향을 받지 않아 2D 그래픽이나 특효과에 적합합니다.
  • 버텍스/프래그먼트 셰이더(Vertex/Fragment Shader): 렌더링 과정을 완전히 제어할 수 있는 높은 유연성을 제공합니다.

간단한 셰이더 생성하기

다음은 조명 영향을 받지 않는 색상을 표시하는 간단한 언리트 셰이더 예제입니다.

1. 셰이더 생성
  1. 유니티 프로젝트 창에서 마우스 오른쪽 버튼을 클릭하고 Create > Shader > Unlit Shader를 선택합니다.
  2. 새로 생성된 셰이더를 BasicUnlitShader로 이름 지정합니다.
2. 셰이더 편집

BasicUnlitShader를 더블클릭하여 열고 다음 코드로 내용을 교체합니다:

Shader "Examples/BasicUnlitShader"
{
    Properties
    {
        _BaseColor ("Base Color", Color) = (1,1,1,1) // 색상 속성 정의
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vertexProcess
            #pragma fragment pixelProcess

            struct inputData
            {
                float4 vertex : POSITION; // 정점 위치
            };

            struct outputData
            {
                float4 screenPos : SV_POSITION; // 화면 공간 위치
            };

            fixed4 _BaseColor; // 색상 변수

            outputData vertexProcess (inputData v)
            {
                outputData o;
                o.screenPos = UnityObjectToClipPos(v.vertex); // 정점 위치를 클립 공간으로 변환
                return o;
            }

            fixed4 pixelProcess (outputData i) : SV_Target
            {
                return _BaseColor; // 색상 반환
            }
            ENDCG
        }
    }
}
3. 재질 생성
  1. 프로젝트 창에서 마우스 오른쪽 버튼을 클릭하고 Create > Material을 선택합니다.
  2. 새로 생성된 재질을 BasicUnlitMaterial로 이름 지정합니다.
  3. 재질의 Inspector 패널에서 Shader를 Examples/BasicUnlitShader로 설정합니다.
4. 재질 적용
  1. 장면에 3D 오브젝트(예: 큐브)를 생성합니다.
  2. BasicUnlitMaterial 재질을 큐브에 드래그 앤 드롭합니다.

표면 셰이더 사용하기

표면 셰이더는 유니티에서 일반적으로 사용되는 셰이더 유형으로 대부분의 재질에 적합합니다. 다음은 간단한 표면 셰이더 예제입니다:

1. 표면 셰이더 생성
  1. 프로젝트 창에서 마우스 오른쪽 버튼을 클릭하고 Create > Shader > Standard Surface Shader를 선택합니다.
  2. 새로 생성된 셰이더를 BasicSurfaceShader로 이름 지정합니다.
2. 셰이더 편집

BasicSurfaceShader를 더블클릭하여 열고 다음 코드로 내용을 교체합니다:

Shader "Examples/BasicSurfaceShader"
{
    Properties
    {
        _BaseTexture ("Base Texture", 2D) = "white" {} // 텍스처 속성 정의
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        // 표준 조명 모델 사용
        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _BaseTexture; // 텍스처 변수

        struct InputData
        {
            float2 uv_BaseTexture; // 텍스처 좌표
        };

        void surf (InputData IN, inout SurfaceOutput o)
        {
            fixed4 texColor = tex2D(_BaseTexture, IN.uv_BaseTexture); // 텍스처에서 색상 가져오기
            o.Albedo = texColor.rgb; // 표면 색상 설정
            o.Alpha = texColor.a; // 투명도 설정
        }
        ENDCG
    }
}
3. 재질 생성 및 적용
  1. 새로운 재질을 생성하고 BasicSurfaceMaterial로 이름 지정합니다.
  2. 재질의 Inspector 패널에서 Shader를 Examples/BasicSurfaceShader로 설정합니다.
  3. 재질을 장면의 오브젝트에 적용합니다.

셰이더 구조와 구문

유니티 셰이더는 일반적으로 다음과 같은 부분으로 구성됩니다:

  • 셰이더 선언: 셰이더의 이름과 유형을 정의합니다.
  • 속성(Properties): Inspector 패널에서 조절할 수 있는 속성(색상, 텍스처 등)을 정의합니다.
  • 서브셰이더(SubShader): 하나 이상의 렌더링 패스(Pass)를 포함하며, 오브젝트를 어떻게 렌더링할지 정의합니다.
  • 패스(Pass): 각 패스는 버텍스와 프래그먼트 셰이더 코드를 포함합니다.
예제 구조
Shader "Examples/MyShader"
{
    Properties
    {
        _BaseColor ("Base Color", Color) = (1,1,1,1)
        _BaseTexture ("Base Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        Pass
        {
            CGPROGRAM
            // 셰이더 코드
            ENDCG
        }
    }
}

일반적인 셰이더 특징

색상과 텍스처
  • 색상: fixed4 유형의 변수로 색상 속성을 정의할 수 있습니다.
  • 텍스처: samp2D 유형의 변수로 텍스처 속성을 정의하고, 프래그먼트 셰이더에서 tex2D 함수를 사용하여 샘플링합니다.
법선과 조명
  • 법선: 법선 정보를 전달하여 조명 효과를 구현할 수 있습니다.
  • 조명: 다양한 조명 모델(예: Lambert, Blinn-Phong 등)을 사용하여 조명 효과를 계산할 수 있습니다.

셰이더의 텍스처와 UV 매핑

텍스처

텍스처는 오브젝트 표면에 디테일을 추가하는 이미지 데이터입니다. 셰이더는 다양한 유형의 텍스처를 사용할 수 있습니다:

  • 2D 텍스처: 가장 일반적으로 사용되는 텍스처 유형입니다.
  • 큐브 맵 텍스처: 환경 매핑과 반사 효과에 사용됩니다.
  • 3D 텍스처: 볼륨 효과에 사용됩니다.
UV 매핑

UV 좌표는 텍스처를 오브젝트 표면에 매핑하는 데 사용됩니다. 일반적으로 버텍스 셰이더에서 UV 좌표를 프래그먼트 셰이더로 전달합니다.

struct inputData
{
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0; // UV 좌표
};

struct outputData
{
    float4 screenPos : SV_POSITION;
    float2 uv : TEXCOORD0; // UV 좌표 전달
};

outputData vertexProcess (inputData v)
{
    outputData o;
    o.screenPos = UnityObjectToClipPos(v.vertex);
    o.uv = v.uv; // UV 좌표 전달
    return o;
}

조명 모델

유니티는 다양한 조명 모델을 지원하며, 다음은 일반적인 조명 모델입니다:

  • Lambert: 확산 조명에 사용되며 대부분의 표면에 적합합니다.
  • Blinn-Phong: 반사 고광에 사용되며 금속 및 매끄러운 표면에 적합합니다.
  • PBR(Physically Based Rendering): 물리 기반 렌더링으로 더 사실적인 재질 표현을 제공합니다.
예제: Lambert 조명 모델 사용
#pragma surface surf Lambert

셰이더 성능 최적화

셰이더 개발 시 성능은 중요한 고려 사항입니다. 다음은 최적화 팁입니다:

  • 텍스처 샘플링 감소: 텍스처 샘플링마다 계산 부하가 증가하므로 프래그먼트 셰이더에서 샘플링 횟수를 최소화합니다.
  • GPU 인스턴싱 사용: 동일한 오브젝트를 대량으로 렌더링할 때 GPU 인스턴싱을 사용하면 성능을 크게 향상시킬 수 있습니다.
  • 계산 단순화: 프래그먼트 셰이더에서 복잡한 계산을 피하고, 가능한 한 계산을 버텍스 셰이더로 이동시킵니다.
  • LOD(Level of Detail) 사용: 카메라 거리에 따라 다른 상세 수준의 모델을 사용하여 렌더링 부하를 줄입니다.

셰이더 그래프 사용

셰이더 그래프는 유니티가 제공하는 시각적 셰이더 편집 도구로, 개발자가 코드 작성 없이 노드 연결 방식으로 셰이더를 생성할 수 있게 합니다. 셰이더 그래프 사용 기본 단계는 다음과 같습니다:

1. 셰이더 그래프 생성
  1. 프로젝트 창에서 마우스 오른쪽 버튼을 클릭하고 Create > Shader > PBR Graph 또는 Unlit Graph을 선택합니다.
2. 셰이더 그래프 열기

생성된 셰이더 그래프 파일을 더블클릭하여 셰이더 그래프 편집기를 엽니다.

3. 노드 추가

셰이더 그래프에서 빈 영역을 마우스 오른쪽 버튼으로 클릭하여 노드를 추가할 수 있습니다. 예를 들어:

  • Texture 2D: 텍스처를 로드하는 데 사용됩니다.
  • Color: 색상을 정의하는 데 사용됩니다.
  • Math: 수학 연산을 수행하는 데 사용됩니다.
4. 노드 연결

노드의 출력을 다른 노드의 입력에 연결하여 셰이더 로직을 구성합니다.

5. 저장 및 적용

셰이더 그래프를 저장한 후, 새로운 재질을 생성하고 셰이더 그래프를 해당 재질에 할당한 다음, 재질을 장면의 오브젝트에 적용합니다.

태그: 유니티 셰이더 그래픽프로그래밍 게임개발 CG프로그래밍

6월 24일 03:56에 게시됨