목차

유니티셰이더의기초 1~6까지 따라하면서 정리한 것

ShaderLab : 기본형식

기본 형식

Shader "BasicShader" {
  SubShader {
    // Shaderlab code
  }
}

SubShader

개념상 (그럴걸이라고 믿고 가는) 지원 되는 디바이스 대응

Shader "BasicShader" {
  SubShader {
    // 매우 좋은 스펙 디바이스
  }
  SubShader {
    // 좋은 스펙 디바이스
  }
  SubShader {
    // 낮은 스펙 디바이스
  }
}

Fallback

Shader "BasicShader" {
  SubShader {
    // Shaderlab code
  }
  Fallback "Diffuse"
}

Pass

Shader "BasicShader" {
  SubShader {
    // Shaderlab code
    Pass {  }
    Pass {  }
  }
  Fallback "Diffuse"
}

ShaderLab 키워드

색 입히기

오브젝트를 퍼렇게 칠한다
Shader "Study/SolidBlue"
{
  SubShader {
    Pass {
      Color (0,0,1,1)
    }
  } 
}

재질과 조명추가

키워드

매트리얼 설정

셰이더의 목적은 재질과 라이팅에 반응되도록 하는 것이므로,

SubShader 의 Pass 내부에 Material 키워드로 조명 방식을 추가한다.

Material {
  Diffuse (0,0,1,1)
  Ambient (0,0,1,1)
}

라이팅추가

재질이 표시되려면 조명을 (재질은 조명을 받은 반응이므로) 추가하는데,

Lighting On

매트리얼, 조명 추가된 셰이더

Material, Lighting 키워드가 Pass 블럭 내부에 있다.

조명과 함께 퍼렇게 칠한다.
Shader "Study/VertexLitBlue"
{
  SubShader {
    Pass {
      Material {
        Diffuse (0,0,1,1)
        Ambient (0,0,1,1)
      }
      Lighting On
    }
  } 
}

Fixed Function Shader

클래식한 기능이지만, 셰이더 이전의 쓰던 기능은 다 되므로 은근히 막강.

참고 : Shaders: ShaderLab & Fixed Function shaders

프로퍼티

변수다,생각.
Material {
  Diffuse (0,0,1,1)
  Ambient (0,0,1,1)
}

위의 예제에서는 매트리얼에 값을 고정 값으로 설정 했는데, Properties 키워드와 구문 블럭 내부에, 변수 역할의 프로퍼티를 추가할 수 있다.
(유니티 인스펙터에 노출되는 그것들)

Diffuse와 Ambient에 대한 프로퍼티를 추가. 다른 색상을 지정하도록 코드를 변경.

재질 색상을 프로퍼티로 받아들인다.
Shader "Study/VertexLitBlue2"
{
  Properties {
    _DiffuseColor ("DiffuseColor", COLOR) = (0,0,1,1)
    _AmbientColor ("AmbientColor", COLOR) = (0,0,1,1)
  }
  SubShader {
    Pass {
      Material {
        Diffuse [_DiffuseColor]
        Ambient [_AmbientColor]
      }
      Lighting On
    }
  } 
}
_DiffuseColor ("DiffuseColor", COLOR) = (0,0,1,1)

사용 가능한 타입

SetTexutre

SetTexutre: 텍스쳐 프로퍼티

2D 프로퍼티로 텍스쳐를 설정해서 오브젝트에 입힐 수 있다.

텍스쳐를 입힌다.
Shader "Study/VertexLitTex"
{
    Properties {
        _DiffuseColor ("DiffuseColor", COLOR) = (0,0,1,1)
        _AmbientColor ("AmbientColor", COLOR) = (0,0,1,1)
        _MainTex ("MainTex", 2D) = "white"
    }
    SubShader {
        Pass {
            Material {
                Diffuse [_DiffuseColor]
                Ambient [_AmbientColor]
            }

            Lighting On

            SetTexture [_MainTex] 
        }
    } 
}
최초의 화면
텍스쳐를 등록한 후의 결과

위의 결과는, 텍스쳐를 오브젝트에 적용되었지만 라이팅 연산이 반영되지 않았다.

SetTexutre: 라이팅 연산 추가

SetTexture 구문을 확장해서 ( {, }를 추가한다 ) 텍스쳐 연산 방법을 추가한다.

SetTexture [_MainTex] { Combine texture * primary } 
Shader "Study/VertexLitTex2"
{
    Properties {
        _DiffuseColor ("DiffuseColor", COLOR) = (0,0,1,1)
        _AmbientColor ("AmbientColor", COLOR) = (0,0,1,1)
        _MainTex ("MainTex", 2D) = "white"
    }
    SubShader {
        Pass {
            Material {
                Diffuse [_DiffuseColor]
                Ambient [_AmbientColor]
            }
            Lighting On
            SetTexture [_MainTex] {
                Combine texture * primary
            }
        }
    } 
}

텍스쳐 색상(texture)과 이전 라이팅 계산 결과(primary)를 곱해서 화면에 표시한다.

Combine

Combine에 대한 온라인 도움말

Combine의 조합 방식

combine <src1> * <src2> 곱한다. 결과는 다소 어두워진다. 하지만 색상 결합의 기본은 곱이므로 이걸 사용한다.
(0.2 * 0.2 = 0.04) 색상이 점점 0(검정)에 가까워지므로.
하지만 1(white)로 곱하면 원래 색상이 나오므로.
combine <src1> + <src2> 더한다. 밝아진다.
점점 1에 가까워지니까.
combine <src1> - <src2> 빼는데.. 이건 좀 미묘.
combine <src1> +- <src2> src1을 src2에 더한 다음, 0.5를 뺀다. (signed add?)
combine <src1> lerp(<src2>) <src3> src2의 알파값으로 src1(=1)과 src3(=0)사이의 보간 값을 사용한다.
숫자 범위가 (1~0)임의 주의
combine <src1> * <src2> + <src3> src1.rgba * src2.a + src3 . 이건 뭘까..
combine <src1> * <src2> +- <src3> src1.rgba * src2.a + src3 - 0.5
combine <src1> * <src2> - <src3> src1(전체) * src2(알파값) - src3(전체)

src 프로퍼티는 아래 키워드로 변경 가능

combine <연산> <보정용 키워드>

src1 * src2 src1 + src2 src1 - src2

색상과 알파분리

combine src1 src2, color(alpha)

“,” 로 색상과 알파 부분을 분리.

  1. “src1 src2”에서는 원래 그대로 적용
  2. color(alpha)에서는 (1)번 연산에서 적용된 결과에 알파값을 적용

그외

SetTexutre: 두장의 텍스쳐

combine lerp 활용

텍스쳐만 표시되도록 재질 설정을 삭제하고 텍스쳐만 받는 셰이더 작성

Shader "Study/TwoTexture"
{
  Properties {
    _MainTex ("MainTex", 2D) = "white"
    _SubTex ("SubTex", 2D) = "white"
  }
  SubShader {
    Pass {
      SetTexture [_MainTex] 
      
      SetTexture [_SubTex] { Combine texture * previous }
    }
  } 
}

두번째 텍스쳐는 알파값이 있는 투명한 이미지인데, 투명 처리를 하지 않아서 그림이 깨져보인다.

combine lerp()로 알파를 반영 해본다.

// texture의 알파값으로 src1, src2의 비율을 조정한다. 알파가 1(not 투명) _SubTex값을 사용, 0에 가까워질수록 previous를 사용
SetTexture [_SubTex] {
  Combine texture lerp(texture) previous
}

셰이더 수정

Shader "Study/TwoTexture"
{
    Properties {
        _MainTex ("MainTex", 2D) = "white"
        _SubTex ("SubTex", 2D) = "white"
    }
    SubShader {
        Pass {
            SetTexture [_MainTex] 

            SetTexture [_SubTex] {
                Combine texture lerp(texture) previous
            }
        }
    } 
}

Blend

반투명 효과 같은, “색상섞은 후 효과”를 얻으려면 Blend 로 조합 방법을 적는다.

기본 포맷

Blend <SrcFactor> <DstFactor>
(새로 찍을 색상 값) SrcFactor * (기존 배경의 색상) DstColor

색상을 섞겠다는 뜻인데, SrcFactor와 DstFactor에는 블렌딩에 사용될 색상 속성(Blend Factor)을 지정해야 한다.

Blend SrcAlpha OneMinusSrcAlpha

원래 문서의 설명(이 명료해서)

이 경우에 만약 오브젝트의 알파값이 0.6 이라고 한다면, SrcAlpha = 0.6 이고 OneMinusSrcAlpha = 0.4 이므로 오브젝트 색상과 배경 색상은 60% 대 40% 비율로 섞여서 결국 오브젝트가 반투명하게 보이는 효과를 나타내는 것입니다.

0~1 사이의 색상이나 알파 값을 어디에서 가져올 것이냐에 대한 선택 구문

잡…

Blend SrcAlpha DstAlpha
이 경우, 둘다 0.6이면 어떻게 될려나. 최대값은 1이니까

구문의 위치

SubShader, Pass의 안쪽에 위치.

오브젝트를 반투명하게 표시

텍스쳐 두장만 표시하는 셰이더에, Blend를 넣어 봅니다.

Shader "Study/TransObject"
{
  Properties {
    _MainTex ("MainTex", 2D) = "white" {}
    _SubTex ("SubTex", 2D) = "white" {}
  }
  SubShader {
    Pass {
  
Blend SrcAlpha OneMinusSrcAlpha

      SetTexture [_MainTex] 
      SetTexture [_SubTex] { Combine texture lerp(texture) previous }
    }
  } 
}

Blend만 넣어서는 결과가 나오지 않음.

어느 정도의 알파값을 SrcAlpha로 지정할 것인지 정할 수 있는 코드를 넣어야 하는데, 색상값을 입력 받아
이 색상의 알파값을 최종 알파값으로 사용하도록 코드를 추가.

Shader "Study/TransObject"
{
  Properties {

_Alpha ("AlphaColor", COLOR) = (0,0,0,1)

    _MainTex ("MainTex", 2D) = "white" {}
    _SubTex ("SubTex", 2D) = "white" {}
  }
  SubShader {
    Pass {
  
Blend SrcAlpha OneMinusSrcAlpha

      SetTexture [_MainTex] 
      SetTexture [_SubTex] { 

ConstantColor[_Alpha]  
Combine texture lerp(texture) previous, constant

      }
    }
  } 
}

렌더링 큐를 설정하지 않는데도 앞뒤 제대로 나오니.. 쩝인데. 혹시 모르니,

오브젝트의 앞 뒤로 반투명하게 나와야 할게 제대로 나오지 않는다면 렌더링 큐 설정이 필요하다는 뜻.

Shader “Study/TransObject” {

Properties {
  _Alpha ("AlphaColor", COLOR) = (0,0,0,1)
  _MainTex ("MainTex", 2D) = "white" {}
  _SubTex ("SubTex", 2D) = "white" {}
}
SubShader {
  

Tags { “Queue” = “Transparent” }

  
  Pass {
    Blend SrcAlpha OneMinusSrcAlpha
    SetTexture [_MainTex] 
    SetTexture [_SubTex] { 
      ConstantColor[_Alpha]  
      Combine texture lerp(texture) previous, constant
    }
  }
} 

} </code>

렌더링 큐를 Transparent로 설정해서, Transparent 에 해당되는 녀석들이 그려질때 같이 그려지도록 설정한다.

렌더링 큐

오브젝트가 렌더링 되는 순서를 정할 수 있는데, 5단계가 기본이다.

키워드 숫자인덱스 설명
Background 1000 가장 먼저 그린다. 다른 것들에 가린다는 뜻
Geometry
기본값
2000 대부분 여기에 해당됨. 반투명 오브젝트 위주
AlphaTest 2450 반투명한 Geometry? 가 뭐지? 나무? 알파 테스트를 필요 있는 것.
Transparent 3000 투명한 (유리, 파티클) 오브젝트는 여기로 와야 함. 이게 거의 많이 쓰일 것 같은데..
Overlay 4000 가장 나중에 그리는데, 언제든 보이는 가장 앞에 있는 (렌즈플레어 같은) 오브젝트

렌더링 큐는 Tag 키워드로 입력하는데,

Tags = { "Queue" = "Transparent" }

또한 기본 키워드에 숫자를 더하거나 빼서 렌더링 순서를 임의 설정할 수 있다.

Tags = { "Queue" = "Geometry+1" }

색상

셰이더에서도 색상값은 (0~1) 사이의 값을 사용.

색상 연산

범위 값이, 0~1 사이 값인 것만 주의 하면 연산할때 도움이 된다.