TRTC – Chapter 8 – Shadow

VartsiaSwift, TRTC

This chapter is not as big as the previous but the concept at hand is still important. There is quite a bit code in the raytracer so far an there is more to come.

Like the book says most of the code to generate shadows is there already. What is needed is to do little tweaks in the code. Nothin too big so lets dive in.

Lighting in Shadow and Testing for Shadows

If there is a point that is in shadow then there must be a object between that point and the light source. Because the diffuse and specular components are calculated using the light source vector we can’t use them when the point is in shadow. What we do is that we ignore them and use only the ambient component. This makes sense so the test is like this.

To do the implementation we must add one thing that is missing. Our newRGLighting function don’t know if the point is in shadow or not so that must be fixed first. After that it’s easy to drop the diffuse and the specular components when the point is in shadow. The newRGLighting function needs an extra argument isShadow. So here is the new newRGLighting function:

The inShadow parameter is calculated using a new isShadowed function. It looks like:

There is quite a few test cases to check if point is in shadow or not. I will not list all of them here. Like always you could found them in the source code.

At this point the book promises that only one more thing is neede before we can render shadows. There is some kind of tweak needed in the newRGShadeHit function. This tweak is needed because there is inaccuracy in floating point values. So what it means in practice is that we can’t precisely say where the ray intersect the surface. These inaccuracies aka. rounding errors means that the sphere could cast a ray on its own point of intersection.

So the solution is to adjust the point slightly in the direction of the normal, before testing for shadows. I imagine this in a way that the point jumps up from the surface into the direction of the points normal.

In code this all means that we must add an overPoint attribute in RGComputation struct and a way to calculate that attribute in newRGShadeHit function. The new RGComputation struct, prepareRGComputation function and newRGShadeHit functions are here respectively:

About the epsilon. Well the epsilon has been a round from the early beginning of this book and now I decided to change it’s implementation in my code a little. So I added an extension static function in Double which returns epsilon. It’s now hardcoded into 0.00001. This is now just for convenience. Double extensions are like this now:

And for this chapter…that was all. Wow. Those little changes in code made it capable to produce shadows. The Putting It Together part is basically the same as in chapter 7. Just the new function cals are used. You could find it in the Chapter 8 playground. The result is this image below.

Chapter 8 Putting it together image with shadows.