I’ve been working on building a volume renderer the past few weeks. A book I bought, Real Time Volume Graphics http://www.real-time-volume-graphics.org/ has been very helpful. Good read.
So far I’ve implemented a 2D slice based object aligned renderer that supports tri-linear interpolation via a fragment shader and multi-texturing. Tonight I hacked up a version strictly based upon 3D textures. Both produce OK output, but I’m really interested in seeing how a raycaster would look here. Not too concerned about performance, I’ll be using fast hardware (nVidia 3400 and up) with small volumes (256^3). I’m interested in getting better visuals so I started to look into single pass raycasting.
So I’m reading the chapter on raycasting and there’s a fragment shader provided that should implement most everything you’d need:
http://www.real-time-volume-graphics.org/?page_id=14
http://www.cg.informatik.uni-siegen.de/data/Tutorials/EG2006/RTVG04_GPU_Raycasting.pdf
// Cg fragment shader code for single-pass ray casting
float4 main(float4 TexCoord0 : TEXCOORD0,
uniform sampler3D SamplerDataVolume,
uniform sampler1D SamplerTransferFunction,
uniform float3 camera,
uniform float stepsize,
uniform float3 volExtentMin,
uniform float3 volExtentMax
) : COLOR
{
float4 value;
float scalar;
//Initialize accumulated color and opacity
float4 dst = float4(0,0,0,0);
//Determine volume entry position
float3 position = TexCoord0.xyz;
//Compute ray direction
float3 direction = TexCoord0.xyz - camera;
direction = normalize(direction);
//Loop for ray traversal
for(int i = 0;i < 200;i++) //Some large number
{
//Data access to scalare value in 3D volume texture
value = tex3D(SamplerDataVolume, position);
scalar = value.a;
//Apply transfer function
float4 src = tex1D(SamplerTransferFunction, scalar);
//Front-to-back compositing
dst = (1.0 - dst.a) * src + dst;
//Advance ray position along ray direction
position = position + direction * stepsize;
//Ray termination: Test if outside volume...
float3 temp1 = sign(position - volExtentMin);
float3 temp2 = sign(volExtentMax - position);
float inside = dot(temp1, temp2);
//... and exit loop
if(inside < 3.0)
{
break;
}
}
return dst;
}
Problem is, I’m stuck. I have absolutly no clue as to what the C++ code should look like to fire off this shader. I mean, I understand the concept, but I really don’t know how to implement the other half. I’ve written 2D and 3D texture based volume renderers. I understand those. This GPU based raycaster has me stumped. I google’d around for some sort of simple raycaster demo w/source but I came up empty.
Can someone help me out here? I know the extents of the view volume. I’ve got a 3D texture. I have my transfer function texture defined. I understand (I think) what is meant by ‘camera’ referenced in the code, but how to fire off this shader…I’m stumped. What’s the C++ code suppose to look like?
I’m not asking for hand-holding here. If anyone can point to some source I’ll plow through it on my own. The simpler the better.