Skip to content

Commit eea12d0

Browse files
committed
Replace ray triangle intersection with MOLLER TRUMBORE
1 parent f2c11dd commit eea12d0

File tree

6 files changed

+72
-28
lines changed

6 files changed

+72
-28
lines changed

ray-tracing-cuda/ray.cu

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ __device__ __host__ Ray::Ray(vec3 position, vec3 direction)
1010
direction_ = normalize(direction);
1111
}
1212

13-
__device__ __host__ vec3 Ray::position() const { return position_; }
13+
__device__ __host__ const vec3 Ray::position() const { return position_; }
1414

15-
__device__ __host__ vec3 Ray::direction() const { return direction_; }
15+
__device__ __host__ const vec3 Ray::direction() const { return direction_; }

ray-tracing-cuda/ray.cuh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ class Ray {
66
public:
77
__device__ __host__ Ray();
88
__device__ __host__ Ray(glm::vec3 position, glm::vec3 direction);
9-
__device__ __host__ glm::vec3 position() const;
10-
__device__ __host__ glm::vec3 direction() const;
9+
__device__ __host__ const glm::vec3 position() const;
10+
__device__ __host__ const glm::vec3 direction() const;
1111

1212
private:
1313
glm::vec3 position_, direction_;

ray-tracing-cuda/ray_tracing.cu

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,16 @@
66
#include "utils.cuh"
77

88
using glm::vec3;
9-
using std::pair;
109

1110
constexpr int TRACE_DEPTH_LIMIT = 10;
1211

1312
__device__ glm::vec3 Trace(HitableList *world, Ray ray, curandState *states) {
14-
struct Layer {
15-
vec3 emitted;
16-
vec3 attenuation;
17-
};
18-
1913
Layer storage[TRACE_DEPTH_LIMIT];
2014

2115
int storage_size = 0;
2216

17+
bool should_debug = false;
18+
2319
vec3 result;
2420
for (int depth = 0;; depth++) {
2521
HitRecord record;
@@ -39,11 +35,18 @@ __device__ glm::vec3 Trace(HitableList *world, Ray ray, curandState *states) {
3935
result = emitted;
4036
break;
4137
}
38+
storage[storage_size].t = record.t;
39+
storage[storage_size].pos = ray.position();
40+
storage[storage_size].target = hit_point;
4241
storage[storage_size].emitted = emitted;
4342
storage[storage_size++].attenuation = attenuation;
4443
ray = reflection;
4544
}
4645

46+
if (should_debug) {
47+
DebugTracePath(storage, storage_size);
48+
}
49+
4750
for (int i = storage_size - 1; i >= 0; i--) {
4851
result = storage[i].emitted + storage[i].attenuation * result;
4952
}

ray-tracing-cuda/ray_tracing.cuh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
#include "hitable_list.cuh"
77
#include "ray.cuh"
88

9+
struct Layer {
10+
glm::vec3 pos;
11+
double t;
12+
glm::vec3 target;
13+
glm::vec3 emitted;
14+
glm::vec3 attenuation;
15+
};
16+
917
__device__ glm::vec3 Trace(HitableList *world, Ray ray);
1018

1119
__global__ void RayTracing(HitableList *world, Camera *camera, int height,

ray-tracing-cuda/utils.cu

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
#ifndef STB_IMAGE_WRITE_IMPLEMENTATION
22
#define STB_IMAGE_WRITE_IMPLEMENTATION
33
#endif
4+
#ifndef GLM_ENABLE_EXPERIMENTAL
5+
#define GLM_ENABLE_EXPERIMENTAL
6+
#endif
47

58
#include <glog/logging.h>
69
#include <stb_image_write.h>
710

811
#include <fstream>
12+
#include <glm/gtx/intersect.hpp>
913
#include <string>
1014

1115
#include "hitable.cuh"
1216
#include "ray.cuh"
17+
#include "ray_tracing.cuh"
1318
#include "utils.cuh"
1419

1520
using glm::cross;
@@ -22,26 +27,38 @@ __global__ void CudaRandomInit(uint64_t seed, curandState *state) {
2227
curand_init(seed, idx, 0, &state[idx]);
2328
}
2429

25-
__device__ bool TriangleHit(vec3 p[3], const Ray &ray, double t_from,
30+
__device__ bool TriangleHit(const vec3 p[3], const Ray &ray, double t_from,
2631
double t_to, double *out_t, vec3 *out_normal) {
27-
vec3 n = normalize(cross(p[2] - p[0], p[1] - p[2]));
28-
double den = dot(ray.direction(), n);
29-
double num = dot(p[0] - ray.position(), n);
30-
double t = num / den;
31-
if (std::isnan(t) || std::isinf(t)) return false;
32-
if (t < t_from || t > t_to) return false;
33-
vec3 hit_point = ray.position() + (float)t * ray.direction();
34-
{
35-
double dot_values[3];
36-
for (int i = 0; i < 3; i++) {
37-
vec3 a = p[i], b = p[(i + 1) % 3];
38-
dot_values[i] = dot(cross(a - hit_point, b - hit_point), n);
39-
}
40-
for (int i = 0; i < 3; i++)
41-
if (dot_values[i] * dot_values[(i + 1) % 3] < 0) return false;
32+
// MOLLER_TRUMBORE
33+
double eps = 1e-7;
34+
vec3 v0v1 = p[1] - p[0];
35+
vec3 v0v2 = p[2] - p[0];
36+
vec3 pvec = cross(ray.direction(), v0v2);
37+
float det = dot(v0v1, pvec);
38+
39+
// ray and triangle are parallel if det is close to 0
40+
if (fabs(det) < eps) return false;
41+
42+
float invDet = 1 / det;
43+
44+
vec3 tvec = ray.position() - p[0];
45+
float u = dot(tvec, pvec) * invDet;
46+
if (u < 0 || u > 1) return false;
47+
48+
vec3 qvec = cross(tvec, v0v1);
49+
float v = dot(ray.direction(), qvec) * invDet;
50+
if (v < 0 || u + v > 1) return false;
51+
52+
float t = dot(v0v2, qvec) * invDet;
53+
54+
if (!(t_from <= t && t <= t_to)) {
55+
return false;
4256
}
57+
4358
*out_t = t;
44-
*out_normal = dot(n, ray.direction()) < 0 ? n : -n;
59+
vec3 n = normalize(cross(v0v1, v0v2));
60+
*out_normal = dot(ray.direction(), n) < 0 ? n : -n;
61+
4562
return true;
4663
}
4764

@@ -55,3 +72,16 @@ void WriteImage(std::vector<vec3> &pixels, int height, int width,
5572
LOG(INFO) << "Writing image to " << path << "...";
5673
stbi_write_jpg(path.c_str(), width, height, 3, data.data(), 100);
5774
}
75+
76+
__device__ void DebugTracePath(Layer *layers, int n) {
77+
for (int i = 0; i < n; i++) {
78+
printf(
79+
"[%d] (%.3f, %.3f, %.3f) -> (%.3f, %.3f, %.3f) with t: %.3f, "
80+
"attenuation: (%.3f, %.3f, %.3f), emitted: (%.3f, %.3f, %.3f)\n",
81+
i, layers[i].pos[0], layers[i].pos[1], layers[i].pos[2],
82+
layers[i].target[0], layers[i].target[1], layers[i].target[2],
83+
layers[i].t, layers[i].attenuation[0], layers[i].attenuation[1],
84+
layers[i].attenuation[2], layers[i].emitted[0], layers[i].emitted[1],
85+
layers[i].emitted[2]);
86+
}
87+
}

ray-tracing-cuda/utils.cuh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ __global__ void CudaRandomInit(uint64_t seed, curandState *state);
2323
void WriteImage(std::vector<glm::vec3> &pixels, int height, int width,
2424
const std::string &path);
2525

26-
__device__ bool TriangleHit(glm::vec3 p[3], const Ray &ray, double t_from,
26+
__device__ bool TriangleHit(const glm::vec3 p[3], const Ray &ray, double t_from,
2727
double t_to, double *out_t, glm::vec3 *out_normal);
2828

2929
template <typename T>
@@ -48,3 +48,6 @@ __device__ void QuickSort(
4848
if (j > low) QuickSort(array, low, j, comp);
4949
if (i < high) QuickSort(array, i, high, comp);
5050
}
51+
52+
struct Layer;
53+
__device__ void DebugTracePath(Layer *layers, int n);

0 commit comments

Comments
 (0)