컴퓨터 그래픽스

2024.7.13(토) - 9장 라이팅

새우급여기 2024. 7. 14. 19:14

라이팅: 빛과 물체 간 상호작용 처리하는 기술

퐁 모델: 퐁이 제안한 라이팅 기법

퐁 모델

우선 광원을 정의한다.

점 광원: 3차원 공간의 한 점으로부터 전방위로 빛이 발산되는 것.

방향성 광원: 태양과 같이 물체 표면의 여러 점에 입사하는 햇빛의 방향은 서로 평행함. 이런 광원을 방향성 광원이라고 함.

물체 표면으로 들어오는 빛과 카메라를 향해 나가는 빛 사이의 관계를 BRDF로 정의해야 한다.

퐁 모델은 극단적으로 BRDF를 단순화했다.

퐁 모델은 물체 표면에서 감지되는 색상을 디퓨즈, 스페큘러, 앰비언트 반사와 발산광 네 가지 항목으로 분리해서 처리한다.

  • 디퓨즈 항
  • 스페큘러 항
  • 엠비언트 항
  • 발산광

디퓨즈 항

디퓨즈 항은 램버트의 법칙에 따라 정의된다.

램버시안 표면 혹은 디퓨즈 표면이라 불리는 이상적인 표면으로 들어온 빛은 그림 (a)와 같이 모든 방향을 따라 같은 강도로 반사된다. 이를 난반사라고 한다.

스페큘러 항 - 정반사

퐁 모델의 스페큘러 항은 물체 표면에 하이라이트를 만드는 데 사용된다. 이를 위해서는 시선 벡터반사 벡터가 필요하다.

(a)와 같이 시선 벡터는 물체 표면의 점 p와 카메라를 연결하는 것으로 v로 표기된다. 빛 벡터 l과 마찬가지로 v 역시 실제 카메라 시선과 반대 방향으로 정의된다.

앰비언트 항

공간 내 다양한 물체로부터 반사된 빛을 앰비언트 빛이라고 부르는데, 이는 간접 조명에 해당한다. 앰비언트 빛은 장면 모든 지점에서 반사된 빛이 어우러진 것이므로 어떤 특정한 방향이 아닌 ‘모든 방향을 따라’ p점에 들어온다. 따라서 이는 p에서 ‘모든 방향을 따라’ 반사된다. 결국 p에 들어오는 앰비언트 빛의 양은 p의 노멀에 무관하고, p에서 반사되는 빛의 양은 카메라 시선에 무관하다.

(9.11 이미지)

발산광 항

퐁 모델의 발산광 항은 물체 자신이 빛을 발산하는 경우에 사용된다.

(d)의 주전자는 발산광 항에 의해서만 렌더링 되었다.

퐁 모델은 발산광을 가진 물체를 광원으로 취급하지 않는데, 따라서 같은 공간의 다른 물체를 라이팅하는 데 기여하지도 못한다.

(9.12 퐁 모델은 이상의 네 개 항을 더하여 다음과 같이 정의된다.)

(e)는 네 개의 항에서 산출된 RGB 값들을 산술적으로 더한 결과를 보여준다. 빛을 발산하지 않는 물체일 경우 발산광을 삭제하고, 만약 물체가 램버시안 표면에 가깝다면 md를 크게, ms를 작게 설정한다. 반짝이는 금속성 물체 표현에는 ms를 크게 설정하면 된다.

퐁 라이팅을 위한 쉐이더

퐁 라이팅 구현을 위한 정점 쉐이더 및 프래그먼트 쉐이더에 대해 알아보자. 위 그림은 한 물체 표면 두 점을 보여주는데, 한 점마다 하나의 프래그먼트가 생성된다고 가정하면 프래그먼트 쉐이더는 각 점마다 (9.12)식을 이용해 라이팅을 수행할 것이다. 이를 위해서는 빛 벡터 l, 노멀 n, 반사 벡터 r, 시선 벡터 v가 필요하다.

빛 벡터는 유니폼으로 입력받으며 노멀 벡터는 래스터라이저에게서 받는다. 시선 벡터도 정점마다 다르기 때문에 래스터라이저가 전달해줘야한다. 반사 벡터는 노멀 벡터와 빛 벡터가 주어지면 계산이 가능하기 때문에 이 단계에서 자체적으로 계산을 수행하게 된다.

금속성을 띠는 매끄러운 구라고 가정해보자. (d)는 a와 b에서의 스페큘러 반사를 비교한다. a와 b는 동일한 l을 가진다. 한편 a의 경우 반사 벡터 ra와 시선 벡터 va 사이 각도가 크다. 따라서 카메라는 a에서 하이라이트를 거의 보지 못할 것이고, b는 둘이 일치하므로 카메라는 b에서 강한 하이라이트를 볼 것이다. (e)는 퐁 모델로 라이팅을 수행한 결과를 보여준다.

 

예시 코드

퐁 라이팅을 위한 정점 쉐이더

4번 줄에 유니폼 eyePos가, 10번 줄에 출력 변수 v_view가 추가되었다. 이는 정점별 월드 공간 시선 벡터를 말한다.

퐁 라이팅을 위한 프래그먼트 쉐이더

18번 줄 normalize(v_normal)에 집중해보자.

이 앞의 코드의 정점 쉐이더가 출력한 v_normal은 단위 벡터였지만, 프래그먼트 쉐이더 입력으로 제공되는 v_normal은 단위 벡터라는 보장이 없다. 두 쉐이더 중간에 놓인 래스터라이저가 노멀을 보간하기 때문이다. 18번 줄은 내장 함수 normalize를 호출하여 v_normal을 다시 정규화시키는 것이다.

 


이미지 출처: [OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문]

위 서적을 보고 공부한 내용을 정리함