레이 트레이싱 (5)

물체 표면의 법선 벡터

2020년 12월 19일

광선과 물체가 부딪힌 지점 pp 는 카메라 원점 ee 와 광선의 방향을 나타내는 벡터 dd, 카메라로부터 떨어진 거리 tt 를 이용해 아래와 같이 쓸 수 있었습니다.

p=e+tdp = e + td

하지만 지점 pp 만으로는 물체를 렌더하기 위한 Phong reflection 식을 완성할 수 없었습니다. 이번 포스트에서는 Phong reflection 을 완성하고 이후 반사와 굴절을 구하기 위한 요소, 법선 벡터 nn 을 알아보겠습니다.





법선 벡터

물체의 한 지점 pp 는 공간에 있는 가장 작은 요소인 입니다. 구, 원뿔, 원기둥, 평면 또는 직육면체 등은 표면의 한 점에서 법선 벡터를 가집니다. 구, 원뿔, 원기둥과 같은 경우 아래 그림과 같이 한 점의 법선 벡터는 그 접평면의 법선 벡터입니다.

이어지는 절부터는 구, 원뿔, 원기둥, 평면에 대해 각각의 법선 벡터를 구하는 방법을 알아보겠습니다.





구 (Sphere)

구의 한 지점에서의 법선 벡터를 찾는 것은 아주 쉽습니다. 광선과 구가 부딪힌 지점 pp 와 구의 중심 cc 를 잇는 cp\overline{cp} 가 법선 벡터가 됩니다. 주의해야 할 것은 모든 도형의 법선 벡터는 길이가 1인 단위 벡터여야 한다는 것입니다.

nsphere=cp(cp=1)\begin{aligned} n_{sphere} = \overline{cp}\\ (\parallel cp \parallel = 1) \end{aligned}

레이 트레이싱의 원리를 구현하는 코드를 작성할 때 종종 단위 벡터로 정규화하지 않아 디버깅이 힘들어지는 경우가 많습니다. 이는 법선 벡터 뿐만 아니라 광선의 진행 방향, 반사, 굴절에 대해서도 마찬가지입니다.





원뿔 (Cone)

원뿔의 꼭지점을 cc, 광선과 원뿔이 부딪힌 지점을 pp, 원뿔의 중심축을 지나고 꼭지점에서 밑면을 향하는 단위벡터를 vv, cp\overline{cp} 와 수직을 이루면서 중심축 위에 있는 점을 cc' 이라 하겠습니다. 이 때 점 pp 에서의 법선벡터는 cp\overline{c'p} 입니다.

법선 벡터 cp\overline{c'p}cpcc\overline{cp} - \overline{cc'} 로 다시 써보겠습니다.

cp=cpcc\overline{c'p} = \overline{cp} - \overline{cc'}

벡터 cp\overline{cp} 는 이미 알고 있는 정보이므로 미지수 cc\overline{cc'} 만 찾으면 cp\overline{c'p} 를 구할 수 있습니다. cc\overline{cc'} 는 단위 벡터 v\overline{v} 의 스칼라배이므로 cc=αv\overline{cc'} = \alpha \overline{v} 와 같이 쓸 수 있습니다. 이 때 α\alphacc\parallel \overline{cc'} \parallel 이고 cc\parallel \overline{cc'} \parallel 에 대해 다음이 성립합니다.

cosθ=cpcc=cpvcpcc=cpcosθ=cp2cpv\begin{aligned} cos\theta = \frac{\parallel \overline{cp} \parallel}{\parallel \overline{cc'} \parallel} = \frac{\overline{cp} \cdot \overline{v}}{\parallel \overline{cp} \parallel}\\ \\ \therefore \parallel \overline{cc'} \parallel = \frac{\parallel \overline{cp} \parallel}{cos\theta} = \frac{\parallel \overline{cp} \parallel^2}{\overline{cp} \cdot \overline{v}} \end{aligned}

α=cc\alpha = \parallel \overline{cc'} \parallel 에 대해 cpcosθ\frac{\parallel \overline{cp} \parallel}{cos\theta}cp2cpv\frac{\parallel \overline{cp} \parallel^2}{\overline{cp} \cdot \overline{v}} 두가지 식을 사용할 수 있습니다. 만약 라이브러리 또는 본인이 구현한 cosf 함수 비용이 작다면 cpcosθ\frac{\parallel \overline{cp} \parallel}{cos\theta} 를, 아니라면 cp2cpv\frac{\parallel \overline{cp} \parallel^2}{\overline{cp} \cdot \overline{v}} 를 이용하면 될 것입니다. α=cc\alpha = \parallel \overline{cc'} \parallel 를 적용해 법선벡터 식을 정리해보겠습니다.

ncone=cp=cpcpcosθv=cpcp2cpvv\begin{aligned} n_{cone} = \overline{c'p} &= \overline{cp} - \frac{\parallel \overline{cp} \parallel}{cos\theta} \overline{v}\\ \\ &= \overline{cp} - \frac{\parallel \overline{cp} \parallel^2}{\overline{cp} \cdot \overline{v}} \overline{v} \end{aligned}

구의 경우와 마찬가지로 법선 벡터를 구한 뒤엔 단위 벡터로 정규화해주어야 합니다.





원기둥 (Cylinder)

원기둥의 중심축 위 끝점을 cc, 광선과 원기둥이 부딪힌 지점을 pp, 중심축 방향인 단위벡터를 vv 라 하겠습니다. 오른쪽 단면 그림을 보면 구하고자 하는 법선 벡터는 cp\overline{c'p} 입니다. 원뿔의 경우와 마찬가지로 cp=cpcc\overline{c'p} = \overline{cp} - \overline{cc'} 라 하고 cc=αv\overline{cc'} = \alpha \overline{v} 라 하겠습니다. 여기서 α=cc=cpv\alpha = \parallel \overline{cc'} \parallel = \overline{cp} \cdot \overline{v} 입니다. 따라서 원기둥의 법선벡터를 구하는 식은 다음과 같이 정리할 수 있습니다.

ncylinder=cp=cp(cpv)vn_{cylinder} = \overline{c'p} = \overline{cp} - (\overline{cp} \cdot \overline{v})\overline{v}





평면 (Plane)

평면은 객체의 정보를 어떻게 저장하고 있느냐에 따라 법선 벡터를 구하는 방법이 다릅니다. 만약 평면 위의 임의의 한 점과 법선벡터를 저장하고 있다면 법선벡터를 그대로 사용하면 됩니다. 만약 평면의 방정식 ax+by+cz+d=0ax + by + cz + d = 0 를 기반으로 a,b,c,da, b, c, d 를 저장하고 있다면 [a,b,c][a, b, c] 가 법선 벡터입니다.



이제 법선 벡터를 이용해 Phong reflection 쉐이딩 식을 완성할 수 있게 되었습니다. 다음 포스트에서는 빛과 물체의 관계에 필수 불가결적인 요소, 그림자를 표현하는 방법을 알아보겠습니다.