Notice
Recent Posts
Recent Comments
Link
«   2025/08   »
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
Archives
Today
Total
관리 메뉴

행복한 개구리

Unity Shader 21.05.07. 수업내용 - 외곽선 적용 본문

Unity/수업내용

Unity Shader 21.05.07. 수업내용 - 외곽선 적용

HappyFrog 2021. 5. 7. 13:20

월드좌표를 rgb로 변환해주면 이런식으로 좌표에 따라 색이 달라진다.
셋 다 섞어버리면 오른쪽 사진과 같은 쉐이더가 된다.

여기서 램버트 코드의 diffColor에는 기존 식에다가 빛의 색깔과 빛의 감쇠효과까지 추가한 것이다. Directional Light로는 빛의 감쇠효과를 볼수 없지만 Point Light로는 실험할 수 있다.

그리고 머리의 테두리에 빛나는 것은 Rim효과까지 적용을 해두었기 때문이다.

Shader "Custom/OneMore"
{
    Properties
    {
       
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _BumpTex ("BumpTexture", 2D) = "bump" {}
        _SpecPower ("Specular Power", Float) = 0
        _SpecCol ("Specular Color", Color) = (1,1,1,1)
        
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf _More
             
        sampler2D _MainTex;
        sampler2D _BumpTex;

        float4 _SpecCol;
        float _SpecPower;

        struct Input
        {
            float2 uv_BumpTex;
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
            o.Normal = UnpackNormal(tex2D(_BumpTex, IN.uv_BumpTex));
            o.Albedo = c.rgb;
           
            o.Alpha = c.a;
        }

        float4 Lighting_More(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten)
        {
            float4 final;

            //램버트 및 알베도 적용
            float3 diffColor;
            float ndotl = dot(s.Normal, lightDir);
            diffColor = ndotl * s.Albedo * _LightColor0.rgb * atten;

            //스펙큘러 적용
            float3 specColor;
            float3 hVec = normalize(lightDir + viewDir);
            float spec = dot(hVec, s.Normal);
            specColor = _SpecCol.rgb * spec;
            
            //Rim 적용
            float3 rimColor;
            float rim = dot(viewDir, s.Normal);
            float invertRim = 1 - rim;
            rimColor = pow(invertRim, 6) * float3(0.5, 0.5, 0.5);

            //최종 컬러 적용
            final.rgb = diffColor + specColor + rimColor;
            final.a = s.Alpha;


            return final;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

============================================================================

외곽선 만들기

Shader "Custom/TuneAgain"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _BumpTex ("BumpTexture", 2D) = "bump" {}
        _Thickness ("Thickness", Float) = 0
        _Color ("Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        Cull Front

        CGPROGRAM
        #pragma surface surf _Test vertex:vert noambient noshadow

        float _Thickness;
        float4 _Color;

        sampler2D _MainTex;

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

        struct Input
        {
            float4 color:COLOR;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
           
        }

        float4 Lighting_Test(SurfaceOutput s, float3 lightDir, float atten)
        {
            float4 color = _Color;
            return color;
        }
        ENDCG

        Cull Back

        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        sampler2D _BumpTex;

        struct Input
        {
            float2 uv_MainTex;
            float2 uv_BumpTex;
        };

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

코드를 보면 알 수있듯이 CG프로그램을 한번 더 돌리는 작업을 한다. 기본적인 뼈대는 같으며, 다만 프로퍼티는 공유한다. 이 작업에서는 후에 렌더링되는 CG가 본체를 할 것이고 먼저 처리되는 CG가 외곽선이 될 것이다.

 

여기서 vertex:vert를 옵션으로 선언하여 버텍스 값을 가져오고, vert의 inout appdata_full을 통해 버텍스의 모든 정보를 불러온다. 그리고 버텍스의 크기를 기존의 _Thickness만큼 키우면 아래 사진처럼 외곽선이 생성된다.

 

본체를 표현할 코드는 기존에 작성했던데로 범프를 해도 되고, 색감을 표현할 수 있다.

Unity Manual

그리고 컬링을 사용하여 보이는 효과를 다르게할 수 있다.

 

(2pack은 컬링적용 안 함) Front // Back // Off 

 

외곽선의 색을 바꾸고 싶다면 외곽선을 표현하는 코드에서 커스텀 라이트를 만들어 간단하게 색을 조절할 수 있다.

 

현-란

자동적으로 테두리의 색이 바뀌게 못할까 고민하던 중, RGB중 하나의 값 안에서는 월드좌표와 시간을 이용하여 변화를 줄 수 있다는 걸 깨달았다.

 

위는 외곽선 // 아래는 본체텍스쳐의 코드이다. 이런식으로 현란함을 주었다.