RayTracing / raytracing.github.io

Main Web Site (Online Books)
https://raytracing.github.io/
Creative Commons Zero v1.0 Universal
8.84k stars 868 forks source link

A non recursive implementation of `ray_color` #624

Open D-K-E opened 4 years ago

D-K-E commented 4 years ago

I would like to suggest a simple non recursive implementation for ray_color function to be mentioned in an alternative listing during the first book around chapter 8.

I realize that it is maybe outside of the current scope of the first book, where everything is as simple as possible. However, since portability is also a concern for the first book, and it is not possible to use recursion in glsl and OpenCL, it might help to briefly at least mention a non recursive implementation from which the reader might build her own version for more complicated stuff later on.

Here is my proposition:

color ray_color2(const Ray &r, const HittableList &scene, int depth) {
  Ray r_in = Ray(r.origin, r.direction);
  color rcolor = color(1,1,1);
  while (true) {
    HitRecord record;
    if (depth <= 0) {
      // final case
      return color(0);
    }
    if (scene.hit(r_in, 0.001, INF, record)) {
      // recursive case
      point3 target = record.point + random_in_hemisphere(record.normal);
      r_in = Ray(record.point, target - record.point);
      depth--;
      rcolor *= 0.5;
    } else {
      // no hit so bye
      vec3 direction = unit_vector(r_in.direction);
      double temp = 0.5 * (direction.y() + 1.0);
      rcolor *= (1.0 - temp) * color(1,1,1) + temp * color(0.5, 0.7, 1.0);
      return rcolor;
    }
  }
}

Note that I am not using any call stack to emulate the recursion. The function correctly renders the figure in Rendering of diffuse spheres with hemispherical scattering, I also ported it to glsl and it works over there as well.

trevordblack commented 4 years ago

There have been a couple of public implementations in languages or environments that discourage recursion, e.g. Cuda, OptiX, OpenCL, GLSL

I think that having two implementations of the main rendering loop would be overkill, and I think that recursion is the KISS version of the two. But, I'm open to suggestions.

D-K-E commented 4 years ago

I also admit that recursion reads more easily, and it also models better the underlying equation.

Having said that, I also noticed that through listing 34 - 40, we are slowly building up the ray_color for lambertian surfaces by tweaking the distribution function along the way and at the end an alternative implementation with random_in_hemisphere is provided. I thought it would fit the overall flow of the chapter to mention a non recursive implementation while the rendering loop is still simple before passing to metals.

My initial research, aka googling, showed only implementations with a call stack using preprocessor variables of the type #define MAX_BOUNDS etc, so I thought it might be an improvement to implement the function without it.

It would be great to have at least a link to a public non recursive implementation in section 13.2: Next Steps for those who are trying to port what's here to an environment that discourages recursion.

trevordblack commented 4 years ago

https://github.com/RayTracing/raytracing.github.io/wiki/Implementations-in-Other-Languages

See: Cuda

I'm not sure if we're still broadcasting this wiki page.

@hollasch Are we?

hollasch commented 4 years ago

broadcasting == advertising? Not that much. It's still up and readable to the general public. I don't know if anyone with a GitHub account can edit.

trevordblack commented 4 years ago

It's up and readable, but do we have a link up anywhere?

-------- Original Message -------- On May 28, 2020, 21:18, Steve Hollasch wrote:

broadcasting == advertising? Not that much. It's still up and readable to the general public. I don't know if anyone with a GitHub account can edit.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

hollasch commented 4 years ago

Looks like it's only mentioned in the src README's. We should probably note this in the project web page.

D-K-E commented 4 years ago

The implementation I am seeing in the link uses a constant value for iteration, not much different than using a preprocessor directive and a call stack. However it would have been a good pointer if I had known it before.

Morozov-5F commented 3 years ago

I have tried to implement an iterative variant of the rendering ray_colour function and I've managed to make a working variant which produces the same results as recursive option for scenes from "The Next Week" book. Here's the link: https://github.com/Morozov-5F/raytracing-weekend/blob/96aab798a0d72dc67bcc3d0d54f26c063bac856f/main.c#L93 (note that it's in C).