ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 홀로그램 응용
    유니티/게임그래픽 2024. 2. 24. 16:44

    <홀로그램 응용>

    1. 홀로그램을 깜빡이게 해보자

    깜빡이는 주기는 _speed라는 이름으로 입력받은 range로 조절할 수 있다

     

      void surf (Input IN, inout SurfaceOutput o)
            {
                fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
                o.Emission = _Color.rgb;
    
                //rim
                float ndot = saturate(dot(o.Normal, IN.viewDir));
                float rim = pow(1- ndot, _RimPow);
                o.Alpha = rim * sin(_Time.y * _Speed);
            }

    윗부분은 사실 다 아는 내용이니까 넘어가고 출력파트만 보겠다

    o.Alpha = rim * sin(_Time.y);

    이게 핵심이다. 우선은 깜빡이게 하기 위해서는 꺼졌다 켜졌다가 반복되어야 하는데

    그때 들어가는것이 전에 배웠던 _Time 함수이다

     

    알파가 나타났다 사라졌다가 반복되어야하니 o.Alpha안에 넣어주면 된다

     

     

    2. 줄무늬가 위로 올라가는 효과를 만들어보자

    Shader "Custom/NewSurfaceShader"
    {
        Properties
        {
            _MainTex ("Albedo (RGB)", 2D) = "white" {}
        }
        SubShader
        {
            Tags { "RenderType"="Opaque" "Queue" = "Transparent"}
            CGPROGRAM
            #pragma surface surf Lambert alpha:fade
            sampler2D _MainTex;
         
            struct Input
            {
                float2 uv_MainTex;
                float3 viewDir;
            };
    
            void surf (Input IN, inout SurfaceOutput o)
            {
                fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
                o.Emission = 0;
                float ndot = saturate(dot(o.Normal, IN.viewDir));
                float rim = pow(1- ndot,3);
                o.Alpha = 1;
            }
            ENDCG
        }
        FallBack "Diffuse"
    }

    우선 방금짠 코드에서 쓸데없는건 다 빼버리고 Alpha에 rim대신 1을 넣어 불투명하게 만든뒤

    Emission은 검게 만든다

       struct Input
            {
                float2 uv_MainTex;
                float3 viewDir;
                float3 worldPos;   // 추가
            };
    
            void surf (Input IN, inout SurfaceOutput o)
            {
                fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
                o.Emission = IN.worldPos;  //출력
                float ndot = saturate(dot(o.Normal, IN.viewDir));
                float rim = pow(1- ndot,3);
                o.Alpha = 1;
            }

     

    Input구조체에 worldPos를 추가하고 surf 함수에서 받아와 출력해보자

     

    게임속 좌표에 따라 xyz가 rgb에 대입되는것을 볼 수 있다

    말 그대로 물체를 상하좌우 움직이면 색이 변한다는 것.

     

    여기선 줄무늬가 위로 올라가게 해야하니 상하값인 y축만 필요하다

    y축을 출력 하기 위해서 IN.worldPos.g만 출력해보자

     

      void surf (Input IN, inout SurfaceOutput o)
            {
                fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
    
                o.Emission = frac(IN.worldPos.g);
                
                float ndot = saturate(dot(o.Normal, IN.viewDir));
                float rim = pow(1- ndot,3);
                o.Alpha = 1;
            }

     

    여기서 쓰이는 frac 함수

     

    쉽게 말해 안에 들어온 숫자의 소수점 부분만 리턴시켜주는 함수이다

     

    그럼 이 소수점만 반환해주는게 어떻게 검정색-흰색으로 그라데이션을 만들어주냐?

     

    2.9도 0.9를 리턴해주기 때문에 이 함수를 적용하면 숫자가 증가 할수록

    계속 0 ~ 0.999가 반복되는 결과를 가져 온다 결과적으로 검정색에서 흰색의 그라데이션이 반복이 된다

     

    ...라고 하지만 우선은 그라데이션을 만들기위해서 이런 함수를 이용한다는것 정도만 알아두자

     

    우선 흰부분과 검은 부분이 거의 비슷할 정도로 두꺼우니 흰부분을 줄여주자

     

                o.Emission = pow(frac(IN.worldPos.g), 30);

     

    전에 Rim라이트 줄여주는것과 같은 원리이다. 적절한 수를 제곱해주자

    이번엔 라인의 간격을 줄여주자

                o.Emission = pow(frac(IN.worldPos.g * 3), 30);

     

    이제 꽤나 그럴싸한 라인이 만들어졌다. 이제 이걸 위로 움직이게 하여 홀로그램처럼 만들어보자

     

               o.Emission = pow(frac(IN.worldPos.g * 3 - _Time.y), 30);

     

    이것도 어렵지 않다 만들어둔 값에 _Time.y를 빼주기만 하면 된다

     

    이제 선이 올라가는 움직임까지 구현했다면 이 결과물을 rim 연산과 더해준뒤 알채널에 할당해주자

    Shader "Custom/NewSurfaceShader"
    {
        Properties
        {
            _MainTex ("Albedo (RGB)", 2D) = "white" {}
        }
        SubShader
        {
            Tags { "RenderType"="Opaque" "Queue" = "Transparent"}
            CGPROGRAM
            #pragma surface surf Lambert alpha:fade
            sampler2D _MainTex;
         
            struct Input
            {
                float2 uv_MainTex;
                float3 viewDir;
                float3 worldPos;   // 추가
            };
    
            void surf (Input IN, inout SurfaceOutput o)
            {
                fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
                o.Emission = float3(0,1,0);
                float holo = pow(frac(IN.worldPos.g * 3 - _Time.y), 30);                           
                float ndot = saturate(dot(o.Normal, IN.viewDir));
                float rim = pow(1- ndot,3);
    
                float alpha = rim + holo;
                o.Alpha = alpha;
            }
            ENDCG
        }
        FallBack "Diffuse"
    }

     

     

    '유니티 > 게임그래픽' 카테고리의 다른 글

    홀로그램  (0) 2024.02.24
    Fresnel(프레넬) & Rim 라이트  (0) 2024.02.22
    Half-Lambert  (0) 2024.02.22
    Vertex Color 응용  (0) 2024.02.22
    Lambert 커스텀 라이트  (0) 2024.02.21
Designed by Tistory.