Hi I have written a program to perform a GLSL ray cast. It seems to be working, except when I rotate my model, it doesn’t rotate right that is it skews itself and kind of rotates weird and parts of the volume get distorted, and a smaller image of the model is created in the centre through continuous rotation.
All am simply doing is create three textures with the help of 3 FBO’s. I render the back and front faces separately as 2 textures, and the last texture contains the result of the ray cast.
If someone has any idea what is wrong, please help me out. My relevant code is below.
/* Display Function */
void RayCaster::renderRayCast()
{
float ratio = float(width)/float(height);
// Fill screen with viewport
glViewport(0, 0, width, height);
// Reset projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set a 45 degree perspective
gluPerspective(45, ratio, 0.0, 25);
// Reset Modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, zoom);
glRotatef(rotAngleY, 0.0, 1.0, 0.0);
glRotatef(rotAngleX, 1.0, 0.0, 0.0);
glMultMatrixf(rotMat);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Ray Start (Render to FBO)
glBindFramebuffer(GL_FRAMEBUFFER, fboRayStart);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
glUseProgram(rayVertexProgram);
drawQuads(1.0, 1.0, 1.0);
glUseProgram(0);
glDisable(GL_CULL_FACE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, texRayStart);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
// Ray Stop (Render to FBO)
glBindFramebuffer(GL_FRAMEBUFFER, fboRayStop);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glUseProgram(rayVertexProgram);
drawQuads(1.0, 1.0, 1.0);
glUseProgram(0);
glDisable(GL_CULL_FACE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, texRayStop);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
// Ray Cast (Render to FBO)
glBindFramebuffer(GL_FRAMEBUFFER, fboResult);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram(rayCasterProgram);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_3D, volumeTex);
utilities.setUniform("Volume", 2);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_3D, gradientTex);
utilities.setUniform("Gradient", 3);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texRayStop);
utilities.setUniform("RayStop", 1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texRayStart);
utilities.setUniform("RayStart", 0);
//utilities.setUniform("IsoValue", isoValue);
//utilities.setUniform("Absorption", absorption);
drawQuads(1.0, 1.0, 1.0);
glUseProgram(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, texResult);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Render to Quad
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texResult);
reshapeOrtho(width, height);
glColor4f(1.0, 1.0, 1.0, 1.0);
drawFullscreenQuad();
glDisable(GL_TEXTURE_2D);
}
/* Shader */
varying vec4 vPosition;
uniform sampler2D RayStart;
uniform sampler2D RayStop;
uniform sampler3D Volume;
uniform sampler3D Gradient;
uniform sampler2D TransferFunc;
const float StepLength = 0.01;
const float Threshold = 0.45;
vec3 LightPosition = vec3(5.0, 5.0, 15.0);
vec3 DiffuseMaterial = vec3(0.05, 0.05, 0.05);
float lookup(vec3 coord)
{
vec3 V = texture3D(Volume, coord).xyz;
return dot(V, V);
}
void main()
{
vec2 coord = 0.5 * (vPosition.xy + 1.0);
vec3 rayStart = texture2D(RayStart, coord).xyz;
vec3 rayStop = texture2D(RayStop, coord).xyz;
if (rayStart == rayStop) {
discard;
return;
}
vec3 ray = rayStop - rayStart;
float rayLength = length(ray);
vec3 stepVector = StepLength * ray / rayLength;
vec3 pos = rayStart;
vec4 dst = vec4(0);
while (dst.a < 1.0 && rayLength > 0.0) {
float V = lookup(pos);
if (V > Threshold) {
// Refine the hitpoint to reduce slicing artifacts:
vec3 s = -stepVector * 0.5;
pos += s;
V = lookup(pos);
if (V > Threshold)
s *= 0.5; else s *= -0.5;
pos += s;
V = lookup(pos);
if (V > Threshold)
{
float L = StepLength;
float E = lookup(pos + vec3(L,0,0));
float N = lookup(pos + vec3(0,L,0));
float U = lookup(pos + vec3(0,0,L));
vec3 normal = normalize(gl_NormalMatrix * vec3(E - V, N - V, U - V));
vec3 light = LightPosition;
float df = abs(dot(normal, light));
vec3 color = df * DiffuseMaterial;
vec4 src = vec4(color, 1.0);
dst = (1.0 - dst.a) * src + dst;
break;
}
}
pos += stepVector;
rayLength -= StepLength;
}
gl_FragColor = dst;
}