The Ray Tracer Challenge: Page 130 Wall

@jamis

Page 130 I render the wall ok by rotating the plane in x PI/2 as he says to do on page 125.
However I get a massive shadow across the entire wall. Why is that happening?

Seen here : https://www.scfdev.com/test/render1.png

Hmm! Maybe a self-intersection? Although it doesn’t look dark enough for a shadow. Compare that with how dark the spheres’ shadows are. I wonder if it’s actually something in the shading calculation?

The best way to track this is to do something like the following:

  1. Find the <x,y> pixel coordinates of a point in your image that’s misbehaving. (This could be any of the pixels in the image that are showing the shadow in question.)

  2. Run your render for just that pixel.

  3. Add a breakpoint (or a bunch of print statements, if you’re like me) when you cast your shadow rays, and see what object they’re intersecting. (I suspect they’re not intersecting anything, but this will tell you for sure.) If there are no intersections, do this again but with a breakpoint/print in the shading routing, and step through it, looking at the computed values there.

Given that the darker shade seems to appear right about eye-level, I suspect there might be something in how your reflection vector is being computed?

If none of that helps, let me know where you’ve got your code hosted and I’d be happy to take a look and see if anything jumps out at me.

Thanks. I’m almost through chapter 11 at the moment, I’ll try your suggestions.

Hi Jamis,
I think I resolved this in the local_normal_at function.

I was setting the plane’s normal to 0,1,0 but then multiplying it by the plane.transform matrix
which I thought I would need to do if the plane is rotated. ? This caused the light_dot_normal to be < 0 during the top half of the render so the diffuse and specular returned black.

If I just set the local_normal to 0,1,0 it’s fine but I’m confused as to why I don’t need to
transform the normal along with the plane.

Ah! Good catch. Right, the local normal-at function will receive a point that is already transformed into the local object space. The calling function (normal_at) will then transform the result back into world space. So yes, it really is as simple as just returning (0,1,0) from the local normal_at function.