본문 바로가기

유니티/쉐이더

[Unity Shader] 외곽선 만들기 : Pass 추가, Vertex Shader, zwrite

완성 결과

Pass

Pass는 오브젝트 렌더링 단위로 Pass 수만큼 오브젝트를 그려줍니다.

pass추가

Standard Surface Shader를 만들고 다음과 같이 수정했습니다.

CGPROGRAM ~ ENDCG 부분을 추가해주면 Pass가 추가됩니다.

똑같이 2번 그린 것이기 때문에 변화는 없습니다.


Vertex Shader

Surface Shader는 색을 제어하고 Vertex Shader는 말그대로 vertex(정점)를 제어할 수 있습니다.

vertex shader 추가

- #pragmavertex:(함수 이름)을 작성합니다.

- void (함수이름) (inout appdata_full v)함수를 작성합니다.

 

appdata full 구조체

  • float4 vertex : POSITION;
  • float4 tangent : TANGENT;     //접선 방향
  • float3 normal : NORMAL;
  • float4 texcoord : TEXCOORD0;     //첫 번째 UV 좌표
  • float4 texcoord1 : TEXCOORD1; 
  • float4 texcoord2 : TEXCOORD2;
  • float4 texcoord3 : TEXCOORD3; 
  • fixed4 color : COLOR;     //버텍스 컬러

appdata_base : position, normal, texcoord

appdata_tan : position, tangent, normal, texcoord

appdata_full : position, tangent, normal, texcoord, texcoord1, texcoord2, texcoord3


외곽선 생성


코드 설명

cull front : 뒷면만 렌더링 합니다. (2번째 pass에서 앞면렌더링 //cull back 추가

vert 함수 : vertex를 normal 방향으로 확장시켜줍니다.


단순히 검은색으로 만들기 때문에 가장 단순한 라이팅 구조로 만들고 surf함수를 비웠습니다.

Input 구조체에 값을 받지 않으면 오류가 나기 때문에 의미없는 값을 넣었습니다.


필요없는 환경광과 그림자를 없애줍니다.

 


외곽선 정리

바깥쪽에 있는 외곽선만 그리게 바꿔줍니다.

※여기서부터는 이것저것 해보다가 된거라서 실제 적용해도 문제없는지는 모르겠습니다.

 

zwrite를 off 하면 zbuffer에 깊이값을 기록하지 않습니다. 

zbuffer는 깊이값을 0.0~1.0으로 기록한다. (카메라와 가장 가까우면 0.0, 가장 멀리있으면 1.0)


문제점

zwrite를 off로 하면 zbuffer에 1로 기록된다.

가장 멀리 있다고 판단하여 다른오브젝트에 가려지면 외곽선이 그려지지 않는다.


수정

RenderType QueueTransparent로 바꿔준다.


굵기, 색 추가

굵기와 색을 변경할 수 있게 코드를 추가해줍니다.

텍스쳐를 입혀주고 색, 굵기를 조정하면 완성!

 


완성 코드

Shader "Custom/OutLine"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _OutLineColor("OutLine Color", Color) = (0,0,0,0)
        _OutLineWidth("OutLine Width", Range(0.001, 0.01)) = 0.01
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" "Queue" = "Transparent"}
        LOD 200

        cull front
        zwrite off
        CGPROGRAM
        #pragma surface surf NoLight vertex:vert noshadow noambient
        #pragma target 3.0

        float4 _OutLineColor;
        float _OutLineWidth;

        void vert(inout appdata_full v) {
            v.vertex.xyz += v.normal.xyz * _OutLineWidth;
        }

        struct Input
        {
            float4 color;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {

        }

        float4 LightingNoLight(SurfaceOutput s, float3 lightDir, float atten) {
            return float4(_OutLineColor.rgb, 1);
        }
        ENDCG

        cull back
        zwrite on
        CGPROGRAM
        #pragma surface surf Lambert
        #pragma target 3.0

        sampler2D _MainTex;
        struct Input
        {
            float2 uv_MainTex;
        };

        void surf(Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}