Tuesday, May 15, 2007

Correct Reflections and Specular Lighting

Well, this is the first big milestone in the project. My ray tracer now actually renders something that looks believable, abstract, but believable. I corrected the bugs in the reflection ray calculations so reflections now show up on the correct side of the sphere. In addition, I added specular highlights as well. So now the spheres look like shiny balls that reflect their surroundings.

The algorithms are grossly inefficient. I don't really care at this point. :) I will have to go back in and refactor a lot of the code to fix the naive assumptions I made about ray tracing as I was just getting started. I only have one picture to post at this time. I am in the middle of upgrading my linux distribution from gentoo 2006.01 to the 2007.01 profile. This basically means I have to recompile every single library and executable on my machine. Since the dependant libs must be compiled first, sometimes apps stop working periodically. Apps like my ray tracer. *sigh*

I still need to add shadows. I couldn't get it to work before, but I think that fixing the reflections, will fix the shadows as well, since calculating the shadow rays, reflection rays and surface normals are very, very similar. I'll post more images when I can.



I decided to start using flickr for the renders I post. I added a few more renders, you can see them here.

Monday, May 7, 2007

Ray Tracer: Reflections

Ok, so this is quickly becoming nothing more than a blog to chronicle my progression through creating a ray tracer. I've decided to give in to inevitability and simply accept that this is a ray tracing blog. So, I will now feel free to dig into some more detail. For those of you who just want to see the pretty pictures, feel free to ignore the text.

Apparently, Brandon didn't like the verbal beating I gave him in the last post (yeah, he's *that* petty). :) He ran off and created his own ray tracer, with his own associated blog (http://brandonray07.blogspot.com). Not to be outdone, I simply have to update my blog. I must say though, he copped out and is writing his ray tracer in Ruby. I love ruby, I do, its a sweet language. It also isn't very fast for things like ray tracing. In essence, he is cheating (yes, I am *that* petty). :D

I have to admit I am stumped on the shadow ray code to detect if a surface is in shadow. I have spun my wheels on that piece of code for at least a week. I decided to push ahead and go for reflections and specular lighting. The reflections piece is fairly simple. If a light ray hits something, it bounces off. I just have to calculate the angle at which it reflects and the handle the reflected light ray just like any other ray. This is a really cool concept and it is one of the key benefits of ray tracing. It is also simpler to implement than I thought.

As a fortunate side effect of the reflections, I think I finally have a clue what is causing the shadow ray code such difficulty. The sphere's are rendering as though they are both opaque and completely transparent. You can see this in the middle sphere in the reflection images below. The reflection of the blue sphere should be hidden from the camera, but it is being "projected" onto the inside of the sphere on the opposite side of the sphere. Anyway, It is tough to explain, but its plain to me. Since I have to fix it, that works well. :)

Enjoy the latest images:


Friday, April 27, 2007

MRTS (More Ray Tracer Stuff)

I took some time out of working on the ray tracing algorithm to fix a few nagging bugs and make it easier to specify the scene that I am rendering. I fixed the bug that caused spheres to render distorted if they were off center. I also fixed the lighting code and fixed a bug that caused any sphere not at the origin to be incorrectly shaded. Probably the biggest change was to move the definition of the scene outside of the code and into a data file. Now I can change the scene very quickly without a recompile. That is very handy for testing, and for just having fun with it to see how the lighting model behaves if I move a sphere or there, or change the light sources, etc...

Here is a sample XML scene definition, and the image it created. For my co-worker (*ahem* Brandon) that takes issue with rendering the light sources... DEAL WITH IT! :D

 
<scene>
<light_sources>
<color name='blue_light' red='0x00' green='0x00' blue='0xff' />
<color name='red_light' red='0xff' green='0x00' blue='0x00' />
<color name='white_light' red='0xff' green='0xff' blue='0xff' />

<sphere x=' 5.0' y='-5.0' z='-2' radius='0.1' color='white_light' />
<sphere x='-5.0' y='-2.0' z=' 4' radius='0.1' color='white_light' />
</light_sources>

<objects>
<color name='clr' red='0xff' green='0xff' blue='0xff' />

<sphere x=' 0' y=' 0' z='0' radius='1.5' color='clr' />
<sphere x=' 0' y='-10' z='0' radius='1.5' color='clr' />
<sphere x=' 0' y=' 10' z='0' radius='1.5' color='clr' />
<sphere x=' 10' y=' 0' z='0' radius='1.5' color='clr' />
<sphere x='-10' y=' 0' z='0' radius='1.5' color='clr' />
<sphere x=' 10' y=' 10' z='0' radius='1.5' color='clr' />
<sphere x=' 10' y='-10' z='0' radius='1.5' color='clr' />
<sphere x='-10' y=' 10' z='0' radius='1.5' color='clr' />
<sphere x='-10' y='-10' z='0' radius='1.5' color='clr' />
</objects>
</scene>

The purpose of this scene is to show how the light is reflected differently off each sphere depending on where the light sources are. With no further delay, here is the image:


And since Brandon wants to see code so badly, here you go:

int main(int argc, char ** argv) {
// do stuff
}

Till next time, when I plan to add either anti-aliasing, secondary rays, or specular lighting, or perhaps some combination of those items. Stay tuned!

Update:
So I outdid myself. It is apparently really easy to add antialiasing to a ray tracer. It just kills performance. The main gist is this, instead of sending out just one ray per pixel in the image, I send out 4, each offset slightly, I then take the average of each ray and set that to the be value for the new pixel. Here is the same scene above with antialiasing. Notice how the sphere's boundaries are not so pixelated, they are smoother. Now, I just need to generalize the code to handle any number of rays per pixel, not just four. I'm getting ahead of myself. Enjoy the image:

Saturday, April 21, 2007

More Ray Tracer Stuff

I have been asked what a ray tracer is. Simply put, (haha, I know it sounds crazy that I'd assocciate simple with it...), a ray tracer is a piece of software that models rays of light and the physics that govern them. Think of an image captured by a camera, now think of how the light got from the sun to the photographic medium. It all starts out some 93 million miles away as the sun radiates light in all directions. A miniscule fraction of those light rays travel that 93 million miles, pass through the atmosphere, hit the grass, trees, water, mountains, people, goats, and whatever else you may be in the your scene. Each time the light hits a surface it bounces off and makes it through the lens of the camera and gets recorded on the film (or SD card).

That is exactly what a ray tracer does, except in reverse. It would be horribly wasteful to calculate all the rays that eminate from a light source, in hopes that a few will eventually make it to the image. Instead, a ray tracer starts with the simplifying assumption that the only light rays we care to map are the ones that actually make it to the camera, and so that is how the processing is done. Conceptually, we just shoot light rays backwards through the scene and bounce them off objects in a scene and if the ray eventualy hits a light source, then we know that we can color the corresponding pixel of the image according to the objects that the ray bounced off from. In all, its a lot of trigonometry.

And, in answer to your question Dad, it is exactly the same as a mathematical ray. I have been visiting Wikipedia, a lot, to refresh my brain on the quadratic equation, vectors, dot products, and general trigonometry. As a sampling, I took the equation for a 3D sphere and the equation for a ray/line and solved to find the distance along the ray where the ray intersects the sphere, this is the result:
I then solve that equation and, voila!, I know if a ray hit the sphere! Got it? ;)

Here are some images of the latest work on the ray tracer. I added light sources and some diffuse shading of the sphere. The sphere now actually looks something like a sphere, and less like a plain circle.


This the first image I rendered where it actually looks like a sphere. The light source is off image to the upper left. My heart skipped a beat out of sheer surprise when it came out looking so clean and clear (and correct). :)

This image is after a few hours of bug fixing, and adding in a ambient light factor. This is an image of a blue sphere with two light sources, way off in the distance, they are visible in the image as two white dots to the upper left and right of the sphere. Notice how the shading of the sphere is different based on the position of the light sources. The upper left light is further away, and so its shading is different.

Now, I just need to blog about something that is not ray tracing related, lest this become a ray tracing blog. *hrmm...* Forget it, I'm pretty focussed on this thing for now, I fully intend that this ray tracer becomes part of a software portfolio that I can share with future prospective employers. Till next time...

Tuesday, April 17, 2007

Ray Tracer II

Turns out I was debugging code that wasn't buggy. If you look in the pictures below, you will see that the spheres that are off-center are distorted the same thing can be found here. So, I added more spheres to the scene. Each of these spheres have the same radius and the four groups of spheres, top left, top right, bottom left and bottom right, are all positioned directly behind each other. The only difference is that they are all placed at different distances away from the camera. The perspective is near impossible to see with the current coloring scheme, but I'll get that working soon too. I also played around with the camera a bit, moving it left, right, and zooming in. The resultant images can be found below.

I know this doesn't seem like much, but its pretty cool that the spheres are all properly scaled and the perspective is correct without any special code. I just move around the camera and the objects in the scene, and everything gets correctly displayed. Its really cool, really... *sigh*

This is original image with the camera centered:

This is the same image with the camera still centered, but zoomed in:

This is the same image with the camera moved to the left:
Once again, the same image, but this time the camera is moved to
the right:


Monday, April 16, 2007

Ray Tracer

I am currently working on a ray tracer in my spare time. Eventually, it will create really pretty 3D pictures. But that is still a ways off. Before I get ahead of myself, I decided to undertake this project to keep my skills sharp. A ray tracer is relatively simple, well, at least conceptually. Converting it to a working application is another matter.

I started with a simple blank file named raytrace.cpp. I was determined to do everything from scratch, using no existing libraries. The first task was to create a simple blank image. Sounds easy, and it is. I decided to use the PPM file format, which is a simple pixel map file simile similar to a Windows .bmp file, but the file format is dead simple. I did not save an image from this stage of the application, it was a simple black image, completely unremarkable in every way. :)

Stage two, that is shoot out rays from camera and color object in the scene with an arbitrary color, was a bit more difficult. Being that I am not a graphics programmer, and my last math class was about 5 years ago, I had to relearn the basic concepts of vectors, rays, points, spheres matrix transforms and trig. Once I had the basics after about a week of reading in my spare time, I then had to translate that into code. At this stage the project consists of 14 files and about 350 lines of code, 550 if you include my comments. I finally got this stage kind of working last night at about 4:30 AM. With a single sphere in the scene, the current state of the project is:
The next stages are to add more spheres to the scene and add shading, then I will begin bouncing the rays and adding light sources. Stay tuned...

-Michael

Welcome to my world!

I plan to post lots of general information here. Some of it technical, some of it about my family, but all of it about stuff I find interesting and important.

I am a C/C++ programmer by trade. I greatly prefer working in Linux and Unix server environments. I am familiar with socket programming and have created a custom networking protocol as part of the VMAC research project at BYU. I am extremely passionate about high quality software engineering. I am currently leading a group at Cerner to revise C/C++ development tools and practices to address widely acknowledged engineering difficulties.

I am very opinionated, and I am willing to debate those opinions. After years of active involvement in the Open Source community, I have forged and honed these debating skills. BEWARE! :) I am an avid proponent against all things Microsoft. It is my opinion that a computer requires a certain level of understaning to operate correctly, and anything that attempts to make it too simple (i.e. Microsoft Windows) creates communities of people that do not understand computers. You wouldn't purchase and operate a thousand dollar piece of woodworking equipment without understanding how it works. Why are computers different?

On a more personal note, I have been married 10 years, and I am the father of two beautiful daughters. I served a two year church mission in Concepcion, Chile in South America and I still pretend to be fluent in Spanish, though I lack opportunities to speak it. I graduated from Brigham Young University with a degree in Computer Science. I am avid BYU football fan, Basketball is ok, and I don't follow most any other sport.

As you might have noticed, I still haven't decided what this blog will be. One thing is certain, I hope to update the status of my current projects on this blog. Stay tuned. Well, ok, so no one is tuned in yet. *sigh*

-brailsmt