[Toy Coding] Shader 입문

JongHyun Park·2020년 8월 18일
0

유니티는 어떻게 이미지를 렌더링할까?

렌더링 프로세스

Diagram from Alan Zucconi's "A Gentle Introduction To Shaders"

Shader란?

  • 셰이더는 렌더링 프로세스 중에 이용되는 프로그램이다. 적절한 빛과 색을 조절하는 게 목적인데, 포스트-프로세싱 레벨에선 특별한 효과를 만들어내는데에 사용되기도 한다.
  • 셰이더는 GPU가 계산할 것을 염두에 둔다. 그러니까 셰이더는 어떻게 내 3D Model을 그릴 것인지 결정하는 것이다.

Unity에서 Shader의 종류

  • Surface Shader
    - vertex나 pixel shader보다 쉽게 Shader 프로그래밍에 접근하도록 설계된 Shader.
    • 가장 일반적임
  • Unlit Shader
    - Unity의 Light와 상호작용하지 않는 Shader
    • 특수한 효과를 의도할 때 사용한다
  • Image Effect Shader
    - Post-Processing Effect에서 주로 사용된다.
    • 카메라가 렌더링한 이미지에 특수한 효과를 부여한다. (안개라던지, 카툰느낌이라던지)
  • Compute Shader
    - GPU에서 돌아가지만 일반적인 렌더링 파이프라인에서는 벗어난다.
    • GPGPU 알고리즘을 사용하거나 게임의 일부를 렌더링하는 속도를 올리는 데 사용할 수 있다.
    • 지금으로선 굉장히 복잡한 Shader

Shader 코드의 구조 (큰 범위에서 작은 범위로)

Shader 스크립트의 언어

  • Unity에서 Shader는 ShaderLab와 CG를 사용한다.
  • ShaderLab은 유니티에 어떻게 렌더링할 것인지 알려주는 역할을 한다.
  • CG가 이제 Shader Coding이라고 할 수 있다. CGPROGRAM과 ENDCG 사이에서 코딩을 하고 그 내용은 모두 GPU 레벨에서 계산된다.
  • Shader 스크립트는 크게 Properties와 SubShader로 나눠진다. Properties는 각종 변수를 선언, 저장하는 역할을 하고 유니티 엔진 내부에서 그 값을 지정할 수 있다. 실질적으로 어떻게 렌더링할지를 정하는 게 SubShader 안이다.
  • 일부 Shader를 보면 SubShader가 여러개 블록인 경우가 있는데, 이는 각 환경에 맞는 최적화 위해서다.

<Unity의 Unlit Shader>

Shader "Unlit/Hologram"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

위 코드를 살펴보면 vertex와 fragment라는 함수 두 개가 보인다. 이들의 구조는 다음 이미지와 같다.

  • vert 모델의 shape을 최적화해서 리턴한다.
  • frag는 vert에서 리턴한 shape에 따라서 적절한 색깔을 리턴한다.

0개의 댓글