레이 트레이싱 (2)

광선 객체

2020년 12월 01일

지난 포스트에서 레이 트레이싱은 빛을 추적해 이미지 한 픽셀의 색을 구한다는 것을 알아봤습니다. 이번 포스트에서는 추적할 대상인 이 어떤 속성들을 가지고 있고 어떻게 생성할 수 있는지 알아보겠습니다.





Ray

빛 추적은 광선이 지나온 자취를 되돌아 가는 것입니다. 레이 트레이싱은 무수히 많은 광선 중 이미지의 한 픽셀을 거쳐 카메라 원점에 도착한 광선만을 추적합니다. 따라서 광선들의 도착점인 카메라 원점은 되돌아 가는 과정에서 출발점이 됩니다. 이 출발점을 ee 라 하겠습니다.


이미지의 크기가 800 x 600 이라면 추적할 광선은 이미지 픽셀의 개수만큼 존재하므로 광선의 개수 역시 800 x 600 입니다. 그리고 800 x 600 개의 광선들은 원점 ee 에서 이미지의 한 픽셀을 향하는 각기 다른 방향 벡터를 가집니다. 이 벡터를 단위 벡터 dd 라 하겠습니다.


광선은 원점 ee 와 벡터 dd 를 이용해 표현할 수 있습니다.

class Ray:
	def __init__(self, e: List[float], d: List[float]):
		self.e = e # 3차원 벡터
		self.d = d # 3차원 벡터 (단위 벡터)





Ray grid

모든 광선은 ee 에서 출발하지만 각각의 픽셀에 따라 방향 벡터 dd 를 달리합니다.

def render_ray_tracing_image():
	for y in range(0, height):
		for x in range(0, width):
			ray = # x, y 를 이용한 광선 객체
			grid[y][x] = ray_trace(ray)

픽셀마다 달라지는 광선 객체는 위와 같이 반복문 안에서 생성됩니다. 먼저 최상단 왼쪽 픽셀을 향하는 벡터를 초기값 originorigin 이라 하겠습니다. 이터레이션마다 초기값이 이동할 한 픽셀의 가로 세로 벡터 dxdx, dydy 를 알고 있으면 각 광선의 방향 벡터 dd 는 아래 식과 같습니다.

d=origin+αdx+βdyd = origin + \alpha dx + \beta dy

이를 그림으로 표현하면 다음과 같습니다.


카메라 원점을 CC 라 할 때 월드 좌표계에 대해 카메라의 세 좌표축을 설정합니다. 이 때 카메라 원점과 이미지 평면 사이의 거리는 1입니다.

그림의 카메라 원점 CC 에서 최상단 왼쪽 픽셀을 향하는 벡터를 originorigin 이라 하고 카메라의 세 좌표축을 XcX_c, YcY_c, ZcZ_c 라 하면 originorigin 은 다음과 같이 쓸 수 있습니다.

origin=ZcgxXcgyYcorigin = Z_c - gx \cdot X_c - gy \cdot Y_c

이 때 gxgx, gygy 값은 이미지 평면 가로 세로 길이 각각의 절반입니다. 가로 길이의 경우 카메라의 광각(angle of view) 을 이용해 다음과 같이 쓸 수 있습니다.

gx=tan aov2gx = tan\text{ }\frac{aov}{2}

gygy 는 비례식 gx:gy=가로 픽셀 개수:세로 픽셀 개수gx : gy = 가로\text{ }픽셀\text{ }개수 : 세로\text{ }픽셀\text{ }개수 을 이용해 아래와 같이 쓸 수 있습니다.

gy=gx세로 픽셀 개수가로 픽셀 개수gy = gx \cdot \frac{세로\text{ }픽셀\text{ }개수}{가로\text{ }픽셀\text{ }개수}

이제 gxgx, gygy 를 이용해 originorigin 을 구할 수 있습니다. 픽셀마다 광선 객체의 방향벡터 dd 를 찾으려면 originorigin 에 한 픽셀의 가로 세로 벡터 dxdx, dydy 를 더하면 됩니다. 예를 들어 픽셀 pp 의 좌표가 (2, 3) 이라면 pp 에 대응하는 광선 객체는 origin+2dx+3dyorigin + 2dx + 3dy 입니다.

dxdx, dydy 는 이미지의 가로 세로 길이의 절반인 gxgx, gygy 를 이용해 아래와 같이 쓸 수 있습니다.

dx=2gx가로 픽셀 개수1Xcdx = \frac{2gx}{가로\text{ }픽셀\text{ }개수 - 1} \cdot X_c dy=2gy세로 픽셀 개수1Ycdy = \frac{2gy}{세로\text{ }픽셀\text{ }개수 - 1} \cdot Y_c

위 식의 분모에서 1을 빼는 이유는 광선의 방향벡터가 픽셀의 가운데를 향하면서 픽셀 하나만큼의 길이를 제외시키기 때문입니다.

이제 origin,dx,dyorigin, dx, dy 를 알아냈으므로 광선객체의 벡터 dd 속성을 구할 수 있습니다.

d=origin+αdx+βdyd = origin + \alpha dx + \beta dy

식에서 α,β\alpha, \beta 는 광선 객체를 생성하는 이중 반복문의 인덱스입니다. 이로써 각 픽셀에 대한 광선 객체를 구할 수 있게 되었습니다. 광선 객체는 레이 트레이싱의 시작이자 이후 물체와의 부딪힘 판단, 반사, 굴절을 구하는데 사용됩니다. 다음 포스트에서는 광선 객체를 이용해 물체와의 부딪힘을 판단하는 방법을 알아보겠습니다.





참고