유니티/게임그래픽

Half-Lambert

DOlpa_GB 2024. 2. 22. 11:40

Half-Lambert란 갑자기 음영이 검게 떨어지는 단점을 보완하게 위해 벨브에서 발표한 Lambert라이팅의 수정공식으로, 

물리적으로는 옳지 않으나 가볍고 게임속 음영을 보기편하게 하는 공식이다

딱봐도 게임할땐 오른쪽이 더 보기 편해보인다

float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten)
{
    float ndot = dot(s.Normal, lightDir) * 0.5 + 0.5;
    float4 final = saturate(ndot) + 0.5;
    return final;
}

 

적용하는 방법은 매우 간단하다. ndot에 들어가는 값에 (* 0.5 + 0.5) 만 넣어주면 된다

전후 차이이다. 확실히 더 자연스럽고 보기좋게 바뀐것을 알 수 있다

 

 float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten)
 {
     float ndot = dot(s.Normal, lightDir) * 0.5 + 0.5;
     float4 final = pow(ndot,3);
     return final;
 }

반대 공식도 있다. Half-Lambert 공식은 빛이 거의 180도 영향을 끼치게 하기에

이 정도를 조금 줄이기 위해서는 결과물에 제곱을 해줄수 있다 *pow(X,n) = X의 n제곱

 

16-8일차 - Lambert 커스텀 라이트

우선 간단하게 텍스쳐 하나 받아 출력하게 한다 Shader "Custom/NewSurfaceShader" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } CGPROGRAM #pragma surface surf _MyLambert noambient //

sangeun00.tistory.com

이렇게 Lambert와 Half-Lambert의 기본공식을 만들어밨지만 윗글에도 적어둔것처럼 조명의 색상이나 강도등이 

텍스쳐에 전혀 적용되지 않은 모습들을 확인할 수 있다. 이번엔 그것들을 전부 해결하며 Lambert라이트를 완성해보겠다

 

Shader "Custom/NewSurfaceShader"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _BumpMap ("Albedo (RGB)", 2D) = "bump" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf _MyLambert noambient   // 환경광 제거
        sampler2D _MainTex;
        sampler2D _BumpMap;


        struct Input
        {
            float2 uv_MainTex;
            float2 uv_BumpMap;
        };

        void surf (Input IN, inout SurfaceOutput o)  // Lambert쓸거면 output 이후로 지우자
        {
           fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
           //Normal Map
           fixed4 d = tex2D(_BumpMap, IN.uv_BumpMap);
           fixed3 normal = UnpackNormal (d);
           o.Normal = normal;
           
           o.Albedo = c.rgb;
        }

        float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten)
        {
            //Lambert
            float ndot = dot(s.Normal, lightDir) * 0.5 + 0.5;
            float4 final = pow(ndot,2);
            return final;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

우선 노멀맵을 하나 추가하여 출력하도록 하자

        float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten)
        {
            //Lambert
            float ndot = dot(s.Normal, lightDir);
            float4 final;
            final.rgb = ndot * s.Albedo * _LightColor0.rgb * atten;
            final.a = s.Alpha;
            return final;
        }

텍스쳐와 조명색상, 감쇠를 연산하여 조명을 완성했다

조명의 색상과 감쇠효과를 얻기 위해 가장 중요한건 이 한줄이다

            final.rgb = ndot * s.Albedo * _LightColor0.rgb * atten;

우선 final 변수는 위에서 float4 형식으로 선언해주었다

final.rgb = ndot * s.Albedo * _LightColor0.rgb * atten;

 

ndot = dot(s.Normal, lightDir) 즉 노멀벡터와 라이트벡터를 내적 연산해주는 값이 들어간 변수이다

즉 조명과 노멀의 각도를 표현

final.rgb = ndot * s.Albedo * _LightColor0.rgb * atten;

 

Albedo로 입력받은 텍스쳐. SurfaceOutput이 s로 들어왔으니 s.Albedo이다

final.rgb = ndot * s.Albedo * _LightColor0.rgb * atten;

 

 

조명의 색상이나 강도를 내장하여 가져올수 있는 변수. 

이 변수를 곱한후 조명의 색상이나 강도를 변화시키면 그대로 반영이 된다

 

final.rgb = ndot * s.Albedo * _LightColor0.rgb * atten;

 

atten은 그림자를 받거나 거리가 멀어지면서 점점 조명이 흐려지는 라이트의 거리별 감쇠현상을 나타냄
즉 atten을 계산하지 않는다면 그림자에 관한것들이 대부분 사라지게 된다

물론 Direction Light에서는 큰 차이를 느낄수 없지만 

Point Light에서는 멀수록 어두워지는 효과등이 전부 atten의 역할이다

final.rgb = ndot * s.Albedo * _LightColor0.rgb * atten;

반응형

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

홀로그램  (0) 2024.02.24
Fresnel(프레넬) & Rim 라이트  (0) 2024.02.22
Vertex Color 응용  (0) 2024.02.22
Lambert 커스텀 라이트  (0) 2024.02.21
디지털 라이트 이론 & Vector  (0) 2024.02.21