Game Dev/Unity Shader

15. Lighting And Shadow - 다니엘 릿 쉐이더 프로젝트

Septentrions 2025. 10. 18. 11:03

드디어 그래픽스 통곡의 벽인 라이팅 파트이다.

정신 차리고 최대한 이해하자..

PBR.. 집에 PBR만을 다룬 그래픽스 서적이 있는데.. 읽다가 내 수준이 아닌 것 같아서 포기한 전적이 있다..

 

 

라이팅은 게임에 포함하고 싶은 쉐이더 중에서 가장 중요한 피쳐일 것이다.

플레이어들은 3D 게임에서 오브젝트들을 구분 할 때, 시각적 흔적을 통해 구분한다.

라이팅과 쉐도우는 오브젝트의 Depth를 판단하는데 중요한 정보이기도 하다.

현실적인 그래픽은 모두 라이팅과 쉐도우가 중요하다.

 

Lighting Models

라이팅 모델은 게임 내에서 광원 (light source)가 오브젝트의 표면(surface)와 상호 작용하는 방식을 설명하는 방법이다.

라이팅 모델은 현실을 완전히 재현하지 못하지만, 거의 근접하게 재현한 모델이다.

 

물체에 떨어지는 빛을 물체 표면과 광원 사이의 직접적인 상호 작용으로 발생하는 local 또는 direct illumination

그리고, 빛의 일부가 표면에서 반사되어 다른 표면에 비치는 global illumination으로 나눌 수 있다.

 

우선, 어떤 모델들이 있는지 알아보자.


Ambient Light

한낮에 커튼을 닫고, 불을 끄더라도 여전히 방이 보이지만 외부와는 다른 느낌을 알 것이다.

이 때, 방안의 오브젝트들은 태양빛에 의해 직접적으로 비춰지지 않음에도 같은 수준 (level)의 조명을 받고 있을 것이다.

Ambient Light는 Global Illumination을 근접하게 재현하는 방법이다.

실제 빛이 비출 때는 표면 반사, 직접 조명을 받는 등 계산적으로 굉장히 비용이 많이 들어간다.

하지만 이 엠비언트 라이트는 모든 오브젝트에 동일한 (flat) 색상을 적용하는 라이트 모델이다.

 

빛의 총량은 엠비언트 라이트의 양이라고 생각하면 편할 것이다. (Uniform)


Diffuse Light

완벽하게 매트한 (광택이 없는) 표면에 빛을 비추면, 빛은 완전히 분산되는 경향이 있다.

그 말은 반사되는 빛의 양은 표면과 각도에 따라 결정된다는 의미이다.

약간의 각도 변화는 약간의 변화가 생긴다.

일종의 Direct illumination으로 Diffuse Light라고 한다.

 

Diffuse Light는 오브젝트의 표면으로부터 광원에 대한 light 벡터, 그리고 표면의 normal 벡터를 사용한다.

Diffuse Light는 카메라의 위치에는 영향을 받지 않는다.

 

광원 벡터 L, 노말 벡터 N 의 dot product 는 표면에 ambient light 비율을 제공한다.

그리고, normalize하기도 좋다.

*dot product의 최소 최대값은 -1, 1 이기 때문이다.

각도 측면상 0보다 낮아질 수는 없으므로 clamp로 [0, 1]로 변환한다.

이 값은 이후에 광원의 컬러와 곱해지며 Diffuse Light의 총량을 얻을 수 있다.

 

Light_Diffuse = Light_Color * max(0, dot(L, N))

 

여기까지면 라이트 모델의 총량이 업데이트 된다.

Light_Total = Light_Ambient + Light_Diffuse

램버시안 법칙이 존재하는데, 완벽한 matte에 빛이 반사될 경우에 모든 방향의 빛이 모두 동일한 크기를 갖는다고 한다.

어처피 빛의 총합은 광원에서 출발하여 노말 벡터와의 관계만 계산해주면 된다는 의미이다.


Specular Light

이번엔 관찰자 시점에서의 빛 변화를 알아야 한다.

빛나는 오브젝트들을 우리가 바라 볼때, 위치에 따라 다르게 보일 것이다.

이를 Specular Lgiht라고 한다.

스펙큘러 라이트는 오브젝트의 표면이 매끄러운 정도를 표현할 수 있다.

 

Diffuse Light만 가지고는, 우리는 오브젝트를 인지할 수 없고 불완정해 보인다.

반사된 빛은 모든 방향으로 흩어지기 때문이다.

 

스펙큘러 라이트를 가지면, 대부분의 빛은 오브젝트의 표면에 도달 하였을 때, 같은 각도로 반사된다.

오브젝트를 바라 볼 때, 특정 부분이 밝게 빛나는 이유이다.

 

스펙큘러 라이트의 총량은 오브젝트의 표면으로부터 관찰자에 대한 벡터 (v), 표면으로부터 반사된 빛 (light ray) 에 대한 벡터 (r)의 Dot Product이다. 

 

Light_Specular = Light_Color * dot(r, v) ^ a

여기서 a는 빛의 세기이다. 

 

Light Ray 벡터 r을 구하는건 실제로는 엄청난 계산량을 소모한다.

이 벡터를 대신하여 실제로는 r 을 반사시키기전의 광원 (Light Source) l 벡터를 관찰자 벡터 (v)의 half에 해당하는 벡터를 사용한다. (h)

 

무슨 소린가 싶겠지만.. 계산적으로 정답과 가까운 먼 옛날 그래픽스 천재들이 만들어낸 방법이다.

(Blinn's method)

l 벡터에서 h 벡터, h벡터에서 v벡터의 각도는 동일하다.

수식은 다음처럼 변경된다.

 

h = (l + v) / Abs(l + v)

Light_BlinnSpecular = Light_Color * dot(n, h) ^ a

 

그러면, 라이팅 모델은 또 한번 변경된다.

Light_Total = Light_Ambient + Light_Diffuse + Light_BlinnSpecular

 

 

 

스펙쿨러 라이트는 한방향을 콕찝어 비추는거라 할 수 있다. 특정 부분이 밝게 비춰지는 이유이다.

 

 

Ambient, Diffuse, Specular를 모두 합한 라이트 모델은 기본적인 형태의 라이트 모델이다.

여기에 추가적으로 몇가지 라이트를 추가 해줄 수 있다.


Fresnel Light

군대 강안 부대에 있을 때, 초소 근무 중 강을 바라보면 눈이 따갑게 반짝이는 현상을 많이 겪을 것이다.

관찰자가 표면을 아주 얕게 쳐다보면 빛나게 느껴지면서, 각도를 가파르게 주면 덜 밝게 느껴진다.

이를 프레넬 현상이라 부른다.

일반적으로 프레넬 라이트는 라이트 모델에 포함되지 않는다.

대신에 넣게 되면, 시각적으로 재미있는 쉐이더를 많이 만들 수 있다.

 

프레넬 라이트는 관찰자와 표면 노말 벡터의 각도에 반비례한다.

물체를 비스듬히 볼 때 (노말 벡터와 각도가 벌어질 때) 프레넬 효과는 강해지고, 정면으로 바라보면 프레넬 효과가 사라진다.

그 말은? 관찰자와 노말 벡터의 Dot Product로 쉽게 계산할 수 있다는 이야기다.

 

Light_Fresnel = Light_Color * (1 - dot(n, v))^b

여기서 b는 빛의 세기를 의미한다.

빛의 세기가 강해지면, 오히려 프레넬 효과가 약해지는 방식이다.

 

라이팅 모델은 또 한번 업데이트 한다.

Light_Total = Light_Ambient + Light_Diffuse + Light_BlinnSpecular + Light_Fresnel

정면으로 (한가운데) 볼 수록 프레넬 효과가 없고, 각이 틀어질수록 점점 밝게 빛난다.


Blinn-Phong Reflection Model

표면과 빛의 상호작용을 구하는 방법은 Phong Reflection Model로 이미 70년대에 제안된 방법이다.

여기에 Specular Light를 계산하는 방식을 계산한 Blinn Method를 이용하여 Blinn-Phong Reflection Model로 불리게 되는게 지금까지 이어져 온다.

 

그래픽스는 정체된 기술이라 하지만, 그만큼 완벽에 가깝게 발전했다고 생각 할 수 있지 않을까?

이미 컴퓨터 그래픽은 현실을 넘어 더욱 현실 같이 보이게 만든지 오래다.

연산량, 하드웨어가 중요하긴 하지만..

 

본론으로 들어와서..

결국 라이트 모델은 표면, 컬러를 계산하여 각 픽셀의 최종 광량을 얻어야 한다.

Float Shading, Gouraud Shading, Phon Shading 기법들은 서로 다른 접근 방식으로 빛을 표현하는 기법들이다.

다음 포스팅에서 다뤄볼 예정이다.