OpenGL Stuff

I have been playing around with OpenGL recently... and I'm going to try and post some odds and ends.

Simulating X-Ray Transmitted Irradiance

The idea: try and use OpenGL and a GPU to simulate the image you would get from either an old fashioned x-ray machine, or a more modern CT scanner. Not only does this look cool, there is an actual motivation for this. We need input data to test new tomographic reconstruction algorithms (i.e. CT scanners)... we can either use real data, which requires an expensive machine with fixed geometry, or we can simulate any kind of machine we can think up. We can also simulate with zero error, or induce any amount of error we wish.

Background:

X-ray attenuation is a measure of how much a medium reduces the intensity of x-rays passing thru it.. or how "opaque" a medium appears to x-rays. A highly attenuating material blocks x-rays better than an object with low attenuation. We can model the attenuation of an object as a function that maps points in space to values of attenuation. From this we can calculate the loss of intensity of a beam of x-rays that are passing through this object. Given an x-ray source with intensity a detector that measures the intensity and a linethat describes the set of points between the source and detector, we get:

Simulation:

OpenGL only allows one to describe an object from surfaces, and intenisty calculations require "thickness", so we need to fake it. To make this work we need to assume that any object we draw is a closed volume and has a constant attenuation value.

We create a frame buffer object (FBO) that we render our scene into. We need to use floating point values to obtain the precision needed (we used RGBA32F). When drawing an object, the color of the object (in our case just the red channel), is used to determine the objects attenuation value. We simulate the integralfor each pixel in the rendered image by accumulating "positive" or "negative" attenuation for each polygon drawn.

When we draw a polygon with a specified attenuation of we render each fragment to the screen asfor a polygon facing us, andfor a polygon facing away from us... whereis the z-depth of that fragment. Whenever we render a fragment to the buffer, we add it to the existing value.

Imagine a box, with the front face at and the back face at and an attenuation of 1. When we draw the front face, we store a value -10. When we store the back face, we add to it 25. The result is 15, which is

After rendering the entire scene into attenuation space (in the FBO), we then render into relative intensity space by taking the exponential of each pixels attenuation.

All in all, we end up using a FBO, with a vertex and fragment shader to generate the attenuation space, and then another fragment shader to render into intensity space.

After playing around with this, I found that someone else had already done this. They wrote a very nice paper on the subject, and have an almost identical approach. Here is a link to the 2009 paper by Franck P. Vidal, et al. Simulation of X-ray Attenuation on the GPU

Future Ideas:

Using an orthographic projection would simulate a parallel-beam setup. This is fairly rare, and most CT machines use a fan-beam or cone-beam configuration. We used a perspective view, because it looks nice to humans... setting up a true cone-beam geometry would require manually calculating the project matrix. A fan-beam would be identical to a cone-beam, but only using the center stripe of pixels.

The use of multiple color channels (there are 4: red, green, blue, alpha) could be used to simulate a multi-energy machine.

Downloads:

Here is the software example that I wrote: atten1.zip

It has been released under the GPL 3.0 License.