Raytracing a sphere : primary rays

So I was thinking about writing a little bejeweled style game the other day and thought it’d be good enuff to have some shaded balls for the jewels.

Naturally, I decided to write small raytracer.

In case you missed the excellent “Raytracing Topics & Techniques” by Jacco Bikker, here is a quick break down of how a raytracer works: for each pixel at (x,y) in our image, we cast a ray, eg: from (x,y,0) to (x,y,-1).

Casting a ray involves checking to see which object it would hit / intersect first.

In the case of sphere’s, there is a pretty straight forward bit of black magic we can hijack from povray:

        public double rayIntersection( Pt start, Pt stop ) {
            // start_to_sphere = start - center_of_sphere
            Pt start_to_sphere = new Pt( start, center_of_sphere );

            double radius2 = radius_of_sphere * radius_of_sphere;

            double dv = stop.dot( start_to_sphere );

            double stop_length2 = stop.lengthSquared();
            double start_to_sphere_length2 = start_to_sphere.lengthSquared();
            double start_to_surface_of_sphere = start_to_sphere_length2 - radius2;

            double determinant = (
                ( dv * dv )
                -
                ( stop_length2 * start_to_surface_of_sphere )
            );

            double result = -1;
            if( determinant >= 0 ) {
                determinant = Math.sqrt( determinant );
                double t1 = ( -dv + determinant ) / stop_length2;
                double t2 = ( -dv - determinant ) / stop_length2;
                result = ( ( t1 = 0 ) || t2 < 0 ) ? t1 : t2;
            }
            return result;
        }

I know that looks cryptic and nasty, but the bottom line is that this will return a number from 0-1 to indicate how far along the ray the hit occurred or -1 if no hit occured.

Using a single ray per pixel and this using the distance value to weight the red, green and blue values for the sphere produced a result like this:

in about 0.320 of a second.

Looks pretty crappy, huh? Bet you could do better in the gimp in about that amount of time! 😛

Whatever… that was just the primary ray. The primary ray is neat, it tells us where the ray hit on what (player hater?), but why doesn’t it look that neat?

The reason is cuz there is no lighting model…

SPOILER WARNING: RayBall.java

BTW, if someone can give me a more descriptive (and accurate) name for that “dv” variable, I’ll happily change it. The changes from the povray example seem to work, cuz after all pt.dot( pt ) = pt.distanceSquared(), right?

———————
IE must be destroyed.

Advertisements

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: