본문 바로가기
Computer Graphics/ShaderLab, HLSL

[ShaderLab] (Half) Lambert Light

by 진현개발일기 2024. 3. 2.

■ 커스텀 라이트 (Custom Light)

이전까지 스니핏(snippet)에 #pragma surface surf Standard 와 같이 'Standard'라는 지시어로 어떠한 라이트 구조를 사용하는지 명시했었다. 여기에는 Lambert, BlinnPhong, Standard의 키워드가 대표적으로 들어갔는데 이들을 제외하고 커스터마이징한 라이팅 구조를 쓰고싶다면 아래와 같이 고쳐주면 된다.

 

surf 뒤에 CustomLight라는 키워드를 추가해줬다. 이름은 아무렇게나 지어도 된다.

 

void surf 함수 아래 float4를 반환하는 LightingCustomLight함수가 보일 것이다. CustomLight함수 이전에 'Lighting'키워드가 중요하다. 이는 surf함수 이후에 Light 함수를 정의하는 것인데 "Lighting + 커스터마이징 구조의 이름" 형식을 따르면 된다.

■ 램버트 조명 (Labmert Light)

이론은 이전에 게임 수학을 공부하면서 정리했던 내용을 포스팅해놨었다.

https://yjhdevelopdiary.tistory.com/157

 

[Math] 내적, 램버트 반사, 시야각 판별

■ 램버트 반사 램버트 반사 모델 (Lambertian reflection)이란 현실 세계와 비슷한 조명 효과를 주기 위해 고안된 방법이다. 계산량이 적어 속도가 빠르지만 그럴듯한 조명 효과를 줄 수가 있어 3차원

yjhdevelopdiary.tistory.com

 

 

[CG구현]

 

LightingCustomLight함수를 본다면 ndotl 함수에 saturate함수를 적용한 것을 볼 수 있다.

saturate함수는 0~1의 범위로 제한하는 함수이다. dot(내적)은 -1 ~ 1의 값을 반환하는데 0~-1은 모두 동일하게 검은색으로 매우 어두운 색깔을 띄고있다.

 

-1에 수렴하는 값들은 나중에 ambient light 등을 적용할 때 문제가 생긴다. 당장 0.5만큼의 라이트를 비춘다면 라이트를 분명히 비추고 있음에도 -0.5가 되어 매우 어두운 색깔을 띄고있는 것이다. 앞서 말했듯이 0~-1은 동일한 검은색을 띄고있는데 빛을 받고 있는 상태에서도 -0.5라는 음수 값으로 인해 어두운 그림자를 내고있으면 부자연스러워보일 것이다.

 

이러한 이유로 saturate함수를 사용해 0~1의 범위를 제한하고있다.

 

[Saturate 사용시]

 

[Saturate제거시]

 

 

■ Half-Lambert (하프 램버트)

Labmert 라이트는 꽤 가벼운 조명 공식이다. 하지만 cos 그래프 연산의 특성상 밝은 상태였다가 갑자기 너무 검게 음영진다는 단점이 있다. 그래서 이 단점을 해결하고자 만들어진 것이 Half Lambert이다.

 

하프램버트는 물리적으론 옳지 않지만, 보기 좋기에 만들어졌고 무엇보다 매우 가볍고 효과가 좋은 공식이라고 한다.

 

[Half Lambert 적용]

 

코드를 보면 위와 같이 '* 0.5 + 0.5'를 연산해주는 것이 하프 램버트이다. 하지만 위에서 볼 수 있듯이 실제 사용하기엔 너무 밝다.

 

그래서 실제로 사용할 때는 아래와 같이 세제곱을 연산해준다고 한다.

pow(ndotl, 3)의 결과

 

훨씬 부드럽고 자연스러워졌다.

 

이제 이 상태에서 텍스처와 조명 색상, 감쇠를 연산해 완벽한 램버트 조명을 구현해보았다.

 

 

[Atten 연산 O]

[Atten 연산 X]

 

확실히 atten연산을 안했을 경우 부자연 스러운 부분이 듬성듬성 보이는 것을 알 수 있다.

728x90