본문 바로가기
개발/Unity) Shader

Unity Shader) 그림자 처리

by 테샤르 2025. 5. 15.

그림자 처리 

 

Texture의 그림자를 만들면 깊이감이 생긴다.

좀더 자연스러운 그림자를 위해서 블러효과를 추가하고 깊이를 표현해주기 위해서 그림자의 위치를 변경할수 있게 했다.

 

반응형
반응형

 

아웃라인과 그림자를 좀더 강하게 주면 다음과 같이 나온다.

 

 

< Material 속성 >


< Shader Code >

Shader "Custom/ShadowOutLine"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Main Color", Color) = (1,1,1,1)

        _ShadowColor ("Shadow Color", Color) = (0,0,0,0.5)
        _ShadowOffset ("Shadow Offset", Vector) = (2, -2, 0, 0)
        _ShadowBlur ("Shadow Blur", Float) = 1.0
        _ShadowStrength ("Shadow Strength", Range(0,1)) = 0.7

        _OutlineColor ("Outline Color", Color) = (1,0,0,1)
        _OutlineThickness ("Outline Thickness", Float) = 1.0
        _EnableOutline ("Enable Outline", Float) = 1.0
    }

    SubShader
    {
        Tags { "Queue"="Transparent" "RenderType"="Transparent" "IgnoreProjector"="True" }
        LOD 100
        Blend SrcAlpha OneMinusSrcAlpha
        Cull Off
        ZWrite Off

        // 그림자 Pass
        Pass
        {
            Name "SHADOW"

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;

            float4 _ShadowColor;
            float4 _ShadowOffset;
            float _ShadowBlur;
            float _ShadowStrength;

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

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            v2f vert (appdata v)
            {
                v2f o;
                float4 pos = v.vertex;
                pos.xy += _ShadowOffset.xy;
                o.vertex = UnityObjectToClipPos(pos);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float2 offsets[9] = {
                    float2(-1,-1), float2(0,-1), float2(1,-1),
                    float2(-1, 0), float2(0, 0), float2(1, 0),
                    float2(-1, 1), float2(0, 1), float2(1, 1)
                };

                float blur = _ShadowBlur * 0.01;
                fixed4 sum = 0;

                for (int j = 0; j < 9; j++)
                {
                    float2 offsetUV = i.uv + offsets[j] * blur;
                    sum += tex2D(_MainTex, offsetUV).a;
                }

                float avg = sum / 9.0;
                return _ShadowColor * avg * _ShadowStrength;
            }
            ENDCG
        }

        // 메인 이미지 + 외곽선 Pass
        Pass
        {
            Name "OUTLINE_MAIN"

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;

            float4 _Color;
            float4 _OutlineColor;
            float _OutlineThickness;
            float _EnableOutline;

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

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

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

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 texCol = tex2D(_MainTex, i.uv);

                // 원본 이미지가 있는 경우
                if (texCol.a > 0.01)
                {
                    return texCol * _Color;
                }

                // 외곽선이 꺼져 있다면 투명
                if (_EnableOutline <= 0.5)
                {
                    return fixed4(0, 0, 0, 0);
                }

                // 외곽선 검사
                float thickness = _OutlineThickness * 0.005;
                float2 dirs[8] = {
                    float2(-1, 0), float2(1, 0), float2(0, 1), float2(0, -1),
                    float2(-1, 1), float2(1, 1), float2(-1, -1), float2(1, -1)
                };

                for (int k = 0; k < 8; k++)
                {
                    float2 offsetUV = i.uv + dirs[k] * thickness;
                    if (tex2D(_MainTex, offsetUV).a > 0.01)
                    {
                        return _OutlineColor;
                    }
                }

                return fixed4(0, 0, 0, 0); // 기본 투명
            }
            ENDCG
        }
    }
}

 

 

★☆☆

 

반응형

댓글