Hi,
I’m having severe problems with this shader, which does a volume rendering of a 3d-texture and optionally checks against the z-buffer.
It works well enough as written, but if I try to remove the texture-fetch from the z-buffer it fails, and goes black (or some other color). I’ve checked that len and len2 are similar, and I can plot each, and I use len2 in the for loop, but … I still can’t remove the lines doing the z-buffer step, that kills the output just stops completely.
If I replace the texture lookup with 1, 0 or anything in between, it fails. (The value should be 1, since the z-buffer is cleared and nothing is drawn there.)
I can’t for the life figure out why this happens, and why I don’t get an error message in that case.
Do I trigger some compiler bug, or is it just an error in my code?
This is on an NVIDIA GTX 260, Vista 32-bit sp2, driver 185.85.
#version 120
uniform sampler3D volume;
uniform sampler2D depth;
uniform bool inverse;
uniform float min_intensity;
uniform float max_intensity;
uniform float resolution;
uniform float texture_lod;
uniform float far;
uniform float near;
uniform vec2 viewport_size;
centroid varying vec3 tex;
varying vec3 vtx;
varying vec3 plane_n_model;
float convertZ(in float depthBufferValue)
{
float clipZ = ( depthBufferValue - 0.5 ) * 2.0;
return -(2.0 * far * near) / ( clipZ * ( far - near ) - ( far + near ));
}
void rayPlaneIntersection(vec3 r_pos, vec3 r_dir, vec3 p_normal, float p_dist, inout float len)
{
// assume r_dir & p_normal are normalized
// from http://www.cs.princeton.edu/courses/archive/fall00/cs426/lectures/raycast/sld017.htm
float x = dot(r_dir, p_normal);
if (x < 0.0) {
float t = (dot(r_pos, p_normal) + p_dist) / -x;
len = min(len, t);
}
}
// intersect with [0,0,0] - [1,1,1] cube
void computeRayLength(vec3 p, vec3 v, inout float len)
{
rayPlaneIntersection(p, v, vec3(-1.0, 0.0, 0.0), 1.0, len);
rayPlaneIntersection(p, v, vec3(1.0, 0.0, 0.0), 0.0, len);
rayPlaneIntersection(p, v, vec3(0.0, -1.0, 0.0), 1.0, len);
rayPlaneIntersection(p, v, vec3(0.0, 1.0, 0.0), 0.0, len);
rayPlaneIntersection(p, v, vec3(0.0, 0.0, -1.0), 1.0, len);
rayPlaneIntersection(p, v, vec3(0.0, 0.0, 1.0), 0.0, len);
}
void main()
{
// precompute useful coord
vec2 fbo_tc = gl_FragCoord.xy * viewport_size;
// intersect with unit cube
vec3 view_v = vtx - gl_ModelViewMatrixInverse[3].xyz; // camera to surface point
vec3 view = normalize(view_v); // direction through volume
float len = sqrt(3.0);
computeRayLength(vtx, view, len);
float len2 = len;
// intersect with z-plane at z-buffer value (not needed here, but shader fails to produce pixels otherwise!?!)
float z = texture2D(depth, fbo_tc).r;
float plane_dist = convertZ(z);
vec3 plane_p_model = (gl_ModelViewMatrixInverse * vec4(0, 0, -plane_dist, 1)).xyz; // plane point in model
float plane_dist_model = -dot(plane_n_model, plane_p_model); // distance from origo to plane in model
rayPlaneIntersection(vtx, view, plane_n_model, plane_dist_model, len);
// setup iteration parameters
float step = 1.0 / resolution; // step length
float end = len2 * resolution; // max iterations
float acc = 0.0; // intensity accumulator
vec3 v = view * step; // texture step vector
vec3 p = tex; // texture coordinate
// do large steps for majority of the volume
float i = 0.0;
for(; i < end - 8.0; i += 8.0) {
acc += texture3D(volume, p += v, texture_lod).r;
acc += texture3D(volume, p += v, texture_lod).r;
acc += texture3D(volume, p += v, texture_lod).r;
acc += texture3D(volume, p += v, texture_lod).r;
acc += texture3D(volume, p += v, texture_lod).r;
acc += texture3D(volume, p += v, texture_lod).r;
acc += texture3D(volume, p += v, texture_lod).r;
acc += texture3D(volume, p += v, texture_lod).r;
}
// compute the last parts (important if limited by solid geometry, less so at edge)
for(; i < end; i++) {
acc += texture3D(volume, p += v, texture_lod).r;
}
// normalize and rangify
acc *= step;
acc -= min_intensity;
acc *= 1.0 / (max_intensity - min_intensity);
// output
// gl_FragColor.rgb = vec3(inverse);
// gl_FragColor.a = acc
gl_FragColor.r = len;
gl_FragColor.b = len2;
gl_FragColor.g = inverse ? 1.0 : 0.0;
gl_FragColor.a = acc;
}