Noraml Extrusion Shader

폴리곤의 노멀벡터 방향으로 버텍스를 확장시키는 간단한 기법

3D 모델을 좀 더 통통하게 할 때(혹은 반대로) 사용


-------------------------------------------------------------

   v.vertex.xyz += v.normal * _Amount;

-------------------------------------------------------------


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Shader "Custom/NormalExtrusion" 
{
    Properties 
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Amount ("Extrusion Amount", Range(-1.01.0)) = 0
    }
    
    SubShader 
    {
        Tags 
        { 
            "RenderType" = "Opaque" 
        }
    
        CGPROGRAM
        #pragma surface surf Lambert vertex:vert
        
        struct Input
        {
            float2 uv_MainTex;
        };
    
        float _Amount;
        
        void vert (inout appdata_full v)
        {
            v.vertex.xyz += v.normal * _Amount;
        }
    
        sampler2D _MainTex;
                
        void surf (Input IN, inout SurfaceOutput o)
        {
            o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
        }
        
        ENDCG
    } 
    FallBack "Diffuse"
cs


[ _Amount : 0 ]


[ _Amount : -0.2 ]


[ _Amount : 0.5 ]


'02.Development > Shader' 카테고리의 다른 글

[Shader] 셰이더 기초 (공유)  (1) 2016.02.04

출처 : http://kieuns.com/wiki/doku.php?id=language:shader:unity:shaderlab-basic#shaderlab



ShaderLab : 기본형식

  • Unity의 셰이더 작성용 ShaderLab 스크립트 언어.

기본 형식

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

SubShader

  • 한개의 Shader에 스크립트에, 여러개의 SubShader 작성.
  • 유니티 디바이스에 맞는 스크립트를 선택 사용.

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

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

Fallback

Shader "BasicShader" {
  SubShader {
    // Shaderlab code
  }
  Fallback "Diffuse"
}
  • 여러 SubShader조차 실패 하는 경우, Fallback에 정의된 쉐이더를 사용.

Pass

  • SubShader 내부에 정의(추가)
  • 오브젝트의 렌더링 단위.
  • SubShader 안의 Pass 수만큼 오브젝트에 셰이더 작업을 처리
  • 위의 것부터 순서대로 처리
Shader "BasicShader" {
  SubShader {
    // Shaderlab code
    Pass {  }
    Pass {  }
  }
  Fallback "Diffuse"
}

ShaderLab 키워드

색 입히기

오브젝트를 퍼렇게 칠한다
Shader "Study/SolidBlue"
{
  SubShader {
    Pass {
      Color (0,0,1,1)
    }
  } 
}
  • 오브젝트를 퍼렇게 칠한다.
  • 색상 정보만 있기 때문에, 색만 칠한다.
  • Color 키워드는 색상을 부여하는구나,라고 이해하고.

재질과 조명추가

키워드

  • Material
    • Diffuse, Ambient
  • Lighting

매트리얼 설정

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

  • 매트리얼과 조명 모델을 추가한다.

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

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

라이팅추가

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

  • 여기에서는 고정파이프라인을 사용하므로
  • 조명에 대한 전반 처리는 GPU에 미리 정의된 것을 사용
  • Lighting 키워드를 조명을 사용한다는 것을 명시
Lighting On

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

MaterialLighting 키워드가 Pass 블럭 내부에 있다.

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

Fixed Function Shader

  • VertexShader, PixelShader 이전에 사용되던 그래픽 파이프 라인.
  • 기능이 정해져 있어서, 단순 설정만으로도 동작된다.
  • Per-Vertex Lighting 만 사용.
  • 프로그래밍이 들어가지 않는다.(진짜?)

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

  • 활용은 개인기에 따라..

참고 : Shaders: ShaderLab & Fixed Function shaders

프로퍼티

변수다,생각.
  • 매트리얼의 Diffuse, Ambient에 적용할 색상을 “색상프로퍼티”로 받아 온다.
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)
  • _DiffuseColor : 셰이더에서 사용할 변수 이름
  • “DiffuseColor” : 인스펙터에서 보여질 이름
  • COLOR : 이 프로퍼티의 타입
  • (0,0,1,1) : 기본 값. 값을 변경하지 않는 경우 사용할 값.

사용 가능한 타입

  • name (“display name”, Range (min, max)) = number 
    : Defines a float property, represented as a slider from min to max in the inspector.
  • name (“display name”, Color) = (number,number,number,number) 
    : Defines a color property.
  • name (“display name”, 2D) = “name” { options } 
    : 2D texture 정의 프로퍼티
  • name (“display name”, Rect) = “name” { options } 
    : Defines a rectangle (non power of 2) texture property.
  • name (“display name”, Cube) = “name” { options } 
    : Defines a cubemap texture property.
  • name (“display name”, Float) = number 
    : Defines a float property.
  • name (“display name”, Vector) = (number,number,number,number) 
    : Defines a four component vector property.

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] 
        }
    } 
}
최초의 화면 
텍스쳐를 등록한 후의 결과 
  • SetTexture : 키워드로 텍스쳐를 지정한다.

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

SetTexutre: 라이팅 연산 추가

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

SetTexture [_MainTex] { Combine texture * primary } 
  • Combine : 텍스쳐에 다른 값과 연산( 곱)한다.
    • texture : Combine에 사용되는 키워드. 텍스쳐를 뜻함
    • primary : Combine 키워드가 호출되지 전까지의 계산 결과물.
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에 대한 온라인 도움말

  • 3개까지의 src1~src3 까지 사용가능한 듯
  • 가능한 연산
    • 곱/합/빼기

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 프로퍼티는 아래 키워드로 변경 가능

  • Texture : SetTexture [<텍스쳐 이름>]에서 지정한 텍스쳐. (SetTexture 구문에서 텍스쳐를 제어하려면 가리키는 키워드가 필요하잖아.)
  • Primary : 정점 색상을 사용한 라이팅 계산 결과. Material에 지정한 조명 모델에 대한 계산 결과.
  • Previous : 바로 직전까지 계산한 텍스쳐 연산 결과.
  • Constant : Constant is the color specified in ConstantColor

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

  • doublequad : combine 결과를 x2 또는 x4
    SetTexture [_MainTex] { Combine texture * primary DOUBLE }
  • src 프로퍼티에는 one - 옵션을 붙여서 반대값을 사용하게 할 수 있다.
  • src : src alphaalpha키워드를 붙어서 알파만 사용하게 할 수 있다.
src1 * src2src1 + src2src1 - src2

색상과 알파분리

combine src1 src2, color(alpha)

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

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

그외

  • ConstantColor color \\:Defines a constant color that can be used in the combine command.
  • matrix [MatrixPropertyName] \\: Transforms texture coordinates used in this command with the given matrix.

SetTexutre: 두장의 텍스쳐

combine lerp 활용

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

Shader "Study/TwoTexture"
{
  Properties {
    _MainTex ("MainTex", 2D) = "white"
    _SubTex ("SubTex", 2D) = "white"
  }
  SubShader {
    Pass {
      SetTexture [_MainTex] 
      
      SetTexture [_SubTex] { Combine texture * previous }
    }
  } 
}
 
  • primary 삭제 : primary를 넣으면, 연산된 라이팅 결과가 없기 때문에 검게 처리된다.
  • _MainTex 지정 후, 
    바로 _SubTex로 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% 비율로 섞여서 결국 오브젝트가 반투명하게 보이는 효과를 나타내는 것입니다.

 

 

  • Factor라는 것에 유의해야 하는데,
  • OneMinusAlpha는 원본 색상에서의 (1-Alpha)값을 배경색에 대한 알파값으로 적용하라는 뜻.

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

      }
    }
  } 
}
  • _Alpha라는 컬러 값을 받는 프로퍼티 추가
  • SubShader > Pass > 두번째 SetTexutre 에, ConstantColor 키워드로 색상 숫자값을 선언하고,
  • combine에서 텍스쳐 연산 이후에
  • 얼마나 알파 값을 적용할 것인지 _Alpha를 사용하도록 코드 추가

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

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

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단계가 기본이다.

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

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

  • SubShader에 위치할 수도 있고,
  • Pass 구문 안에도 넣을 수 있다.
Tags = { "Queue" = "Transparent" }

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

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

색상

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

  • 순서 : RGBA
  • Color( 1, 1, 1, 1 ) : Color ( <R>, <G>, <B>, <A> )

색상 연산

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

    • 큰수와 작은수를 곱하면 색상값이 더 작아지는데 조심. ( 0.1 * 0.01, 작아지지잖아 )
    • Pow 함수를 사용할때는 요 주의
    • 곱보다는 숫자 변화가 적지만
    • 더한다는건 더 흰색에 가까워진다는 뜻이므로



'02.Development > Shader' 카테고리의 다른 글

[Shader] Normal Extrusion Shader  (0) 2016.02.04

+ Recent posts