PDA

View Full Version : Problems with reading data from FBO to MainMemory



Louvie
06-28-2007, 02:27 AM
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\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
printf("Framebuffer incomplete, missing attachment\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
printf("Framebuffer incomplete, attached images must have same dimensions\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
printf("Framebuffer incomplete, attached images must have same format\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
printf("Framebuffer incomplete, missing draw buffer\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
printf("Framebuffer incomplete, missing read buffer\n");
break;
default:
assert(0);
}
}




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

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

//texID is attached to COLOR_ATTACHMENT0
glGenTextures(1,&amp;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_CO LOR_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,&amp;texture 1[0][0]);
else if( i == 1)
glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA32F_ ARB,texWidth,texHeight,0,GL_RGBA,GL_FLOAT,&amp;texture 2[0][0]);
else if( i == 2)
glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA32F_ ARB,texWidth,texHeight,0,GL_RGBA,GL_FLOAT,&amp;texture 3[0][0]);
else
glTexImage2D(GL_TEXTURE_RECTANGLE_NV,0,GL_RGBA32F_ ARB,texWidth,texHeight,0,GL_RGBA,GL_FLOAT,&amp;texture 4[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, &amp;texID);
glDeleteFramebuffersEXT(1, &amp;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,&amp;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(&amp;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\n";

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 :)

Relic
06-28-2007, 05:30 AM
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.

Louvie
06-28-2007, 07:55 PM
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.

147-2
06-29-2007, 10:29 AM
I think for you to get alpha, you might have to turn on blending.

Louvie
07-01-2007, 07:29 PM
thank you all.
it can work now ^_^