PDA

View Full Version : glGetTexImage & 3D textures



WaywardSquanderer
06-19-2012, 12:17 PM
I am trying to voxelize polygon meshes using a technique from Real-Time Volume Graphics p 319. The basis for this is using a FBO to render a bounding volume containing the mesh into a 3D texture. I'm having various issues, but before I start asking questions about those, I need to understand what is happening to my texture.

So that leads me to the use of glGetTexImage (and not glReadPixels as it give me FBO data, not texture data). I am able to render to a texture (though currently it is not my desired result), so I know that the FBO -> 3D texture works under certain conditions (these conditions being related to the issues alluded to above). But what I don't understand is how to actually print the texel values for testing purposes. Say I want to print the 16 layers (slices) of a 16 x 16 x 16 3D texture, where each of the dimensions is referred to as texX, texY and texZ, respectively. I wrote the following function starting with sample code from allegro.com (http://www.allegro.cc/forums/thread/601551). The problem is, depending on where I call this function, it may print out the value 205 for every image[n] element, despite the contents of the 3D texture being a background cleared to transparent black and the object in the scene being opaque white. Or it may print out values that don't seem to make any sense (RGBA: 238 254 238 254) when called before sampling the image to a stack of quads.



void printPixelsInSlice(int slice){

GLubyte* image;
image = new GLubyte[texX * texY * texZ * 4];

glGetTexImage(GL_TEXTURE_3D, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
cout << "Reading texels" << endl;
for(int i = 0; i < texY; i++){
for(int j = 0; j < texX; j++){

int start = ((texX * texY * slice) + (i * texX) + j) * 4;
cout << "Texel at " << i << " " << j << " " << slice << " has color " << (int)image[start] << " " << (int)image[start + 1] << " " << (int)image[start + 2] << " " << (int)image[start + 3] << endl;
}
}

delete[] image;
}


Before the call to this function, TEXTURE0 is active, and it is the only texture being used.

So the primrary question is, when and how is glGetTexImage used?

I have tried calling it when the FBO is rendering into one of its slices, but that's when I get values of 205 despite the 3D texture actually having modified content. Note: rendering to texture is done in front to back direction.



void renderToTex(){

glGenFramebuffers(1,&framebufferObject);

glBindTexture(GL_TEXTURE_3D, texture);

glBindFramebuffer(GL_FRAMEBUFFER, framebufferObject);
glActiveTexture(GL_TEXTURE0);

for(int z = 0; z < texZ; z++){

glFramebufferTextureLayer(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
texture,
0,
z);

//Check frame buffer status
cout << endl << "FRAMEBUFFER STATUS: ";
checkFramebufferStatus();
printFramebufferInfo();

//Render into texture
renderIntoSlice(z);

glActiveTexture(GL_TEXTURE0);

//Print texel values by slice
printPixelsInSlice(z); //<---- function call here
// prints '205' for every component of RGBA

}

glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

I have also tried calling it before I map the 3D texture to a stack of quads. In this case, when rendering from back to front (and printing in such a manner), the first few slices have bizarre values (RGBA: 238 254 238 254) . Then eventually I get values of 0 0 0 0 and 255 255 255 255, which is what I expect.



void drawSliceStack(){

float dzPos = -1.0; //Z coordinate in world space
float dzStep = 1.0 / texZ; // layer of texture space

float texStep = 1.0 / (float) texZ; //change in texture depth
float dzTex = 1.0 - texStep;//(texStep / 2.0 );//Start in the middle of a texel

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, texture);

//Render textured quads
for(int slice = 0; slice < texZ; slice++){

printPixelsInSlice(texZ - slice); //function call here, gets better but strange results
glBegin(GL_QUADS);

glTexCoord3f(0.0, 0.0, dzTex);glVertex3f(0.0, 0.0, dzPos);
glTexCoord3f(1.0, 0.0, dzTex);glVertex3f(1.0, 0.0, dzPos);
glTexCoord3f(1.0, 1.0, dzTex);glVertex3f(1.0, 1.0, dzPos);
glTexCoord3f(0.0, 1.0, dzTex);glVertex3f(0.0, 1.0, dzPos);

glEnd();
glFlush();
dzPos += dzStep;
dzTex -= texStep;

}
}

Any help would be greatly appreciated!

V-man
06-20-2012, 04:32 AM
Have you tried glReadPixels right after rendering to your texture layer? Are the results returned correct?

WaywardSquanderer
06-20-2012, 06:53 AM
glReadPixels is correctly returning the data in the FBO, but this does not always end up in the 3D texture. This is why I was lead to believe that glReadPixels will give me FBO data, but not necessarily 3D texture data.

I'm not sure if the following is important information, but if more context will help... The algorithm currently operates via rendering a mesh in isometric perspective within a bounding volume. For each slice or depth interval of the 3D texture resolution, a clipping plane is used to slice the mesh. I can get this to work, but the problem is that it creates a solid voxelization, since it only shears off slices with a single clipping plane traversing from near to far. In other words, when you clip off a slice from the direction you are looking at, this leaves the back facing triangles of the back of the mesh exposed, so this is included in the 3D texture as well.

NOTE: The actual program does not include enable lighting. I just use it here so you can see the difference between a front face and a back face.
779 781

In the previously mentioned case, glReadPixels gives me data that matches up with the 3D texture results.

I want a hollow voxelization, or at least would like to see what result I get. To do this, I want a second clipping plane, such that a second clipping plane removes the back portion of the mesh.
780
But for some reason, the inclusion of the second clipping plane (and no other lines of code besides glClipPlane(...) and enabling the new clip plane) causes the 3D texture to be all black. And this is despite glReadPixels giving me data that suggests I should have an image. This is why I'm trying to use glGetTexImage instead of glReadPixels. Or at the least, compare glReadPixels to glGetTexImage.

V-man
06-20-2012, 11:02 AM
So what you are saying is that you render that bunny mesh. As soon as you enable 2 clip planes, the result returned by glReadPixels is alright but the result returned by glGetTexImage is wrong.

Sounds like a driver bug. A few suggestions I can make :
1. Get rid of calls to glFlush(). A normal GL program doesn't need it.
http://www.opengl.org/wiki/Common_Mistakes#glFinish_and_glFlush (http://www.opengl.org/wiki/Framebuffer_Object_Examples#glReadPixels)
2. It looks like you are using GL 3.0 level functions. Perhaps you should switch over to pure GL 3.0 (3.1 or 3.2 or 3.3). That means using VBOs, VAO, shaders, your own matrices, no more glClipPlane. You would have to do the clipping yourself using shaders.
3. Update your drivers.
4. Test your program on another system
5. If the above is an unacceptable amount of work and getting glGetTexImage to work is important, you might want to visit the driver bugs forum.

WaywardSquanderer
06-20-2012, 03:06 PM
Yes, the results differ between glReadPixels and glGetTexImage.

I have tested the program on a Radeon 6770M and a GeForce GTX 550 Ti, so I don't think it's a driver issue.

I'd like to avoid the more recent OpenGL versions for the time being, as that will set me back quite a ways in terms of learning time.

I've decided a different course of action, which will very likely end up in a different post. I will try to get the data from the FBO using glReadPixels, then use glTexSubImage3D to write the acquired FBO data into the 3D texture, layer by layer.

Thanks for all of your suggestions!