개요
Ray Tracing in One Weekend 4장(구체 교차 / Ray-Sphere Intersection)에서 사용하는 레이-구체 교차 판정식을 CUDA 디바이스 코드로 구현하고, RayColor()에서 교차 여부에 따라 구체는 빨간색, 그 외는 하늘 배경 그라디언트를 출력하도록 수정한 작업을 정리한다.
이번 단계의 포인트는 아래 3가지다.
•
교차 판정은 이차방정식의 판별식(discriminant)으로 빠르게 처리 가능
•
디바이스 함수에서 자주 쓰는 형태로 HitSphere()를 정리
•
Ray가 값으로 전달되는 상황을 대비해(코드 구조/컴파일러 옵션에 따라) 디바이스 복사 생성자 추가
변경 파일 목록
1. 레이-구체 교차 판정 수학 정리
1.1 구체 방정식
구체 중심을 C, 반지름을 r, 구체 표면 위의 점을 P라고 하면:
1.2 레이 방정식
레이 원점을 O, 방향을 D(정규화가 필수는 아님), 매개변수를 t라고 하면:
1.3 대입 후 이차방정식 형태
레이를 구체 방정식에 대입하면:
oc = O - C라고 두면:
전개하면 아래와 같은 이차방정식이 된다.
•
•
•
1.4 판별식(discriminant)
•
$Delta gt 0$: 두 점에서 교차
•
$Delta = 0$: 접함
•
$Delta lt 0$: 교차 없음
이번 단계에서는 “맞는다/안맞는다”만 필요하므로 Δ > 0 여부만 체크한다.
다음 단계(정확한 hit 위치, 노멀 계산, 가까운 t 선택)로 가면 t 해를 실제로 구하게 된다.
2. kernel.cu: HitSphere() 구현
2.1 함수 시그니처
현재 글의 흐름을 유지하면서도 C++/CUDA 스타일로 읽기 좋게 정리하면 아래 형태가 깔끔하다.
__device__ bool HitSphere(const Vec3& center, double radius, const Ray& r);
C++
복사
2.2 구현 코드(C++/CUDA C++)
__device__ bool HitSphere(const Vec3& center, double radius, const Ray& r)
{
Vec3 oc = r.origin() - center;
double a = Dot(r.direction(), r.direction());
double b = 2.0 * Dot(oc, r.direction());
double c = Dot(oc, oc) - radius * radius;
double discriminant = b * b - 4.0 * a * c;
return (discriminant > 0.0);
}
C++
복사
2.3 부연 설명: b를 2배로 두는 형태
책/구현에 따라 아래처럼 half_b = dot(oc, D)를 쓰는 버전이 많다.
•
b = 2 * dot(oc, D)를 쓰면 판별식 계산에 4ac가 같이 들어가고
•
half_b를 쓰면 Δ = half_b^2 - a*c로 단순해진다.
지금 단계는 “개념 정리”가 목적이라면 현재 형태도 충분히 좋다.
3. RayColor() 수정: 구체면 빨강, 아니면 하늘
__device__ Color RayColor(const Ray& r)
{
// 중심 (0,0,-1), 반지름 0.5 구체에 맞으면 빨간색
if (HitSphere(Vec3(0.0, 0.0, -1.0), 0.5, r))
return Color(1.0, 0.0, 0.0);
// 배경: 하늘색 그라디언트
Vec3 unitDirection = UnitVector(r.direction());
double t = 0.5 * (unitDirection.y() + 1.0);
return (1.0 - t) * Color(1.0, 1.0, 1.0)
+ t * Color(0.5, 0.7, 1.0);
}
C++
복사
4. Ray.h: 디바이스 복사 생성자 추가
4.1 추가 이유
커널/디바이스 함수에서 객체를 값으로 전달하거나, 컴파일러가 임시 객체를 만들면서 복사가 발생할 수 있다.
이때 복사 생성자가 명시되어 있으면 의도가 명확해지고, 특정 상황에서 컴파일 이슈를 줄이는 데 도움이 된다.
class Ray {
public:
__device__ Ray(const Ray& other)
: orig(other.orig), dir(other.dir) {}
// ...
};
C++
복사
C++에서 복사 생성자는 보통 컴파일러가 자동 생성해 주지만,
CUDA 디바이스 컴파일 경로에서 클래스 정의/가시성/인라인 여부에 따라 문제가 되는 경우가 있어 명시하는 선택이 유효하다.
렌더링 결과(현재 단계)
•
해상도: 1440 × 720
•
구체: 중심 (0, 0, -1), 반지름 0.5
•
구체 색상: 빨간색 (1, 0, 0)
•
배경: 흰색(하단) → 하늘색(상단) 그라디언트
•
출력 파일: output.ppm




