The very last chapter of the book teases, briefly, about the concept of "area lights". These are light sources with physical dimension, which cast soft, diffuse shadows, rather than the hard, crisp shadows of point light sources. They can greatly enhance the realism of your scenes, but they come at a cost: your ray tracer has to work a lot harder to render those soft shadows!
Still, the payoff is worth it. Find out for yourself in the very first bonus chapter for The Ray Tracer Challenge:
In this chapter you'll learn how to construct a rectangular area light, make a first attempt at soft shadows by using a regular grid of samples, and then improve the shadows by adding randomness how the sample points are selected. It's all done just as in the book, with unit tests and pseudocode, and includes the scene description for the chapter's banner scene, as well. Give it a try!
As ascotti said, the two vectors describe the directions of the light's edges. If you look at the diagram at the beginning of section 3 ("Area Lights"), you'll see one edge labelled "vvec" and one labelled "uvec". Those vectors describe which direction those edges point relative to the corner.
ascottiJamis Thanks Got! I was thinking in 2D and working in 2D. It now makes sense. Because I was not thinking correctly when creating an area light I was dividing the X and Z coordinate to create uvec and vvec by usteps and vsteps. Instead of dividing the whole vector by the steps. Doooh! Then when I was working on the scenarios using Y coordinate I was confused.
For the Scenario: The area light with jittered samples I end up with a contribution of 0.25 vs the expected 0.5 on the point(1, -1, 2). The other 4 in the array are coming out with the expected value.
Also, I think I was pretty tired by the time I got to it so my other tests that are failing are in Scenario Outline: lighting() samples the area light. I'm only getting the ambient contribution as the light_dot_normal is coming out negative in my lighting computation. I know the text said that the position is no longer needed and could be removed, but my pattern_at_shape function to get the color still uses it?
In the sample Yaml for the chapter, jitter is set to true. What does the value of true actually mean in this context? Each sample should be a random value between 0 and 1?
there are multiple questions, I will give feedback and add some questions
Your first question I don't have enough information, but I was wondering if your sequencer you built for testing is a ring implementation? Does it start over if it reaches the end of the sequence?
For Scenario Outline: lighting() samples are you looping through the samples of each point in the area light? Is the light_vector using the light_position of the current instance of the cell from the loop of cells in the area light? I will share my lighting function, but keep in mind I pass the computation as a parameter instead of the individual properties of the computations. So you might be wondering why I'm not passing many parameters to the function. Also using c#. Lighting
You mentioned that pattern_at_shape uses light.position but I don't see that in the code I have written. What I see is that pattern_at_shape translates a word location to a local location, but no dependency on light.position. Can you elaborate on this?
Regarding the jitter true/false, this will allow for the area light to have jitter or not. How I implemented this was to build off the concept of the sequence used in testing. Testing uses a deterministic ring sequence. I also built a non-deterministic sequence which returns a random number. The test ask for a sequence of numbers, sequence(0.1, 0.5, 1.0). If jitter is false then I use a sequence with only one number, .5. Which mean .5 is returned ever time Next() is called. If jitter is true, I assign the attribute/property jitter_by with a non-deterministic sequence that returns a random number.
I reviewed some code, but nothing sticks out. Have you tried either debugging and stepping through code to see if the expected values are present, or output trace information?
The math would indicate that there are 4 samples and the IsShadow should be true for 2 iteration of the 4 which would give you the 0.5 results. I'm going to assume that 3 of the iterations not returning true giving you only 1 IsShadow true which will then give you 0.25 as a result.
Below are the values of the IntensityAt function, which you might also want to evaluate the PointOnLight function making sure you are getting the correct jitter values.