Suppose we have a basic ray tracer where we send a shadow and reflection ray.

The basic code (where rgb colors geometric vectors are vec3) will look like:

vec3 rayColor(ray r, int depth) {

vec3 color(0)

if (depth > maxDepth) return color

if (hitsScene(r)) { // somehow this passes back state like hitpoint p

if (Rs > 0) { // Rs is rgb specular reflectance

ray s(p, reflect(r, N))

color += rayColor(s, depth+1)

}

if (Rd > 0) { //Rd is rgb diffuse reflectance

ray shadow(p, L) // L is the direction to the one light

if (not hitsScene(shadow)) {

color += Rd*lightColor*max(0, dot(N,L) )

}

}

}

else

color = background(r)

return color

}

The three spheres we add to get fuzzy effect. |

*s()*that returns a random point in a unit sphere centered at the origin (see last blog post). All we need to do is randomly perturb each shadow and specular reflection ray, and we can generate another diffuse ray that will get bounce light. This is:

vec3 rayColor(ray r, int depth) {

vec3 color(0)

if (depth > maxDepth) return color

if (hitsScene(r)) { // somehow this passes back state like hitpoint p

if (Rs > 0) { // Rs is rgb specular reflectance

// radius_specular is a material parameter where 0 = perfect

ray s(p, reflect(r, N)+ radius_specular*rs())

color += rayColor(s, depth+1)

}

if (Rd > 0) { //Rd is rgb diffuse reflectance

ray shadow(p, L + radius_shadow*rs()) // L is the direction to the one light

if (not hitsScene(shadow)) {

color += Rd*lightColor*max(0, dot(N,L) )

}

ray diffuse(p, N + rs()) // assumes N is unit length

color += Rd*rayColor(diffuse, depth+1)

}

}

else

color = background(r)

return color

}

## 2 comments:

The code can't seem to decide if rs is a variable or a function.

Trying to force a world-space endpoint into the ray definition doesn't seem helpful, especially given that the original code doesn't do it. I think it would be clearer if rs was a parameterless function (e.g., it returned a random vector in the unit sphere centered at the origin). Then you could use:

ray shadow(p, L + rs() * radius_diffuse)

Alternatively, mention that the 2-parameter form could be used as an alias for a direction perturbation function:

#define perturbDirection rs

ray shadow(p, perturbDirection(L, radius_diffuse))

You are right; that code will be much cleaner! Thanks!

The comment above will not make a lot of sense once I change the blog post to reflect the suggestion: for those that want to see what the fuss was if the rs(center, radius) function is used (as it was in the original blog post) with the ray endpoint as the "center" the code is much uglier.

Post a Comment