This is an introductory project to GSLS (GL Shading Language). Isosurfaces are like the contours on a map except for they are 3D surfaces rather than lines. Contours consist of points on the same height in a terrain. Isosurfaces consist of points that have the same density (intensity) in a 3D image. Here, by a 3D image we mean a 3D array of '3D pixels' (called voxels).
Sometimes, contours or isosurfaces are called level sets since they consist of points on the same 'level'.
Isosurfaces are used for many purposes, one of them being visualization of medical images such as Computed Tomography (CT) or Magnetic Resonance Imaging (MRI) scans. Although triangle mesh models of isosurfaces can be computed explicitly and just rendered as 3D surfaces, one can do without that to get isosurface images. In this project, you'll implement a simple isosurface renderer using 3D texturing and programmable shading.
The algorithm you'll be implementing basically draws a family of parallel squares perpendicular to the viewing direction.
The squares are going to be textured using the 3D texture we will provide (basically, some kind of a medical 3D image). The texture coordinates are going to be designed so that the planes will actually be consecutive slices through the image. For example, initial texture coordinates assuming there are 9 slices are show in the figure above.
Of course, if you just render the planes as you used to do in the previous projects, you'll just see the first one on the screen. Fortunately, they are tricks you can use to get something more interesting.
The first one is rejecting fragments based on their properties. Rejecting a fragment means that it does not influence the frame buffer (in particular, color or depth of the corresponding pixel). Rejecting a fragment is very simple: you just say 'discard' in the fragment shader. Of course, discard will normally appear in a conditional statement.
Let's say that you discard fragments darker than some constant (called the isovalue) c. What you are going to see on your screen is now more interesting. Basically, all points on the squares with intensity less than c are not drawn, so you'll be seeing an outline of the volume consisting of points with intensity above c. This means that what you actually will actually be seeing the surface formed by points with intensity exactly c (this is the boundary of that volume!).
Now, all we need to do is to do some reasonable shading to add 3D look to the isosurface. One can do that by just using the usual illumination formula. But what normal should one use? Well, the normal to the isosurface, that can be computed as the gradient of the intensity (look up 'gradient' and 'level set' in wikipedia.org if you don't remember your calculus). To simplify things, we'll execute the illumination formula for every fragment (even for fragments that are not visible). This may be slow on poor graphics cards.