I am trying to write a real time ray tracer using compute shaders in opengl 4.3. I know that this is a rather popular question. I have checked this, and this, but the architecture provided over there does not really correspond to my use case.
I am simply trying to transform the ray_color
function provided in the P. Shirley's book here into a non recursive function.
The mentioned ray_color
function:
color ray_color(const ray& r, const hittable& world, int depth) {
hit_record rec;
// If we've exceeded the ray bounce limit, no more light is gathered.
if (depth <= 0)
return color(0,0,0);
if (world.hit(r, 0.001, infinity, rec)) {
point3 target = rec.p + rec.normal + random_unit_vector();
return 0.5 * ray_color(ray(rec.p, target - rec.p), world, depth-1);
}
vec3 unit_direction = unit_vector(r.direction());
auto t = 0.5*(unit_direction.y() + 1.0);
return (1.0-t)*color(1.0, 1.0, 1.0) + t*color(0.5, 0.7, 1.0);
}
Here is my attempt:
vec3 no_hit_color(in Ray r) {
vec3 dir = normalize(r.direction);
float temp = 0.5 * (dir.y + 1.0);
vec3 cval = vec3(1.0 - temp) + temp * vec3(0.5, 0.7, 1.0);
return cval;
}
vec3 ray_color(in Ray r, in Scene scene, int depth) {
//
Ray r_in;
r_in.origin = r.origin;
r_in.direction = r.direction;
vec3 bcolor = vec3(1);
while (true) {
Ray r_out;
if (depth <= 0) {
//
return vec3(0);
}
HitRecord rec;
if (hit_scene(scene, r_in, 0.001, INFINITY, rec)) {
vec3 target = rec.point + random_in_hemisphere(rec.normal);
r_in = makeRay(rec.point, target - rec.point);
depth--;
bcolor *= 0.5;
} else {
bcolor *= no_hit_color(r_in);
return bcolor;
}
}
}
If I use a static value for depth, with something like #define MAX_DEPTH
, I think i can implement the algorithm, by making my own stack, but I would like to keep the depth as dynamic variable where I can let users tweak according to their computing power.
So I would like to implement it using while if possible.
My version produces a black slice near the bottom of the sphere, which does not correspond to the reference picture.
Update 1:
I am slightly convinced that the above implementation is correct but my camera position from which I am generating rays is problematic.
if (depth <= 0) { return vec3(0); }
should return the bcolor instead otherwise if you hit the depth limit black artifacts would occur ... – Vacuva