안녕하세요. 정글러 입니다.
Ray Tracing은 광선이 카메라(또는 관찰자)로부터 출발해 장면 속의 물체와 상호작용하며
빛과 그림자, 반사, 굴절 등을 계산하여 이미지를 생성하는 렌더링 기법입니다.
1. 카메라에서 광선을 방출
2. 광선이 물체에 충돌하는지 확인
3. 충돌한 지점에서 광원의 방향을 기준으로 조명, 반사, 그림자 등을 계산
4. 계산 결과를 픽셀에 기록
Ray의 정의: 시작점과 방향을 가지며, 이 정보를 통해 광선이 공간에서 어디로 향하는지 계산
class Ray {
public:
glm::vec3 origin; // 광선의 시작점
glm::vec3 direction; // 광선의 방향 (정규화된 벡터)
Ray(const glm::vec3& o, const glm::vec3& d) : origin(o), direction(glm::normalize(d)) {}
// 광선의 특정 시점 위치를 계산
glm::vec3 PointAt(float t) const {
return origin + t * direction;
}
};
}
Sphere의 정의: 광선과 구가 충돌하는지 확인하는 메서드가 포함
class Sphere {
public:
glm::vec3 center; // 구의 중심
float radius; // 구의 반지름
glm::vec3 color; // 구의 색깔
Sphere(const glm::vec3& c, float r) : center(c), radius(r) {}
// 광선과 구의 충돌 여부를 계산
bool Intersect(const Ray& ray, float& tHit) const {
glm::vec3 oc = ray.origin - center;
float a = glm::dot(ray.direction, ray.direction);
float b = 2.0f * glm::dot(oc, ray.direction);
float c = glm::dot(oc, oc) - radius * radius;
float discriminant = b * b - 4 * a * c;
if (discriminant < 0) return false;
tHit = (-b - sqrt(discriminant)) / (2.0f * a);
return tHit >= 0;
}
};
}
광선과 구의 충돌은 세가지 경우를 나눠서 계산
- 0보다 작을 경우, 충돌x
- 0이거나 0보다 클 경우엔 return
Hit 정보 저장
struct HitRecord {
glm::vec3 point; // 충돌 지점
glm::vec3 normal; // 충돌 지점의 법선
float t; // 광선 매개변수 (거리)
bool hit; // 충돌 여부
};
}
Ray Tracer의 메인 로직 : 모든 객체를 관리하고 메인 로직을 정리
#include <vector>
#include "Ray.h"
#include "Sphere.h"
#include "Hit.h"
namespace hlab {
class RayTracer {
public:
std::vector<Sphere> objects;
void AddObject(const Sphere& obj) {
objects.push_back(obj);
}
glm::vec3 TraceRay(const Ray& ray) {
HitRecord closestHit;
closestHit.t = std::numeric_limits<float>::max();
closestHit.hit = false;
for (const auto& object : objects) {
float tHit;
if (object.Intersect(ray, tHit) && tHit < closestHit.t) {
closestHit.t = tHit;
closestHit.hit = true;
closestHit.point = ray.PointAt(tHit);
closestHit.normal = glm::normalize(closestHit.point - object.center);
}
}
if (closestHit.hit) {
// 단순히 법선을 색상으로 변환하여 렌더링
return 0.5f * (closestHit.normal + glm::vec3(1.0f));
}
// 배경 색상
return glm::vec3(0.0f, 0.0f, 0.0f);
}
};
}
보다 사실적인 효과를 위해선, 조명효과(쉐이딩)를 이용해야 합니다.
우선 광선과의 거리에 따라 렌더링되는 구를 살펴보았습니다.
감사합니다.
'Graphic > Computer Graphics' 카테고리의 다른 글
[Graphics] Compute Shader 알아보기 (0) | 2025.04.03 |
---|---|
[Graphics] Barycentric Coordinate System 알아보기 (0) | 2025.03.10 |
[Graphics] Rasterization과 Ray tracing의 차이 (0) | 2025.02.21 |
[Graphics] Phong Reflection Model(Ambient / Diffuse / Specular) 이해하기 (0) | 2025.02.04 |
[Graphics] vcpkg_imgui 설치하기 (1) | 2025.01.15 |