Sign in to follow this  
Winegums

Reading texture/framebuffer data with glReadPixels()

Recommended Posts

Winegums    286
Hi, I'm rendering an image to the screen, and I then want to get the screen buffer and dump all the colour data per pixel to a set of three arrays (one per colour channel). I've sorta played with this stuff before, but not actually getting data from the buffer back to the application. Heres what I've got so far:

void GetTextureData()
{
//Setup FBO
		// First we bind the FBO so we can render to it
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
		
		// Save the view port and set it to the size of the texture
		glPushAttrib(GL_VIEWPORT_BIT);
		glViewport(0,0,width,height);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear The Screen And The Depth Buffer
		glLoadIdentity();									// Reset The View

		PreDisplay();			//Setup to draw in ortho
		glBindTexture(GL_TEXTURE_2D, imageTexture[0]);
 		glEnable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);
		glDisable(GL_DEPTH_TEST);	//Disable depth testing and masking
		glDepthMask(GL_FALSE);

		float dimensionsNeg = 0.0f;
		float dimensionsPos = 1.0f;

		PreDisplay();			//Setup to draw in ortho
			glColor3f(1.0f,1.0f,1.0f);
			glBegin(GL_QUADS);
				glTexCoord2f(0.0f, 0.0f); glVertex3f(dimensionsNeg, dimensionsNeg, 0.0f);
				glTexCoord2f(0.0f, 1.0f); glVertex3f(dimensionsNeg, dimensionsPos, 0.0f);
				glTexCoord2f(1.0f, 1.0f); glVertex3f(dimensionsPos, dimensionsPos, 0.0f);
				glTexCoord2f(1.0f, 0.0f); glVertex3f(dimensionsPos, dimensionsNeg, 0.0f);
			glEnd();
		ViewPerspective();

			for(int i = 0 ; i < N ; i++)
			{
				for(int j = 0 ; j < N ; j++)
				{
					glReadPixels(i,j,1,1,GL_RED, GL_FLOAT, &dens_prev_r[IX(i,j)]);
					glReadPixels(i,j,1,1,GL_GREEN, GL_FLOAT, &dens_prev_g[IX(i,j)]);
					glReadPixels(i,j,1,1,GL_BLUE, GL_FLOAT, &dens_prev_b[IX(i,j)]);
					dens_r[IX(i,j)] = dens_prev_r[IX(i,j)];
					dens_g[IX(i,j)] = dens_prev_g[IX(i,j)];
					dens_b[IX(i,j)] = dens_prev_b[IX(i,j)];

				}
			}

		// Restore old view port and set rendering back to default frame buffer
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear The Screen And The Depth Buffer
		glPopAttrib();
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);


}


The data pumped to the arrays is either 1.0f or 0.0f, with nothing in between.

Share this post


Link to post
Share on other sites
Boder    938
I'm not the biggest expert, but that just looks horrible to have glreadpixels in a double-nested loop like that.

Share this post


Link to post
Share on other sites
V-man    813
I always recommend that you read the FBO in the same format that it is in because this case MUST be correctly implemented in the driver.
It is possible that other cases are not well tested, not well debugged by driver team, or fall into the who-cares category.

Depending on your format :

glReadPixels(i,j,1,1,GL_BGRA, GL_FLOAT, pixels);
or
glReadPixels(i,j,1,1,GL_BGRA, GL_UNSIGNED_BYTE, pixels);

Share this post


Link to post
Share on other sites
Winegums    286
How do you store GL_BGRA ? With GL_FLOAT it made sense to store it in a single variable. If i store GL_BGRA, do I have to dissasemble it into different channels?

Share this post


Link to post
Share on other sites
Winegums    286
thanks, I tried that (I didn't realise it would be so intuitive but I'm still getting 1.0f for everything.

Could it be that I've setup the framebuffer object wrong? It's based mostly on a sample, and I think it might be setup to record depth and not colour, or something?


void SetupFBO()
{
// Setup our FBO
glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);

// Create the render buffer for depth
glGenRenderbuffersEXT(1, &depthBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);

// Now setup a texture to render to
glGenTextures(1, &img);
glBindTexture(GL_TEXTURE_2D, img);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RED, GL_FLOAT, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

// The following 3 lines enable mipmap filtering and generate the mipmap data so rendering works
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// glGenerateMipmapEXT(GL_TEXTURE_2D);

// And attach it to the FBO so we can render to it
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, img, 0);

// Attach the depth render buffer to the FBO as it's depth attachment
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthBuffer);


GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
exit(1);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind the FBO for now
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this