technology from back to front

Toy raytracer in Python

I spent a few days in Wellington recently with my 12-year-old brother. We somehow got to talking about ray tracing, and so we ran through a bit of linear algebra (vectors, normals, and dot products, basically) and built ourselves a raytracer in Python as a lark. We collaborated on the Vector and Point classes, and I filled in the rest of the program. There’s still a bug in the checkerboard code (see the odd horizontal lines in the reflection of the checkerboard in the yellow sphere?) but it’s not too awful for an afternoon’s idle hacking.

The code is contained within raytrace.py, and here’s the output it generates:

Raytracer output

Wouldn’t it be nice to have classes like Vector and Point as part of the standard distribution of Python? Even better, though, and perhaps less subject to bike-shed debates, would be the inclusion of a simple, small PNG-writing module like this one as part of standalone base Python!

by
tonyg
on
29/10/08
  1. Pretty neat. Y’know, I’ve done a PNG Canvas library for a few years now:

    http://the.taoofmac.com/space/Projects/PNGCanvas

    It might be interesting to put all of them together somehow.

  2. Absolutely! I’d love to see a basic Canvas interface grow up, backed by (say) PNG as well as mappable to surfaces offered by the various GUI libraries out there. Sadly, even systems as beginner-friendly as Python still make it very, very difficult to get pixels on screen. A simple Canvas would be a big step in the right direction.

  3. TuckerBeck
    on 18/02/09 at 11:07 pm

    Both things you are looking for are already available.

    Points, Vectors – > Numpy’s array objects (support vector math and very fast too )

    PNG writer -> Python Imaging Library

    Both are ridiculously easy to implement for this sort of thing.

  4. TuckerBeck, readily available yes, but not part of base python.

  5. Hi tonyg,

    that bug you describe concerning the lines of the checkerboard is probably not a bug, but something one calls the aliasing effect. Aliasing happens when you sample something with a too low frequency. You shouldn’t worry too much about this, however, since you’ve just dived into the matter, as you said. Why not try some fancy other raytracing stuff instead of dealing with the aliasing? :)

    Keep on,
    Frank

  6. [...] hat jemand einen Toy-Raytracer mit Python [...]

  7. If you just want to play about with graphics, Nodebox is a great way to do it in python with all of that stuff built in.

  8. Peter: Nodebox looks lovely! It does seem to be OS X specific, though. I’d love for there to be a consistent, cross-platform approach to simple graphics in some reasonable programming language. (See: squeak smalltalk.)

    Frank: It doesn’t look like an aliasing effect. It looks more like some kind of sign or rounding problem. Re: slightly fancier raytracing: the low hanging fruit, I’d say, would be CSG… :-)

  9. Hi tonyg, I’m trying to understand how intersection works in your code, but fail till now. Can you please explain what happens in intersectionTime function of Sphere class, and maybe outline how it would look for another primitive like Cone?

  10. Victor: how is your vector math, are you familiar with dot products and the like? It’s hard to explain without diagrams, but if you try to figure out how you would implement intersectionTime then this implementation may become clearer.

  11. Over a year later, I found that bug – you don’t take either the origin of the ray or of the plane into account when computing the intersection distance, only the dot product of their direction vectors. Have fixed in local version, shall I push to hg?

  12. Hi Paul,
    I didn’t find a bug yet, so it would be nice to see a fix :) I’m ok with vector math, but still I don’t understand why the sphere works and my cone – not :) to be more specific – here’s mine implementation (it renders something, which is definitively not cone :(:

  13. oops the code is stripped out from the comment. you can find it here: http://etherpad.com/51Zq0cdWhf

  14. I may be even wrong and it works, but I cant position it properly. Anyway – example output:
    [URL=http://www.picamatic.com/view/6189859tmp/][IMG]http://www.picamatic.com/show/2009/12/04/07/57/6189859bigthumb.png[/IMG][/URL]

  15. @Paul: yes please!

    @Victor: intersectionTime is meant (if I remember rightly!) to return how far along the given ray, if at all, an intersection between the ray and the surface of the object happens, in units of multiples of ray.vector (so a value of n returned from intersectionTime indicates that the first intersection happens at a point (ray.point + n * ray.vector)). I haven’t looked closely at your code, but from the presence of the quadratic equation it looks like you’re on the right track :-) What does it render currently?

  16. @tonyg
    actually looks like cone when reflected in the yelow sphere (I didn’t change the scene). I never managed to position the camer properly though :) And my code fails simple tests in 2d, which shall work fine, so I suppose the equation is wrong somehow.

  17. Damn! A raytracer under 400 lines of code. Readable code, no less! Shame about the speed, but it goes with the VM territory, I guess.. Does running it with Psyco make a difference?

  18. @pieter: I’m afraid I don’t remember :-) but since I left the code for loading psyco in there, I suspect it probably did make a difference. It’d be interesting to see what PyPy does with it.

  19. Arek Czechowski
    on 10/04/13 at 8:10 am

    Hello Sir – I’ve taken your code and rewrote in coffeescript to compare speed, I hope you don’t mind. Code is here: https://github.com/agend07/coffee_raytracer

    Arek

  20. Arek, that’s very cool! Thanks very much for letting us know.

 
 


− 5 = zero

2000-14 LShift Ltd, 1st Floor, Hoxton Point, 6 Rufus Street, London, N1 6PE, UK+44 (0)20 7729 7060   Contact us