Problems with reading data from FBO to MainMemory

Hi.
Recently i used GPU to accelerate scientific computing.firstly i wanted to try a simple

test: computing the summation of 4 floating matrices(texSize*texSize).
i create 4 floating textures to represent 4 matrices. i attach them to a squre when i draw

the square in FBO. the summation is implemented in glsl fragment program. and after

drawing,i use glReadPixels(…) read the computing result from FBO to MainMemory.But the

values in the MainMemory are all zeros. So would you like to help me?

to simplify, i used GLEW libs and glsl class written by Martin Christen.

And the following is the main code:

// GLSLProgram.cpp  
//

#include "stdafx.h"
#include "glsl.h"
#include <gl\wglew.h>
#include <gl\glut.h> 
#include <cassert>

using namespace glsl;
using namespace std;

GLuint fboID;
GLuint texID;
GLuint depID;

#define texWidth  256
#define texHeight 256 

// 4 matrices
GLuint  inputTexID[4];
GLfloat texture1[texHeight][texWidth];
GLfloat texture2[texHeight][texWidth];
GLfloat texture3[texHeight][texWidth];
GLfloat texture4[texHeight][texWidth];


// for storing the result
GLfloat result[texHeight][texWidth];


glShaderManager SM;
glShader *shader = NULL;


void CheckFramebufferStatus()
{
	GLenum status;
	status = (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
	switch(status) {
		case GL_FRAMEBUFFER_COMPLETE_EXT:
			break;
		case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
			printf("Unsupported framebuffer format
");
			break;
		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
			printf("Framebuffer incomplete, missing attachment
");
			break;		 
		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
			printf("Framebuffer incomplete, attached images must have same dimensions
");
			break;
		case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
			printf("Framebuffer incomplete, attached images must have same format
");
			break;
		case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
			printf("Framebuffer incomplete, missing draw buffer
");
			break;
		case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
			printf("Framebuffer incomplete, missing read buffer
");
			break;
		default:
			assert(0);
	}
}




void InitOpengl()
{
	glEnable(GL_DEPTH_TEST);
	glClearColor(0.2,0.2,0.2,1.0);
	glClearDepth(1.0f);   

	glGenFramebuffersEXT(1,&fboID);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fboID);

    //texID is attached to COLOR_ATTACHMENT0  
	glGenTextures(1,&texID);
	glBindTexture(GL_TEXTURE_RECTANGLE_NV,texID);
	glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA32F_ARB,texWidth,texHeight,0,GL_RGBA,GL_FLOAT,NULL);
	glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_RECTANGLE_NV,texID,0);
	glBindTexture(GL_TEXTURE_RECTANGLE_NV,0);
	 
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);

}



void CreatFloatTexture()
{
	glDeleteTextures(4,inputTexID);

	glGenTextures(4,inputTexID);


	//matrices initialization
	for (int i = 0; i < texHeight; i ++)
	{
		for (int j = 0; j < texWidth; j ++)
		{
			texture1[i][j] = 1.1111;
			texture2[i][j] = 2.2222;
			texture3[i][j] = 3.3333;
			texture4[i][j] = 4.4444;
		}
	}

	for (int i = 0; i < 4;i ++)
	{
		glBindTexture(GL_TEXTURE_RECTANGLE_NV,inputTexID[i]);
		if(i == 0)
			glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA32F_ARB,texWidth,texHeight,0,GL_RGBA,GL_FLOAT,&texture1[0][0]);
		else if( i == 1)
			glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA32F_ARB,texWidth,texHeight,0,GL_RGBA,GL_FLOAT,&texture2[0][0]);
		else if( i == 2)
			glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA32F_ARB,texWidth,texHeight,0,GL_RGBA,GL_FLOAT,&texture3[0][0]);
		else 
			glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA32F_ARB,texWidth,texHeight,0,GL_RGBA,GL_FLOAT,&texture4[0][0]);

		glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameterf(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		glBindTexture(GL_TEXTURE_RECTANGLE_NV,0);
	}


}


void cleanup()
{	
	SM.free(shader);
	glDeleteTextures(4,inputTexID);
	glDeleteTextures(1, &texID);
	glDeleteFramebuffersEXT(1, &fboID);
}


void display()
{
	 glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0);
	 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
	{		 
		glPushAttrib(GL_VIEWPORT_BIT); 
		glViewport(0, 0, texWidth, texHeight);

		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glLoadIdentity();
		gluOrtho2D(0,texWidth,0,texHeight);  


		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glLoadIdentity();	

		glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);

		shader->begin();

		for(int i = 0; i < 4; i ++)
		{

			glActiveTexture(GL_TEXTURE0 + i);
			glEnable(GL_TEXTURE_RECTANGLE_NV);
			glBindTexture(GL_TEXTURE_RECTANGLE_NV,inputTexID[i]);
			if(i == 0)
                shader->setUniform1i("texture1",i);
			else if(i == 1)
				shader->setUniform1i("texture2",i);
			else if(i == 2)
				shader->setUniform1i("texture3",i);
			else if(i == 3)
				shader->setUniform1i("texture4",i);
		}

		glBegin(GL_QUADS);
		{
			glMultiTexCoord2i(GL_TEXTURE0, 0, 0);                 
			glVertex2i(0,0);
			glMultiTexCoord2i(GL_TEXTURE0,texWidth, 0);                   
			glVertex2i(texWidth, 0);          
			glMultiTexCoord2i(GL_TEXTURE0,texWidth,texHeight);          
			glVertex2i(texWidth,texHeight);  
			glMultiTexCoord2i(GL_TEXTURE0,0, texHeight);                  
			glVertex2i(0,texHeight); 
		}
		glEnd();  

		shader->end();

		glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
		glReadPixels(0,0,texWidth,texHeight,GL_RGBA32F_ARB,GL_FLOAT,&result[0][0]);

		glPopMatrix();
		glPopMatrix();

		glPopAttrib();

		
	}
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	 
	glutSwapBuffers();
}

void resize(int w, int h)
{
	if (h == 0) h = 1;

	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(60.0, (GLfloat)w/(GLfloat)h, 0.1, 1000.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

}


int _tmain(int argc, _TCHAR* argv[])
{
	glutInit(&argc, argv);
	glutInitWindowSize(512, 512);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB);
	glutCreateWindow("FBO & GLSL");


	GLenum err = glewInit();
	if(GLEW_OK != err)
		std::cout << std::endl << "failed to initialize GLEW!" << std::endl;

	InitOpengl();

	CreatFloatTexture();

	shader = SM.loadfromFile("sum.vert","sum.frag");
	if (shader==0) 
		cout << "Error Loading, compiling or linking shader
";

	glutDisplayFunc(display);
	glutReshapeFunc(resize);
	glutMainLoop();	 

	return 0;
}

 
 

vertex program:

 
 
void main(void)
{
   gl_TexCoord[0] = gl_MultiTexCoord0;
   gl_Position = ftransform();
}

 

fragment program:

 
 uniform sampler2D texture1,texture2,texture3,texture4;
 
void main(void)
{
     vec4 tex1 = texture2D( texture1, gl_TexCoord[0].st);
    vec4 tex2 = texture2D( texture2, gl_TexCoord[0].st);
   vec4 tex3 = texture2D( texture3, gl_TexCoord[0].st);
    vec4 tex4 = texture2D( texture4, gl_TexCoord[0].st);      
   
    vec4 tex = tex1 + tex2 + tex3 + tex4;        

    gl_FragColor = vec4(tex.xyzw);
 }
 

thank you :slight_smile:

Your glReadPixels format parameter is wrong.
It should throw an GL_INVALID_ENUM error.
Use GL_RGBA instead of GL_RGBA32F there.

Add glGetError calls for debugging for such cases.

thanks to relic.
i had corrected some mistakes but it still doesn’t work. i found if i close fbo i could get right results except alpha component which is 1.0. so i think there maybe something wrong with FBO.

I think for you to get alpha, you might have to turn on blending.

thank you all.
it can work now :slight_smile: