레이 트레이싱 (3)

광선과 물체의 부딪힘을 판단하는 방법

2020년 12월 07일

광선과 물체의 부딪힘 판단

3차원 공간 안에는 여러 물체가 존재합니다. 그 중 카메라의 시선에 닿고 무언가에 가려지지 않은 물체만이 실제 보이게 됩니다. 여기서 시선이 닿는다는 것은 광원에서 출발한 광선이 어떤 물체에 부딪혀 반사된 뒤 카메라의 상에 맺혔다는 뜻입니다.


레이 트레이싱에서는 하나의 광선에 대해 여러 물체를 모두 조사하며 부딪힘의 여부를 판단해 어떤 물체를 이미지 상에 그리게 될지 판단합니다. 그리고 최종적으로 한 픽셀의 색이 되는 것은 광선에 부딪힌 물체 중 카메라 원점과의 거리가 가장 가까운 물체의 색입니다. 만약 아무 물체와도 부딪히지 않는다면 픽셀의 색은 공간의 배경색이 됩니다.


지난 포스트에서 광선의 속성 eedd 를 살펴 보았습니다. ee 는 카메라 원점을, dd 는 광선의 진행 방향을 나타내는 단위 벡터입니다. 이 속성들을 이용하면 광선의 자취를 구할 수 있습니다. 식은 아주 간단합니다.

p=e+tdp = e + td

e+tde + tdee 에서 출발한 광선이 dd 방향으로 거리 tt 만큼 이동한 지점의 좌표입니다. 예를 들어 e=[0,0,0]e = [0, 0, 0], d=[1,1,0]d = [1, 1, 0], t=2t = 2 일 때 p=[0,0,0]+2[1,1,0]=[2,2,0]p = [0, 0, 0] + 2\cdot[1, 1, 0] = [2, 2, 0] 입니다.

광선과 부딪힌 물체 중 가장 가까운 물체는 식 e+tde + td 에서 각각의 물체에 대해 구해지는 tt 중 가장 작은 값을 선택함을 의미합니다. 위 그림에서 광선이 카메라 원점 ee 에서 dd 벡터 방향으로 나아갈 때 가장 먼저 부딪치는 지점 p=e+t1dp = e + t_1d 가 이후 부딪치는 지점 e+t2de + t_2d 보다 가깝습니다. 이는 t1<t2t_1 < t_2 임을 의미하고 실제 렌더되는 이미지에서는 먼저 부딪힌 물체의 색이 반영됩니다. 만약 tt 가 음수라면 물체가 카메라 뒤편에 있음을 의미합니다.

다음 절부터는 구, 원뿔, 원기둥, 평면에 대해 광선의 부딪힘을 판단하는 식을 알아보겠습니다.





구 (Sphere)

구는 중심으로부터 거리가 같은 점들의 집합입니다.

위 그림처럼 광선이 구의 한 지점 또는 두 지점과 부딪힌다고 할 때 부딪힌 지점을 p=e+tdp = e + td 와 같이 쓸 수 있습니다. 식을 해석해 보면, 점 pp 는 광원 ee 에서 dd 방향으로 tt 만큼 떨어진 지점입니다. 구의 중심으로부터 구의 표면까지의 거리는 모두 구의 반지름 rr 과 같으므로 아래와 같이 식을 쓸 수 있습니다.

r2=cp2=e+tdc2=ce+td2(d는 단위벡터)=t2+2(dce)t+ce2\begin{aligned} r^2 & = \parallel \overline{cp} \parallel ^2 \\ & = \parallel e + td - c \parallel ^2 \\ & = \parallel \overline{ce} + td \parallel ^2 (d는\text{ }단위벡터)\\ & = t^2 + 2(d \cdot \overline{ce})t + \parallel \overline{ce} \parallel ^2 \end{aligned}

좌변을 우변으로 넘기면 아래와 같습니다.

t2+2(dce)t+ce2r2=0t^2 + 2(d \cdot \overline{ce})t + \parallel \overline{ce} \parallel ^2 - r^2 = 0

tt 에 대한 이차방정식이므로 판별식 det=b2acdet = b^2 - ac 를 이용해 식의 해가 있는지 알아봅니다. 만약 det0det \ge 0 이라면 식의 해 tt 가 존재하며 이는 광선이 구와 부딪힘을 뜻합니다. 반대로 det<0det < 0 이라면 식을 만족하는 tt 가 없으므로 부딪히지 않음을 뜻합니다. 판별식으로 tt 의 존재를 판별한 후에 이차방정식에 대한 해를 구하는 식 b±deta\frac{-b \pm \sqrt{det}}{a} 를 이용해 tt 의 값을 구할 수 있습니다. 식을 만족하는 tt 에 대해 다음 조건들을 고려해 광선과 구 사이의 구체적인 관계를 정의할 수 있습니다.

  • det=0det = 0 일 때 식을 만족하는 tt 는 하나만 존재합니다. 따라서 광선이 구와 부딪히는 지점이 하나임을 뜻합니다.
  • t<0t < 0 이면 부딪히는 지점이 카메라 뒤에 있음을 의미합니다. 광선이 벡터 dd 의 역방향인 d-d 로 향하기 때문입니다.
  • det>0det > 0 일 때 식을 만족하는 tt 는 두 개이므로 양수이면서 다른 한 근보다 작은 근 tt 가 광선과 더 가까운 지점입니다.

아래는 광선과 구의 부딪힘을 판단하는 식에 근거하여 렌더한 결과입니다.





원뿔 (Cone)

원뿔은 밑면이 원인 3차원 도형입니다.

원뿔의 꼭지점을 cc, 밑면에 대해 수직인 벡터를 vv, 꼭지점 cc 에서 원뿔 옆면의 임의의 지점을 향하는 벡터와 vv 사이의 각을 θ\theta, 광선이 원뿔과 부딪힌다고 할 때 그 지점을 p=e+tdp = e + td 라 하겠습니다.

이 때 벡터 cp\overline{cp}vv 의 내적을 이용해 다음과 같이 식을 쓸 수 있습니다.

cpcpv=cosθ\frac{\overline{cp}}{\parallel \overline{cp} \parallel} \cdot v = cos\theta

위 식과 광선에 대한 식 p=e+tdp = e + td 를 이용해 연립방정식을 만들어 보겠습니다.

{p=e+tdcpcpv=cosθ\begin{cases} p = e + td \\ \frac{\overline{cp}}{\parallel \overline{cp} \parallel} \cdot v = cos\theta \end{cases}

두번째 식의 분모를 양변에 곱하고 제곱하면, 아래와 같이 쓸 수 있습니다.

cpv=cpcosθ(cpv)2=(cpcp)cos2θ\begin{aligned} \overline{cp} \cdot v &= \parallel \overline{cp} \parallel cos\theta \\ (\overline{cp} \cdot v)^2 &= (\overline{cp} \cdot \overline{cp}) cos^2\theta \end{aligned}

p=e+tdp = e + tdcp\overline{cp} 에 대입하면 cp=e+tdc=ce+td\overline{cp} = e + td - c = \overline{ce} + td 입니다. 이를 위 식에 대입해 전개하면,

{(ce+td)v}2=(ce+td)(ce+td)cos2θt2(dv)2+2t(dv)(cev)+(cev)2={t2(dd)+2t(ced)+(cece)}cos2θ\begin{aligned} \{(\overline{ce} + td) \cdot v\}^2 &= (\overline{ce} + td) \cdot (\overline{ce} + td) cos^2\theta \\ t^2(d \cdot v)^2 + 2t(d \cdot v)(\overline{ce} \cdot v) + (\overline{ce} \cdot v)^2 &= \{t^2(d \cdot d) + 2t(\overline{ce} \cdot d) + (\overline{ce} \cdot \overline{ce})\}cos^2\theta \end{aligned}

tt 에 대한 2차방정식으로 정리하면 아래와 같습니다. dd 는 단위벡터이므로 (dd)=1(d \cdot d) = 1 로 바꾸어 간단히 표현했습니다.

t2{(dv)2cos2θ}+2t{(dv)(cev)(ced)cos2θ}+(cev)2(cece)cos2θt^2\{(d \cdot v)^2 - cos^2\theta\} + 2t\{(d \cdot v)(\overline{ce} \cdot v) - (\overline{ce} \cdot d)cos^2\theta\} + (\overline{ce} \cdot v)^2 - (\overline{ce} \cdot \overline{ce}) cos^2\theta

이차방정식의 계수를 판별식에 대입하기 쉽게 정리하면 아래와 같습니다.

{a=(dv)2cos2θb=(dv)(cev)(ced)cos2θc=(cev)2(cece)cos2θ\begin{aligned} \left\{\begin{aligned}a &= (d \cdot v)^2 - cos^2\theta \\ b &= (d \cdot v)(\overline{ce} \cdot v) - (\overline{ce} \cdot d)cos^2\theta \\ c &= (\overline{ce} \cdot v)^2 - (\overline{ce} \cdot \overline{ce}) cos^2\theta \end{aligned}\right. \end{aligned}

이제 판별식 det=b2acdet = b^2 - ac 를 이용해 광선이 원뿔과 부딪히는지 판단할 수 있습니다. 구의 경우와 마찬가지로 이차방정식의 해를 구하는 식 b±deta\frac{-b \pm \sqrt{det}}{a} 를 이용해 tt 를 구합니다. tt 의 값에 대한 조건에 따라 아래와 같이 원뿔과 광선 사이의 관계를 정의해 보겠습니다.

  • det=0det = 0 일 때 식을 만족하는 tt 는 하나만 존재합니다. 따라서 광선이 원뿔과 부딪히는 지점이 하나임을 뜻합니다.
  • t<0t < 0 이면 부딪히는 지점이 카메라 뒤에 있음을 의미합니다. 광선이 벡터 dd 의 역방향인 d-d 로 향하기 때문입니다.
  • det>0det > 0 일 때 식을 만족하는 tt 는 두 개이므로 양수이면서 다른 한 근보다 작은 근 tt 가 광선과 더 가까운 지점입니다.

한편 전개한 식은 원뿔의 밑면을 전혀 고려하지 않습니다. 만약 광선이 원뿔의 밑면을 향하고 있다면 아래와 같이 밑면은 통과하고 옆면과 부딪힌 지점만을 계산합니다.

이제 식을 반영해 원뿔을 렌더해 보겠습니다.

모래 시계 모양의 이미지가 출력됐습니다. 이는 tt 에 관한 식이 vv 를 밑면에 수직인 벡터로 갖는 원뿔 뿐만 아니라 v-v 를 갖는 원뿔에 대해서도 만족하기 때문입니다. v-v 를 갖는 원뿔을 제외시키려면 벡터 cp\overline{cp}vv 가 이루는 각도를 이용합니다. 만약 두 벡터가 이루는 각도가 9090^{\circ} 에서 180180^{\circ} 사이라면 원뿔의 수직 벡터가 v-v 임을 의미합니다.

각도를 이용한 조건식은 cpv=cosθ\overline{cp} \cdot v = cos\theta 를 이용합니다. cosθcos\theta9018090^{\circ} - 180^{\circ} 에서 음수입니다. 따라서 아래 조건식을 만족하는 점 pp 만을 렌더했을 때 원뿔을 그릴 수 있습니다.

cpv0\overline{cp} \cdot v \ge 0

한편 cpv\overline{cp} \cdot v 는 아래 그림처럼 높이에 관한 정보를 제공합니다.

cpvheight\overline{cp} \cdot v \le height 를 이용하면 원하는 높이의 원뿔을 그릴 수 있습니다.





원기둥 (Cylinder)

원기둥은 중심축과 위 아래의 두 원 평면을 가지는 입체 도형입니다. 다만 우리가 다룰 원기둥은 옆면만을 고려합니다.

광선이 원기둥과 부딪힌다고 할 때 그 지점을 p=e+tdp = e + td 와 같이 쓸 수 있습니다. 위 그림에서 원기둥의 축벡터 vv 위의 한점 cc' 에 대해 cccp\overline{cc'} \perp \overline{c'p} 를 만족할 때 피타고라스의 정리에 의해 다음과 같이 쓸 수 있습니다.

cp2cc2=r2{\parallel \overline{cp} \parallel}^2 - {\parallel \overline{cc'} \parallel}^2 = r^2

그리고 내적을 이용해 다음 식을 도출할 수 있습니다.

cc=(cpv)v\overline{cc'} = (\overline{cp} \cdot v)v

cp=e+tdc=ce+td\overline{cp} = e + td - c = \overline{ce} + td 을 두 식에 대입해 정리해보겠습니다.

cp2cc2=r2(ce+td)(ce+td)((ce+td)v)2=r2t2(dd)+2t(ced)+cece{t2(dv)2+2t(dv)(cev)+(cev)2}=r2t2{(dv)21}+2t{(dv)(cev)ced}+{r2cece+(cev)2}=0\begin{aligned} & {\parallel \overline{cp} \parallel}^2 - {\parallel \overline{cc'} \parallel}^2 = r^2 \\ & (\overline{ce} + td) (\overline{ce} + td) - ((\overline{ce} + td) \cdot v)^2 = r^2 \\ \\ & t^2(d \cdot d) + 2t(\overline{ce} \cdot d) + \overline{ce} \cdot \overline{ce} - \{t^2 (d \cdot v)^2 + 2t(d \cdot v)(\overline{ce} \cdot v) + (\overline{ce} \cdot v)^2\} = r^2 \\ & t^2 \{(d \cdot v)^2 - 1\} + 2t\{(d \cdot v)(\overline{ce} \cdot v) - \overline{ce} \cdot d\} + \{r^2 - \overline{ce} \cdot \overline{ce} + (\overline{ce} \cdot v)^2\} = 0 \end{aligned}

tt 에 대한 이차방정식이 만들어졌습니다. 판별식 det=b2acdet = b^2 - ac 를 위해 계수 aa, bb, cc 를 정리하면,

a=(dv)21b=(dv)(cev)cedc=r2cece+(cev)2\begin{aligned} a &= (d \cdot v)^2 - 1 \\ b &= (d \cdot v)(\overline{ce} \cdot v) - \overline{ce} \cdot d \\ c &= r^2 - \overline{ce} \cdot \overline{ce} + (\overline{ce} \cdot v)^2 \\ \end{aligned}

이제 판별식을 이용해 광선과 원기둥의 옆면이 부딪히는지 판단할 수 있습니다. 위 식을 이용해 원기둥과 광선이 부딪힌 지점을 렌더해보면 다음 이미지를 얻습니다.

원뿔의 경우와 마찬가지로 벡터 vvv-v 를 축으로 갖는 경우가 모두 반영된 모습입니다. 원뿔과 같은 방법으로 조건 cpv0\overline{cp} \cdot v \ge 0cpvh\overline{cp} \cdot v \le h 를 적용하면 원하는 길이만큼의 원기둥만을 렌더할 수 있습니다.





평면 (Plane)

평면은 법선 벡터와 평면위의 임의의 한점을 이용하거나 평면에 대한 식 ax+by+cz+dax + by + cz + d 를 이용해 그릴 수 있습니다. 이 포스트에서는 법선 벡터와 임의의 한점을 이용한 방법으로 광선과의 부딪힘을 판단해 보겠습니다.

평면과 광선의 부딪히는 지점을 찾는 것은 간단합니다. 부딪히는 지점을 p=e+tdp = e + td 라 하고 평면위의 한 점을 aa, 법선벡터를 nn 이라 하면 apn\overline{ap} \perp n 이 성립합니다. ap=(e+td)a=ae+tdap = (e + td) - a = \overline{ae} + td 이므로 다음과 같이 쓸 수 있습니다.

(ae+td)n=0t(dn)=aent=eandn\begin{aligned} & (\overline{ae} + td) \cdot n = 0 \\ & t(d \cdot n) = -\overline{ae} \cdot n \\ \\ & t = \frac{\overline{ea} \cdot n}{d \cdot n} \end{aligned}

이 때 분모 dnd \cdot n 이 0이라면 (혹은 0에 매우 가깝다면) 정의할 수 없습니다. 이는 아래 그림의 경우와 같습니다.

t<0t < 0 이면 평면이 카메라의 뒤에 있음을 의미합니다. 따라서 dn0d \cdot n \neq 0t>0t > 0 를 만족할 때 광선과 부딪힌다고 할 수 있습니다.


지금까지 구, 원뿔, 원기둥, 평면에 대해 광선과의 부딪힘을 판단하는 방법을 기초적인 기하학을 이용해 알아보았습니다. 물체와 광선이 부딪힌 지점 pp 의 정보는 물체의 접평면의 법선벡터를 구하는데 사용됩니다. 법선벡터는 광원과의 각도를 결정하고 최종적으로 본연의 색깔로부터 얼마나 어두워지는지를 나타내는 쉐이딩(shading)을 구하는데 사용됩니다. 다음 포스트에서는 광선과 부딪힌 지점의 정보가 쉐이딩 기법 Phong reflection 에 어떻게 이용되는지 알아보겠습니다.





출처 및 참고