출처:
Ray Tracing in One Weekend - Adding a Sphere
Github - GaepoMorningEagles/mini_raytracing_in_c
Sphere
Description
레이트레이서에 단일 객체를 추가해 보겠다. 광선이 구와 만나는지를 계산하는 것은 비교적 간단하기 때문에 먼저 구를 나타내는 실습을 하겠다.
Ray-Sphere Intersection
반지름이 r 이고 점 C(Cx,Cy,Cz)를 중심으로 하는 구의 방정식은 (x−Cx)2+(y−Cy)2+(z−Cz)2=r2 이다.
구 위에 존재하는 어떤 점 P에 대해 구의 중심 C에서 점 P로 향하는 벡터를 만들어 위의 식을 다음과 같이 나타낼 수 있다.
(P−C)⋅(P−C)=(x−Cx)2+(y−Cy)2+(z−Cz)2
이제 이 구의 방정식을 벡터를 이용한 구의 방정식으로 다시 쓸 수 있다.
(P−C)⋅(P−C)=r2
우리는 "이 방정식을 만족하는 모든 점 P가 구 위에 존재한다."고 할 수 있다.
이제 어떤 광선의 방정식 P(t)=A+tb에서 어떤 점 P가 구 위에 존재한다는 것을 알고자 한다면, 이 광선의 방정식을 위의 식에 대입하여 다음과 같이 나타낼 수 있다.
(P(t)−C)⋅(P(t)−C)=r2
(A+tb−C)⋅(A+tb−C)=r2
t2b⋅b+2tb⋅(A−C)+(A−C)⋅(A−C)−r2=0
위의 식은 미지수가 t인 2차 방정식이므로 t에 대해 풀 수 있다. 판별식을 구해서 판별식이 0보다 작으면 만나지 않는 것이고, 0이면 한 점에서 만나며(접함), 0보다 크면 두 점에서 만나는 것이다.
Create Raytraced Image
구의 중심, 반지름을 담고 있는 구조체를 만들고 주어지는 값을 넣어서 초기화해준다. 그리고 광선과 구가 만나는지를 검사하는 함수를 만든다. 위에서 t에 대해 정리한 2차 방정식을 이용하면 된다. ax2+bx+c=0에서 각 a, b, c에 대응되는 값을 구한다. double
형 변수 a
, b
,c
를 선언해서 대응되는 값을 계산해 넣어준다. 그리고 판별식을 구해서 그 값이 0보다 큰지 여부를 반환해준다.
코드에서 반환값이 0보다 크면 TRUE
가 반환되어 그 때에 빨간색 원이 생기게 해주었다.
Ray Tracing in One Weekend에서는 빨간색 원이 나타나게 했는데 일본 같아서 색을 바꿨다. 갑자기 불타오르는 애국심🔥
(결과가 제대로 나오면, 위치나 색상을 바꿔보면서 어떻게 나오는지 확인해 보는 것도 재밌다.)
--
Result Image