Hi All,
I have a fragment shader for volume rendering using ray casting:
- Include early ray termination.
- Gradient estimation + gradient filtered texture.
- In/Out texture (using bounding volumes of the active nodes)
Currently the code run fine on G80.
Can any of you suggest how to improve this GLSL code:
(There are some disabled paths (jitter) that I want to enable in the future)
#define EPSILON (0.01)
// Uniform samplers block
uniform sampler2D rayLeaveTex;
uniform sampler2D rayEnterTex;
uniform sampler1D transferTex;
uniform sampler3D volumeTex;
uniform sampler3D gradTex;
uniform sampler2D jitterTex;
// Interpolated frag position
varying vec4 pos;
// Interpolated light position: (gl_ModelViewProjectionMatrixInverse * vert position);
varying vec3 lightPos;
vec3 CalcGrad(vec3 rayPos)
{
vec3 gradient;
float x1 = texture3D(volumeTex, rayPos-vec3(EPSILON,0.0,0.0)).a;
float x2 = texture3D(volumeTex, rayPos+vec3(EPSILON,0.0,0.0)).a;
float y1 = texture3D(volumeTex, rayPos-vec3(0.0,EPSILON,0.0)).a;
float y2 = texture3D(volumeTex, rayPos+vec3(0.0,EPSILON,0.0)).a;
float z1 = texture3D(volumeTex, rayPos-vec3(0.0,0.0,EPSILON)).a;
float z2 = texture3D(volumeTex, rayPos+vec3(0.0,0.0,EPSILON)).a;
gradient.x = x2-x1;
gradient.y = y2-y1;
gradient.z = z2-z1;
return normalize(gradient);
}
void main (void)
{
// Sample the texture to get the leave/enter position
vec2 texturePos = ((pos.xy / pos.w) + 1.0) / 2.0;
vec4 rayLeave = texture2D(rayLeaveTex, texturePos);
vec4 rayEntry = texture2D(rayEnterTex, texturePos);
// Calculate ray and segment length
float segmentLength = length(rayLeave - rayEntry);
vec3 rayDir = normalize(rayLeave.xyz - rayEntry.xyz);
float walkLength = 0.0;
// Calculate ray step
vec3 ray = rayEntry.xyz;
// Jitter texture lower grain artifacts
//vec2 rayJitter = texture2D(jitterTex, texturePos).xy;
//ray.xy += rayJitter;
vec3 rayStep = rayDir*0.002;
float rayStepLength = length(rayStep);
int numSteps = int((segmentLength / rayStepLength) + 1);
vec4 blendedColor = vec4(0.0,0.0,0.0,0.0);
for(int i = 0; i < numSteps; i++)
{
// Get the intensity
vec4 intensity= texture3D(volumeTex, ray.xyz);
// Look up color for the fragment
vec4 color = texture1D(transferTex, intensity.a);
// todo - 0.3 should be non constant threshold value
if (color.a > 0.3)
{
// Gradient
// Calc the gradient
//vec3 gradient = CalcGrad(ray.xyz);
// Get the gradient from filtered gradient texture
vec3 gradient = texture3D(gradTex,ray.xyz).xyz;
gradient = gradient*vec3(2,2,2) - vec3(1,1,1);
vec3 vecLight = normalize(normalize(lightPos) - ray.xyz);
vec diffuseTerm = abs(dot(vecLight, gradient));
color.rgb *= 0.25;
color.rgb += vec3(diffuseTerm, diffuseTerm , diffuseTerm )* color.a;
}
// Blend (FTB)
blendedColor.rgb += (1.0 - blendedColor.a) * color.rgb;
blendedColor.a += (1.0 - blendedColor.a) * color.a;
// Advance ray and accumulated distance
ray += rayStep;
walkLength += rayStepLength;
// Break if out of bounding volume or opaque
if(walkLength >= segmentLength || color.a >= 1.0)
{
break;
}
}
gl_FragColor = blendedColor * vec4(0.5,0.5,0.0,1.0);
}
Thanks,
Ido