FBO, help !

Started by
1 comment, last by EonStrife 16 years, 3 months ago
Hi, I'm trying to do voxelization by using depth peeling techniques, the technologies involved in this are FBO, Occlusion Query, and Cg. I accomplish this by rendering to texture in each step, and then the texture is used as reference for the next step. What's rendered to the texture is just the depth value which I computed in Vertex and Fragment Shader. To determine when to stop, I use occlusion query. The problem is, seems that nothing is drawn to the texture bound to FBO, thus the occlusion query always return 0. Is there anything wrong with my implementation of FBO ? Thanks.

void voxelize()
{

	GLuint query, texReferred;
	GLuint fbo;
	GLuint sampleCount=1;
	GLfloat depthTexRef[SIZE*SIZE*3]={0.0}, depthTexture2[SIZE*SIZE*3];

	glGenFramebuffersEXT(1, &fbo);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
	glGenQueries(1, &query);

	GLUI_Master.auto_set_viewport();
	glViewport (0, 0, SIZE, SIZE);

	glGenTextures(1, &texReferred);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, texReferred);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

	glPushMatrix();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();


	cgGLEnableProfile(cgFragmentProfile);					// Enable Our Fragment Shader Profile
	cgGLEnableProfile(cgVertexProfile);					// Enable Our Vertex Shader Profile

	// Bind Our Vertex Program To The Current State
	cgGLBindProgram(cgProgramF);

	cgGLBindProgram(cgProgramV);

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

	for(int direction=0; direction<1; direction++)
	{
		sampleCount=1;
		for(int i=0; i<SIZE*SIZE*3; i++)
			depthTexRef=0.0;

		glBindTexture(GL_TEXTURE_2D, texReferred);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SIZE, SIZE, 0, GL_RGB, GL_FLOAT, depthTexRef);
	

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(-0.5, 0.5, -0.5, 0.5, 0.0, 1.0);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		switch(direction)
		{
			case DIR_FRONT:
				gluLookAt(0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

				break;
			case DIR_RIGHT:
				gluLookAt(0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

				break;
			case DIR_TOP:
				gluLookAt(0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);

				break;
		}
		model.transformModel();
 		cgGLSetStateMatrixParameter(modelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);

		while(sampleCount!=0)
		{
			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			GLuint texTarget;
			glGenTextures(1, &texTarget);
			glBindTexture(GL_TEXTURE_2D, texTarget);
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SIZE,SIZE, 0, GL_RGB, GL_FLOAT, 0);
			glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texTarget, 0);	
			glBindTexture(GL_TEXTURE_2D, texReferred);

			glBeginQuery(GL_SAMPLES_PASSED, query);
			model.drawModel();
			glEndQuery(GL_SAMPLES_PASSED);
			glGetQueryObjectuiv(query, GL_QUERY_RESULT, &sampleCount);
			cout << sampleCount << endl; //the output is 0 here, which it shouldn't happen

			//post processing
			if(sampleCount!=0)
			{
				glBindTexture(GL_TEXTURE_2D, texTarget);
				glGetTexImage(GL_TEXTURE_2D,0, GL_RGB, GL_FLOAT, depthTexture2);
//				glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);	

				glBindTexture(GL_TEXTURE_2D, texReferred);
				glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SIZE, SIZE, 0, GL_RED, GL_FLOAT, depthTexture2);

				switch(direction)
				{
					case DIR_FRONT:
						for(GLint i=0; i<SIZE; i++)
							for(GLint j=0; j<SIZE;j++)
							{
								if(depthTexture2[(3*i+3*j*SIZE)+1]>0.0)
									bound[j][(GLint)(SIZE-(depthTexture2[i*3+j*SIZE*3]*SIZE))]=1;
							}

					break;
					case DIR_RIGHT:
					break;
					case DIR_TOP:
					break;
				}
			}
		}
	}

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	glDisable(GL_TEXTURE_2D);

	cgGLDisableProfile(cgVertexProfile);
	cgGLDisableProfile(cgFragmentProfile);
	GLUI_Master.auto_set_viewport();
	glViewport (0, 0, (GLsizei) winwidth, (GLsizei) winheight);
	glDeleteFramebuffersEXT(1, &fbo);
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
}

The vertex and fragment shader.


struct VertLBMOut {
  float4 color : COLOR;
  float4 screen : TEXCOORD0;
  float4 position : POSITION;
};

struct VertLBMIn {
  float4 position : POSITION;
  float4 color : COLOR;
  uniform float4x4 modelViewProj;
 };
 
VertLBMOut main(VertLBMIn IN)
{
  VertLBMOut OUT;
  OUT.color = IN.color;
  OUT.position = mul(IN.modelViewProj, IN.position);
  OUT.screen=OUT.position.xyzw/OUT.position.wwww;
  OUT.screen=OUT.screen*0.5 + 0.5;
  return OUT;
}


struct FragLBMOut {
  float4 newDepth : COLOR;
  float depth : DEPTH;
};


struct FragLBMIn {
  float4 color : COLOR;
  float4 screen : TEXCOORD0;
  float4 position : POSITION;
  uniform sampler2D depthMap;
};
 
FragLBMOut main(FragLBMIn IN)
{
  FragLBMOut OUT;
  float4 depthM;
  
  depthM=tex2D(IN.depthMap, IN.screen.st);

  if(IN.screen.z<=depthM.r)
  {
 	 OUT.newDepth.x=depthM.r;
 	 OUT.newDepth.y=0.0; 
   }
  else
  {
	 OUT.newDepth.xy=IN.screen.z;
  }
  
  return OUT;
}

Advertisement
GLuint texTarget;			glGenTextures(1, &texTarget);			glBindTexture(GL_TEXTURE_2D, texTarget);			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SIZE,SIZE, 0, GL_RGB, GL_FLOAT, 0);


I didn't look at the code in detail, but here you are forgeting to call glTexParameter. By default, MIN_FILTER is GL_LINEAR_MIPMAP_NEAREST so you need to either generate mipmaps with glGenerateMipmapsEXT or use GL_LINEAR.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
Thanks.
Something is drawn, but the result of the glGetTexImage is still wrong.

My program works like this, I bind a texture to be read in Cg as reference, and I attach another texture to FBO as rendered target. After finishing the rendering, I retrieve the resulting texture from FBO and 'merge' it with the aforementioned reference texture, and do the process again. Here's the rundown of my program (just ignore the one I wrote in the previous post):

   GLuint query, texReferred, texTarget;   GLuint fbo;   GLuint sampleCount=1;   GLfloat depthTexRef[SIZE*SIZE*4]={0.0}, depthTexture2[SIZE*SIZE*4];   glGenFramebuffersEXT(1, &fbo);   glGenQueries(1, &query);   GLUI_Master.auto_set_viewport();   glViewport (0, 0, SIZE, SIZE);   glEnable(GL_TEXTURE_2D);   glGenTextures(1, &texTarget); //this one as rendered target, will be bound to fbo   glBindTexture(GL_TEXTURE_2D, texTarget);   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);   glGenTextures(1, &texReferred); //this one will be used as reference for the Cg program   glBindTexture(GL_TEXTURE_2D, texReferred);   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);        .        .        .   cgGLEnableProfile(cgFragmentProfile);               // Enable Our Fragment Shader Profile   cgGLEnableProfile(cgVertexProfile);               // Enable Our Vertex Shader Profile   // Bind Our Vertex Program To The Current State   cgGLBindProgram(cgProgramF);   cgGLBindProgram(cgProgramV);   for(int direction=0; direction&lt;3; direction++)   {      sampleCount=1;      for(int i=0; i&lt;SIZE*SIZE*4; i++)         depthTexRef=0.0;      glMatrixMode(GL_PROJECTION);      glLoadIdentity();      glOrtho(-0.5, 0.5, -0.5, 0.5, 0.0, 1.0);      glMatrixMode(GL_MODELVIEW);      glLoadIdentity();      gluLookAt(...)      model.transformModel();       cgGLSetStateMatrixParameter(modelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);      while(sampleCount!=0)      {         glBindTexture(GL_TEXTURE_2D, texReferred);         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, SIZE, SIZE, 0, GL_RGBA, GL_FLOAT, depthTexRef);         cgGLSetTextureParameter(cgTextureRef, texReferred);         cgGLEnableTextureParameter(cgTextureRef);         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);         glBindTexture(GL_TEXTURE_2D, texTarget);         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, SIZE,SIZE, 0, GL_RGBA, GL_FLOAT, NULL);         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texTarget, 0);            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);         glBindTexture(GL_TEXTURE_2D, texReferred);         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         glBeginQuery(GL_SAMPLES_PASSED, query);         model.drawModel();         glEndQuery(GL_SAMPLES_PASSED);         glGetQueryObjectuiv(query, GL_QUERY_RESULT, &sampleCount);         cgGLDisableTextureParameter(cgTextureRef);         if(sampleCount!=0)         {            glBindTexture(GL_TEXTURE_2D, texTarget);            glGetTexImage(GL_TEXTURE_2D,0, GL_RGBA, GL_FLOAT, depthTexture2); //the returned result is not quite right, even if I comment the model.drawModel(); line, it will still return some random values                                 //.                                 //do some process here                                //.                               //merge the rendered texture with reference texture            for(GLint i=0; i&lt;SIZE*SIZE; i++)               if(depthTexRef[i*4]&lt;depthTexture2[i*4])                  depthTexRef[i*4]=depthTexture2[i*4];         }      }   }   glDisable(GL_TEXTURE_2D);   cgGLDisableProfile(cgVertexProfile);   cgGLDisableProfile(cgFragmentProfile); 

This topic is closed to new replies.

Advertisement