This code should display something like this:
Normal readback : 201.000000 201.000000 201.000000 201.000000
PBO readback : 201.000000 201.000000 201.000000 201.000000
Normal readback : 201.000000 201.000000 201.000000 201.000000
PBO readback : 201.000000 201.000000 201.000000 201.000000
But it instead does something like this:
Normal readback : 201.000000 201.000000 201.000000 201.000000
PBO readback : 201.000000 201.000000 201.000000 201.000000
Normal readback : 201.000000 201.000000 201.000000 201.000000
PBO readback : -1619085020624977094633163538024103936.000000 nan nan -24778363146118103040.000000
The last numbers from the PBO readback are kinda random actually. Sometimes it gives me the same numbers back when I execute the test a couple of times without too much pause inbetween. But when I wait a bit it gives me other numbers, never the right ones though
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
static int width = 1;
static int height = 1;
static GLuint texidFBO;
static GLuint texidInput;
static GLuint pboid[1];
static GLuint fbo;
static GLuint shaderProgram;
const char* vertSource = "" \
"#version 120
" \
"
" \
"void main()
" \
"{
" \
" gl_Position = ftransform();
" \
" gl_TexCoord[0] = gl_MultiTexCoord0;
" \
"}
";
const char* fragSource = "" \
"#version 120
" \
"#extension GL_ARB_texture_rectangle : enable
" \
"
" \
"uniform sampler2DRect input_image;
" \
"
" \
"void main()
" \
"{
" \
" gl_FragData[0] = vec4(texture2DRect(input_image, gl_TexCoord[0].xy)+200.0);
" \
"}
";
GLuint compileProgram(void)
{
GLuint program, fragment_shader, vertex_shader;
program = glCreateProgramObjectARB();
vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER);
glShaderSourceARB(vertex_shader, 1, &vertSource, NULL);
glCompileShaderARB(vertex_shader);
fragment_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
glShaderSourceARB(fragment_shader, 1, &fragSource, NULL);
glCompileShaderARB(fragment_shader);
glAttachObjectARB(program, vertex_shader);
glAttachObjectARB(program, fragment_shader);
glLinkProgramARB(program);
glValidateProgramARB(program);
glDeleteObjectARB(vertex_shader);
glDeleteObjectARB(fragment_shader);
return program;
}
void initGL(int w, int h)
{
int i;
GLfloat texdata[4*width*height];
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, width, height, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0, width, height);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
for (i = 0; i < 4*width*height; i++)
{
texdata[i] = 0.f;
}
glGenTextures(1, &texidFBO);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texidFBO);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA32F_ARB, width, height, 0, GL_RGBA, GL_FLOAT, texdata);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, texidFBO, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glGenBuffers(1, pboid);
}
void initTextureAndShader(void)
{
GLfloat texdata[4*width*height];
int i;
GLuint input_image;
for (i = 0; i < 4*width*height; i++)
{
texdata[i] = 1.f;
}
texidInput = 0;
glGenTextures(1, &texidInput);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texidInput);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB32F_ARB, width, height, 0, GL_RGB, GL_FLOAT, texdata);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
shaderProgram = compileProgram();
glUseProgramObjectARB(shaderProgram);
input_image = glGetUniformLocationARB(shaderProgram, "input_image");
glUniform1iARB(input_image, 0);
glUseProgramObjectARB(0);
}
void doRender(void)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texidInput);
glUseProgramObjectARB(shaderProgram);
glBegin(GL_QUADS);
glTexCoord2f(width, 0);
glVertex2f(0, 0);
glTexCoord2f(0, 0);
glVertex2f(width, 0);
glTexCoord2f(0, height);
glVertex2f(width, height);
glTexCoord2f(width, height);
glVertex2f(0, height);
glEnd();
glUseProgramObjectARB(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
void readBackWithoutPBO(void)
{
GLfloat data[4*width*height];
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texidFBO);
glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GL_FLOAT, data);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
printf("Normal readback : %f %f %f %f
", data[0], data[1], data[2], data[3]);
}
void readBackWithPBO(void)
{
int i;
GLfloat* mem;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pboid[0]);
glBufferData(GL_PIXEL_PACK_BUFFER_ARB, 4*sizeof(GLfloat), NULL, GL_STREAM_READ);
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, NULL);
mem = (GLfloat*)glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
assert(mem);
printf("PBO readback : %f %f %f %f
", ((GLfloat *)mem)[0], ((GLfloat *)mem)[1], ((GLfloat *)mem)[2], ((GLfloat *)mem)[3]);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
int main ( int argc, char** argv )
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(width, height);
glutCreateWindow("PBO transfer test");
initGL(width, height);
initTextureAndShader();
doRender();
readBackWithoutPBO();
readBackWithPBO();
readBackWithoutPBO();
readBackWithPBO();
return 0;
}