-
Half-Lambert유니티/게임그래픽 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제곱
이렇게 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