-
Lambert 커스텀 라이트유니티/게임그래픽 2024. 2. 21. 18:09
우선 간단하게 텍스쳐 하나 받아 출력하게 한다
Shader "Custom/NewSurfaceShader" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } CGPROGRAM #pragma surface surf _MyLambert noambient // 환경광 제거 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) // Lambert쓸거면 output 이후로 지우자 { fixed4 c = tex2D(_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; } float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten) { return float4(1,0,0,1); } ENDCG } FallBack "Diffuse" }
하지만 여기서 처음 보는 부분이 있다
//반환타입 float4는 최종 color //Custom Light 만들때 반드시 Lightning<라이트 모델이름> ex) Lightning_MyLambert float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten) { return float4(1,0,0,1); }
= > 여기서 _MyLambert가 라이팅 이름이다
#pragma surface surf _MyLambert noambient
이게 커스텀 라이트 함수의 기본형이다. 반환타입은 float4이고 이 반환값은 최종 color를 의미한다
float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten)
{
return float4(1, 0, 0, 1);
}
여기서 주의할건 커스텀 라이트 이름앞에 Lighting을 붙여줘야 라이트 함수로 받아들인다
float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten)
{
return float4(1, 0, 0, 1);
}
변경하거나 수정할 수 없다. 주어진대로 사용해야 한다.
매개변수 SurfaceOutput s 의 값은 surf 함수에서 계산된 후 전달된 구조체 인스턴스이다
매개변수 float3 lightDir 는 Vertex에서 바라보는 조명의 방향을 뒤집은 조명 벡터이다. 길이가 1인 단위벡터이다
매개변수 float atten 는 그림자를 받거나 거리가 멀어지면서 점점 조명이 흐려지는 라이트의 거리별 감쇠현상을 나타낸다
float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten)
{
return float4(1, 0, 0, 1);
}
위 코드는 말 그대로 (1,0,0,1) 값을 출력하도록 만드는 단순한 코드이며
이제 dot 함수를 사용하여 노멀벡터와 라이트벡터를 내적 연산을 해주자
float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten) { float ndot = dot(s.Normal, lightDir); return ndot; }
이전 surf 함수에서 o.Normal에 아무값도 넣지 않았으나 기본값이 있는 s.Normal의 값을 가져올 수 있다
이게 Lambert 라이트의 기본형이다
하지만 지금은 보다시피 조명의 색상도 받지 못하며 내적연산한 값이 1 ~ -1이기에
후에 ambient light나 추가 라이트를 비출때 이 음수가 문제를 불러일으킬 수 있다
이것을 방지하기 위해 0 밑의 값은 전부 0으로 잘라버려야 하는데
이러한 기능을 가진 함수는 saturate, max가 있다
이번엔 staturate함수를 사용하여 바꿔보겠다
float4 Lighting_MyLambert(SurfaceOutput s, float3 lightDir, float atten) { float ndot = dot(s.Normal, lightDir); float4 final = saturate(ndot) + 0.5; return final; }
솔직히 이 과정에서 쓰이는 코싸인, 벡터를 내적한다던가 하는것들은 아직 이해되지 않는다
하지만 우선 이런 상황에서 이런 함수가 쓰인다는것, 그리고 커스텀 라이팅 만드는법만 익히고 넘어가자
'유니티 > 게임그래픽' 카테고리의 다른 글
Half-Lambert (0) 2024.02.22 Vertex Color 응용 (0) 2024.02.22 디지털 라이트 이론 & Vector (0) 2024.02.21 Lambert & Blinn Phong (0) 2024.02.21 NormalMap (0) 2024.02.21