seen

12-13-2006, 10:32 PM

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.

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.