I’ve also been messing around with Peter Peter Trier’s GPU Raycasting setup, but I thought it would be better if I started my own thread, rather than hijacking herpaul’s earlier one, since I’m taking a slightly different tack.
I’ve got Peter’s setup semi-working as an isosurface renderer. Well, I say ‘semi-working’: it looks quite interesting, but is also quite broken.
As you can see from the screenshots below, there’s definitely a sense of depth, but the view ‘through’ each face of the cube doesn’t match up with the views through the other faces. Also, as the cubes are rotated, the the apparent depth of the isosurface, as viewed through each face decreases, until as the face is viewed more obliquely, the appearance is is a 2D slice through the isosurface, stuck to the surface of the face.
(The small graphics at bottom-left represent the front and back faces of the cube, and the vector created by subtracting colour values, as described on Peter’s blog).
Unfortunately, I don’t have access to a Windows PC, so I’ve not been able to see Peter’s demo application in action, so I don’t know if the ray volume is meant to be rotated. On the other hand, even when viewed without rotation, my version still doesn’t look quite right.
Here’s the shader code:
// VERTEX SHADER
varying vec4 pos;
void main()
{
//Transform vertex by modelview and projection matrices
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
pos = gl_Position;
//Forward current color and texture coordinates after applying texture matrix
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
}
// FRAGMENT SHADER
uniform sampler2D BackBuffer, VolTex;
uniform float StepSize;
uniform float IsoValue;
uniform vec4 IsoColor;
uniform vec3 IsoScale;
uniform vec3 IsoOffset;
uniform vec2 IsoThreshold;
varying vec4 pos;
void main()
{
// Find the right place to lookup in the backside buffer
vec2 texc = ((pos.xy / pos.w) + 1.0) / 2.0;
vec4 start = gl_TexCoord[0];
vec4 back_position = texture2D(BackBuffer, texc);
vec3 dir = back_position.xyz - start.xyz;
// The length from front to back is calculated and used to terminate the ray
float len = length(dir.xyz);
vec3 norm_dir = normalize(dir);
float delta = StepSize;
vec3 delta_dir = norm_dir * delta;
float delta_dir_len = length(delta_dir);
vec3 vec = start.xyz;
vec4 col_acc = vec4(0.0);
float alpha_acc = 0.0;
float length_acc = 0.0;
vec4 color_sample = vec4(0.0);
float alpha_sample = 0.0;
// Main raycast loop
for(int i = 0; i < 450; i++)
{
vec3 vectmp = (vec * 2.0 - 1.0) * IsoScale + IsoOffset;
// Borg surface formula from Paul Bourke's site
// http://local.wasp.uwa.edu.au/~pbourke/geometry/borg/
//float borg = sin(vectmp.x * vectmp.y) + sin(vectmp.y * vectmp.z) + sin(vectmp.z * vectmp.x);
float blob = pow(vectmp.x,2.0) + pow(vectmp.y,2.0) + pow(vectmp.z,2.0) +
sin(4.0*vectmp.x) + sin(4.0*vectmp.y) + sin(4.0*vectmp.z) - 1.0;
color_sample.rgb = IsoColor.rgb;
//color_sample.a = (borg > IsoThreshold[0] && borg < IsoThreshold[1]) ? 1.0 : 0.0;
color_sample.a = (blob > IsoThreshold[0] && blob < IsoThreshold[1]) ? 1.0 : 0.0;
alpha_sample = color_sample.a * StepSize;
col_acc += (1.0 - alpha_acc) * color_sample * alpha_sample * 3.0;
alpha_acc += alpha_sample;
vec += delta_dir;
length_acc += delta_dir_len;
// Terminate if opacity > 1 or the ray is outside the volume
if(length_acc >= len || alpha_acc > 1.0) break; }
//Multiply color by texture
gl_FragColor = vec4(col_acc);
}
The shader runs on the cube with backface-culling applied, taking the frontface-culled cube rendering as input to the ‘back_buffer’ uniform.
I’m sure there’s something simple I’m doing wrong, but I’ve no idea what.
Any help would be much appreciated!
Cheers,