render to fbo problem (ray-casting)

Hi!
I have implemented a Ray-Casting algorithm using GPU. I’m having a framebuffer object with 3 textures attached to it (1 for the front face of the cube, one for the backface and one in which I would like to have my results). Of course I have a 3d texture too.

Code where I define textures and attach them to the farame buffer:

 	glGenTextures(1, &backfaceTex);
	glBindTexture(GL_TEXTURE_2D, backfaceTex);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
	glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA16F_ARB, WINDOW_SIZE, WINDOW_SIZE, 0, GL_RGBA, GL_FLOAT, NULL);

	glGenTextures(1, &frontfaceTex);
	glBindTexture(GL_TEXTURE_2D, frontfaceTex);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
	glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA16F_ARB, WINDOW_SIZE, WINDOW_SIZE, 0, GL_RGBA, GL_FLOAT, NULL);

	glGenTextures(1, &final_image);
	glBindTexture(GL_TEXTURE_2D, final_image);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
	glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA16F_ARB, WINDOW_SIZE, WINDOW_SIZE, 0, GL_RGBA, GL_FLOAT, NULL);
glGenFramebuffersEXT(1, &framebuffer);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,framebuffer);

	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, backfaceTex, 0);
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, frontfaceTex, 0);
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, final_image, 0);

	glGenRenderbuffersEXT(1, &renderbuffer);
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer);
	glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, WINDOW_SIZE, WINDOW_SIZE);
	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderbuffer);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

code for getting the two textures needed at ray casting:

 void drawCubesToTextures()
{
	static float rotate = 0; 
	//rotate += 15.25;
	//std::cout<<rotate<<std::endl;
	glPushMatrix();

	resize(WINDOW_SIZE,WINDOW_SIZE);
	glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, framebuffer);
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer);

	glLoadIdentity();
	glTranslatef(0,0,-2.25);
	glRotatef(rotate,0,0,1);
	glTranslatef(-0.5,-0.5,-0.5);// center the texturecube

	glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, framebuffer);
//Back face cube
	glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	glEnable(GL_CULL_FACE);
	glCullFace(GL_FRONT);
	drawQuads(1.0,1.0, 1.0);
	glDisable(GL_CULL_FACE);
//end Back face cube
//Front face cube
	glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);
	drawQuads(1.0,1.0, 1.0);
	glDisable(GL_CULL_FACE);

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	glPopMatrix();
//end Front face cube
}

display function, where my problem appears: How to get the final image rendered to final_image texture, as in the code presented below it does not matter what texture I’m binding, or if I’m binding any, the volumetric image obtained after the ray casting algorithm will appear. (ray casting works just fine, I just want to put the result in the final_image texture)

 void display()
{
	drawCubesToTextures();
	
	GLint location1,location2, location3D, locationTF;

//trying to render to GL_COLOR_ATTACHMENT2_EXT (final_image)

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
	glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );


	setShaders();
	
	location1=glGetUniformLocationARB(p,"frontTexture");
	glActiveTextureARB(GL_TEXTURE0_ARB);
	glBindTexture(GL_TEXTURE_2D, frontfaceTex);
	glUniform1iARB(location1, 0);

	location2=glGetUniformLocationARB(p,"backTexture");
	glActiveTextureARB(GL_TEXTURE1_ARB);
	glBindTexture(GL_TEXTURE_2D, backfaceTex);
	glUniform1iARB(location2, 1);

	location3D=glGetUniformLocationARB(p,"texture3d");
	glActiveTextureARB(GL_TEXTURE2_ARB);
	glBindTexture(GL_TEXTURE_3D, texName3d);
	glUniform1iARB(location3D, 2);

	locationTF=glGetUniformLocationARB(p,"texTF");
	glActiveTextureARB(GL_TEXTURE3_ARB);
	glBindTexture(GL_TEXTURE_1D, texTF);
	glUniform1iARB(locationTF, 3);

	printInfoLog(v);
	printInfoLog(f);

	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);
	drawQuads(1.0,1.0, 1.0);
	glDisable(GL_CULL_FACE);

	releaseShaders();

	//display final image
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	glLoadIdentity();
	reshape_ortho(WINDOW_SIZE,WINDOW_SIZE);
	glEnable(GL_TEXTURE_2D);
//?????????????
	//glBindTexture(GL_TEXTURE_2D,final_image);
	glBindTexture(GL_TEXTURE_2D,frontfaceTex);
///??????????????
	glBegin( GL_QUADS );
		glTexCoord2d(0.0,0.0); glVertex2f(0.0,0.0);
		glTexCoord2d(1.0,0.0); glVertex2f(1.0,0.0);
		glTexCoord2d(1.0,1.0); glVertex2f(1.0,1.0);
		glTexCoord2d(0.0,1.0); glVertex2f(0.0,1.0);
	glEnd();
	glutSwapBuffers();
}

Shaders:

varying vec2 texCoord;
varying vec2 texCoord2;
varying vec3 texCoord3d;
varying vec4 Pos;
varying vec3 normal;

void main()
{
	//gl_Position = ftransform();
	Pos =  gl_ModelViewProjectionMatrix * gl_Vertex;
	texCoord = gl_MultiTexCoord0.st;
	gl_Position = Pos;
	normal =  gl_NormalMatrix * gl_Normal ;
} 
 
uniform sampler2D frontTexture;
uniform sampler2D backTexture;
uniform sampler3D texture3d;
uniform sampler1D texTF;
varying vec4 Pos;
varying vec3 normal;

varying vec2 texCoord;

void main()
{
	float stepsize=0.02;
	vec2 texc = ( (Pos.xy / Pos.w) + 1.0) / 2.0; // find the right place to lookup in the backside buffer
	texc = (Pos.xy+1.0)/2.0;
	//gl_FragColor = vec4 (0.0,0.0,0.2, 1.0);
	vec4 start = texture2D(backTexture,texCoord);
	vec4 stop = texture2D(frontTexture,texCoord);
	vec3 dir = -start.xyz + stop.xyz;
	float len = length (dir.xyz);
	vec3 norm_dir = 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,0,0);
	float alpha_acc = 0.0;
	float length_acc = 0.0;
	vec4 color_sample;
	float alpha_sample;

	for(int i = 0; i < 8; i++)
	{
		color_sample = texture3D(texture3d,vec);
		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;
		if(length_acc >= len || alpha_acc > 1.0) break; // terminate if opacity > 1 or the ray is outside the volume
	}

	gl_FragColor =  col_acc;
	//gl_FragColor = texture1D(texTF,col_acc.r);
  
	//gl_FragColor = vec4(color_sample);
}

tnx for your help,
Paul

p.s. most of the code is from:
http://www.daimi.au.dk/~trier/?page_id=98

You could use glReadPixels, to read the data back from the screen. Alternately you could render to a FBO (frame buffer object)/PBO (pixel buffer object). I’m not precisely clear on the specifics of those, but this seems like the kind of task they would be good for.

P.S. That was a really long post. Next time, only include the parts that are relevant, as I skimmed the entire thing, found the bold, and did my best to answer the question. The shaders, for example, are not relevant to the render destination.

todayman is right there is too much code and you are finally not clear about your needs especially when your problem does not seem to be related precisely to gpu ray-casting.

How to get the final image rendered to final_image texture […]

Do you mean that you want to get the texture data back to system memory? Which texture? 2D or 3D one? Do you want to do this intensively (Each frame) or just once?

If you need to do it intensively, Readpixels or glCopyTexImage* calls coupled with PBO may be a solution. Otherwise, PBO usage may be not relevant.

Tnx for replies. I would edit my post to make it shorter, but I cannot do that, don’t know why.

I am trying to get the result from rendering the shaders in one texture (final_image) and then display that texture on the screen. (as a 2d texture) (now I am not sure that I’m getting the results in any texture)

Maybe you can answer this question for me: why the same texture is displayed when I use any of the following options (in code where the “//???” is):
1.glBindTexture(GL_TEXTURE_2D,final_image);
2.glBindTexture(GL_TEXTURE_2D,frontfaceTex);
3.none, or any other

uniform sampler2D frontTexture;
uniform sampler2D backTexture;
uniform sampler3D texture3d;
uniform sampler1D texTF;
varying vec4 Pos;
varying vec3 normal;

varying vec2 texCoord;

void main()
{
	float stepsize=0.02;
	vec2 texc = ( (Pos.xy / Pos.w) + 1.0) / 2.0; // find the right place to lookup in the backside buffer
	texc = (Pos.xy+1.0)/2.0;
	//gl_FragColor = vec4 (0.0,0.0,0.2, 1.0);
	vec4 start = texture2D(backTexture,texCoord);
	vec4 stop = texture2D(frontTexture,texCoord);
	vec3 dir = -start.xyz + stop.xyz;
	float len = length (dir.xyz);
	vec3 norm_dir = 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,0,0);
	float alpha_acc = 0.0;
	float length_acc = 0.0;
	vec4 color_sample;
	float alpha_sample;

	for(int i = 0; i < 8; i++)
	{
		color_sample = texture3D(texture3d,vec);
		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;
		if(length_acc >= len || alpha_acc > 1.0) break; // terminate if opacity > 1 or the ray is outside the volume
	}

	gl_FragColor =  col_acc;
	//gl_FragColor = texture1D(texTF,col_acc.r);
  
	//gl_FragColor = vec4(color_sample);
}

I don’t know any OpenGL, but I have used shaders quite a lot, and it strikes me there may be a few issues with your GLSL code.

vec2 texc = ( (Pos.xy / Pos.w) + 1.0) / 2.0;

‘Pos.xy’ looks like a hangover from Peter’s original Cg shader. You need something like

vec2 texc = gl_TexCoord[0].xy;

Which uses the buildin gl_TexCoord varying, rather than using your own custom varying. I think it’s good practice to use builtin varyings where available.
You don’t need to multiply and offset, since texture coordinates in OpenGL usually go from 0 to 1 anyway.

You would also need to setup the texture coords in the Vertex Shader, like so:

gl_TexCoord[0] = gl_TextureMatrix[0] * glMultiTexCoord0;

This should give the the correct coordinates to lookup the back and front-face textures.

Having said all that, I’ve been working on the same GPU Raycasting code, and I’ve not got it to work at all, unfortunately.

Hope this helps a bit, and good luck!

a|x

Which uses the buildin gl_TexCoord varying, rather than using your own custom varying. I think it’s good practice to use builtin varyings where available.
You don’t need to multiply and offset, since texture coordinates in OpenGL usually go from 0 to 1 anyway.

Why? gl_TexCoord is deprecated since the 1.3 release and using this built-in do not always correspond to the meaning of its content, so you better use a well named uniform for the sake of shader code clarity.

Oh, OK dletozeun. I stand corrected, in that case.

And actually, I just realised most of what I wrote above is rubbish. Please ignore, everyone (I misread Peter Trier’s page myself)…

a|x