Raytracing a sphere : a simple point light

In the last exciting episode! We used a primary ray intersection and the distance from the collision to the viewing plane as the color.

The result was round, which is about the best you can say for it:

Once we have the distance along the ray, we also have the point where the intersection took place: start + ( start – stop ) * distance.

Now I’m going to introduce a point as a light source a (-1,-1,-1).

So now we have our sphere, our point of collision and this notion of a light. Before ya start whippin’ out the big words and fancy physics about l/d^2, lez me tells ye how this here model is gunna work!

We’ll determine the strength of the light at the point of collision based on the angular difference between the normal on the surface of the sphere at the point of collision and vector from the point of collision to the light.

I know that may seem nutty, so here is a really bad drawing to make things just that much worse:

When the angle between the vector from the collision to the light source and the normal at the pont is smaller (ie, they are closer) the light is more intense.
I tried to draw the normals like they are coming straight from the center of the sphere to the point of impact, because they are.

I know… I know… they are really appalling illustrations and yes, I do feel like I really let myself down…

This raises a couple of pretty obvious questions… First off… how do we calculate the normal from the surface of the sphere. Happily, this ends up being pretty easy to write and even easier to rip off:

        public Pt normalToPoint( Pt on_sphere ) {
            return ( new Pt( on_sphere, center_of_sphere ) ).normalize();

You may notice that I also normalize the vector. So now it has a length of 1. The reason I did that is because we are about to come to the next question: how do we calculate the angle between two vectors?

The answer is perhaps the coolest trick ever! We are going to take their dot product!

I know! Like OMG! So easy! I love dot product! It is the coolest! By taking the sum of the product of the i,j,k coefficients for the vectors we get the inverse cosine of the angle between them!

WOW! What an incredible factoid!

Deep breathe… here it is: dot(u,v) = (u.x * v.x) + (u.y * u.y) + (u.z * u.z) = acos(u,v)

So what? So what! Are you some kinda math-hater! This is math I can understand: adding stuff and multiplying stuff! Come on!

So what can we use it for in this context? Right, sure… Well… for one thing, the range of values is from -1 to +1. If the value is less than zero, the angular difference is greater than 180 degrees, so we don’t brighten the pixel since there’s no way the light could hit this spot on the sphere.

Now when the value is between 0 and 1, 1 means a lot of light and 0 means basically no light.

Before I used the distance from the source of the ray to the collision to determine how much of the color of the sphere we used in that pixel.

In this modified version, I just added the value from the dot product to the distance (making sure the sum is capped at 1) and used that.

The code can be found in the light_traceRay method of RayBall.java though I have to warn you, it still contains spoilers.

Here is the difference: ==>


IE must be destroyed.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: