Wednesday, June 4, 2008

I had to post this

It's only been a couple of hours since the last post... but this is cool:

Lighting works:



The problem was that the python image library needed integers for the color value. Now it's using opengl (just  to draw points), where there is a color function that takes r,b,g float parameters.

It's starting to look nice! =) And adding reflections is going to be pretty trivial..

===Edit:
I forgot to mention that I managed to make it quite faster by removing a lot of calls to the Python C API. (i.e. defining C structures and using them instead of python tuples)
Now it is running at 1.08 the speed of the original C module. That means that I traded 8% performance for making the code less than half the size and much more easier to maintain... decent trade-off

Switched to cython

I had to spend a couple of hours today rewriting some code after reading about Cython.
I rewrote the C module to a Cython file. It runs at about 1.33 the speed of the C module, but I believe that's mainly because I'm using tuples all over the place instead of C structs. My guess is that the decrease in speed would become very moderate after optimizing. The new module also got rid of a bug in the C module where objects would disappear when being too far from the viewing plane.
Even if after optimizing there isn't a huge performance gain, I think the penalty would be well worth it. The code is less than half the length and didn't take long to write..

Here is an image:


Again, two identical, separated spheres.
There is also some primitive lighting. Note the "banding"... It is caused because the program is rounding floats to ints. Shouldn't be very tough to fix.

Sunday, June 1, 2008

More ray tracing

Yesterday I had free time for the first time in weeks!! So I worked a lot on the ray tracer...
All data structures are Python objects. However, all the ray calculation is currently done by a module written in C.
Something that is really cool, is that at the innermost loop of the ray calculation, I have a call to a python function, named "shader".  That call isn't really that expensive and it allows me to run python code at the main loop!! Not only that, the objects (for now only spheres) actually have a reference to the shader they want to use. So I can call basically any python function if I plug it into one of the spheres =)

For now, there is only one loop. The shaders will be in charge of running new loops to calculate lighting, make shadows, reflections, etc.. But for now they only fill the pixel with a determined color.

Here is a 600x300 image that took only 0.079 seconds to draw. It is noteworthy that most of that time was spent drawing pixels with the Python Image Library. A faster library will improve it a lot, and adding support for multiple processors will be easy.


They are two spheres of the same size, the green one is farther away from the eye. (The last image I posted had two spheres of different sizes with no perspective)