A reasonably speedy Python ray tracer

AlexeyBrin | 162 points

I made one in Javascript a long time ago :) http://renderer.ivank.net/

After some time you can get this: http://renderer.ivank.net/balls.jpg :)

Edit: I am glad you like it! I also made this fully-GPU renderer (actually, it is a game): http://powerstones.ivank.net/

IvanK_net | 6 years ago

As the author of the original version, I'm very glad to see such an improvement !

My IPython Cookbook contains increasingly optimized versions with Cython as an illustration of how to use this library to accelerate Python code. The fastest Cython version is 300x faster than pure Python ; a lot of Python/NumPy overhead is bypassed by reimplementing the logic in, basically, C. The OpenMP multicore GIL-releasing version is roughly 4x faster than the fastest Cython version on a quadcore computer. (https://github.com/ipython-books/cookbook-code/tree/master/n...)

There is also a GPU reimplementation (in OpenGL/GLSL) in the VisPy examples (https://github.com/vispy/vispy/blob/master/examples/demo/glo...), it is animated and runs in real time.

rossant | 6 years ago

For anyone without any idea how to do this, Ray Tracing in a Weekend is a good introduction. It teaches you to do the image in the cover in a pretty short time. https://www.amazon.com/gp/product/B01B5AODD8

Mauricio_ | 6 years ago

While cool, it should be pointed out that this way of ordering things doesn't really scale with scene complexity (more objects, more complex triangular meshes requiring acceleration structures) or image size, as the number of masks required to determine visibility would become very prohibitive.

One of the great things about raytracing (at least the basics before you get to more complicated light transport), is how simple the normal recursive algorithm is for rendering a scene. This method in the article complicates that greatly with the mask passes, and I guess could be termed a wavefront renderer.

berkut | 6 years ago

I wrote a pure python (No Numpy) ray tracer as a learning exercise. Spoiler: it was slowwwwwwwwwww.

I converted to NumPy and it was just slow. I then went to array broadcasting (which required surprisingly few code changes due to NumPy being pretty awesome) and it became fast.

Marazan | 6 years ago

Anyone besides me disturbed that one of the code samples had function that took 3 parameters, 2 of which where 'O' and 'D'? I had to look at it a few times before I realized those were different variables.

m00s3 | 6 years ago

Out of curiosity, I did a little digging around. I really need to take a step back and actually understand what is going on fully with the code, but a quick trot through cProfile showed a lot of effort hitting the dot method of vec3, primarily via abs(self) under the norm method.

There's a useful library for python called numexpr, http://numexpr.readthedocs.io/, which can speed up numpy operations, leveraging multiple cores etc. (and Intel's VML library if you have it installed), one I've been aware of but never got around to trying out.

At a quick stab, it seems like it can't take properties of classes? Either way, modifying dot a bit:

    def dot(self, other):
        self_x = self.x
        other_x = other.x
        self_y = self.y
        other_y = other.y
        self_z = self.z
        other_z = other.z
        return ne.evaluate("(self_x * other_x) + (self_y * other_y) + (self_z * other_z)")

at 400x400 this slows things down a little. Once you get above about 800x800 it starts to draw equal. By the time you get to 2000x2000 it's shaving some 10% of the execution time.

edit: here's a quick stab at using numexpr at just the most obvious places, without trying to consider major code refactoring. Note this bumps up the resolution to 2000x2000

https://gist.github.com/twirrim/64f523fd5e8be86eb392b90e9222...

compared to rt3 (at same resolution), I knock off over 10% on this 2015 retina mac:

  $ python rt3.py && python rt4.py
  Took 5.78933000565
  Took 4.9023668766
Twirrim | 6 years ago

In college I built a raytracer in Rust, and I have to say it was one of the most valuable learning experiences I have ever had.

webkike | 6 years ago

Are the reflections in examples like this physically correct? My brain kind of expects the floor to be strongly curved when reflected in the sphere. Maybe it's just the unfamiliar, unrealistic environment?

ricardobeat | 6 years ago

The demos that come with embree do simple stuff like this in real time, which would be about 450 times faster, so I wouldn't call this 'reasonably speedy'.

CyberDildonics | 6 years ago

I’ve got a list of random resources here:

https://github.com/melling/ComputerGraphics/blob/master/ray_...

melling | 6 years ago
[deleted]
| 6 years ago

I'd be interested in how this compares to one optimized by Numba.

gravypod | 6 years ago

now do a Tensorflow version!

make3 | 6 years ago