[index]

# Anton's Research Ramblings

## Real-Time Ray-Tracer in OpenGL using Compute Shaders

Yesterday, I upgraded the previous post's single-threaded CPU-based ray-tracer demo. I replaced the CPU-based ray-tracing operations with compute shaders, which use the parallelism of the GPU. This gave me a speed up of more than 10 times. The documentation/instruction material available for this, rather new, OpenGL feature is pretty lacking - there are not many tutorials, and the reference information isn't very instructional. Eventually I found the information that I needed, but the details/features are not communicated with sensible context. I'll try to make a tutorial or set of instructions for getting started with a minimal demo like this.

The basic idea is that each pixel in my 800x800 display area fires a mathematical ray forward, and checks if it hits the sphere. Instead of calculating this on the CPU, I write this in a compute shader. GL has this very confused notion of work unit division in global and local allotments and different dimensions. Basically, I wanted one ray calculation to run for each pixel. The way to do this is to say that each pixel is a work unit, and we can say that we have a two-dimensional set of work units - 800x800 of them. Each compute shader processes a "work group" - it is repeated for an arbitrary range of these work units. To maximise parallelism we can say that a compute shader invocation will process one work item in its work group. [I tried doing larger subdivisions and it went more and more slowly - I guess it must do these one after the other, rather than in a parallel slot]. To do this we write a layout() instruction in the compute shader says that it will only process one 1x1 subdivision of the total work unit area. The advantage of using a 2d work unit area is that it is then trivial to work out which pixel co-ordinate (x,y) we are processing for inside the compute shader. With this we can work out the ray origin and direction, and we also know which pixel to write to for the output. I also do the intersection test inside the shader, and write the result to a pixel in an image.