I’ve got some particle positions that I adjust and render out to a framebuffer object. From there, I would like to get the positions into a vertex array for rendering. I’ve heard that PBO to VBO is the best way to do that. However, I cannot get my code to work. Can anyone help me out?
I’ve omitted a lot of the code that is not pertinent to this question. Basically, I set up the textures, framebuffer object, and pixel buffer object in the init function. In the main program loop, I update the particle positions in the simulate() function (not shown). Then I transfer the data from the FBO to the PBO for display in the drawParticles() function.
The result is that no points are drawn to the screen at all. If I draw any geometry right after the call to drawParticles(), it comes out yellow even if I say glColor3f(0.1, 0.1, 0.1).
#define MY_TEXTURE_TARGET GL_TEXTURE_RECTANGLE_ARB
#define NUM_FRAMEBUFFERS 1
#define NUM_TEXTURES 2
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
//----------------------------------------------------------------
// drawParticles()
//----------------------------------------------------------------
void drawParticles()
{
glColor3f(0.5, 1.0, 1.0);
// Bind the FBO so you can read the data from it
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbID[0]);
// Do I need to set up viewport to match the size of the textures
// in my FBO?
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, pPosTexW, 0.0, pPosTexH);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, pPosTexW, pPosTexH);
// Bind the PBO so you can put data into it
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, vertBufID[0]);
// initialize the state of the data store
glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, pPosTexW*pPosTexH*4*sizeof(GLfloat),
NULL, GL_STREAM_DRAW);
// select which buffer (FBO attachment) to read from
if (readFromEven) // wrote to oddbuffers
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
else
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
// transfer the data from the FBO to the PBO
glReadPixels(0,0,pPosTexW, pPosTexH, GL_RGBA, GL_FLOAT, BUFFER_OFFSET(0));
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
// set the viewport back to what it was for drawing to the window
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, numCols, 0.0, numRows);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, windowW, windowH);
// unbind the framebuffer object
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
// change the binding point of the buffer object to the
// vertex array binding point
glBindBufferARB(GL_ARRAY_BUFFER, vertBufID[0]);
// draw the vertices
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(4, GL_FLOAT, 0, NULL);
glDrawArrays(GL_POINTS, 0, numParticles);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER, 0);
}
//--------------------------------------------------------------
// myInit()
//--------------------------------------------------------------
void myinit(void)
{
// set up the CG programs
// set the width and height for the particle texture
// create an array to hold the initial particle positions
// create some randomly placed massless particles
// create the particle position textures
// create buffer object for render-to-vertex-array
glGenBuffers(1, &vertBufID[0]);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, vertBufID[0]);
glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, pPosTexW*pPosTexH*4*sizeof(GLfloat),
NULL, GL_STREAM_DRAW);
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
}
//------------------------------------------------------------------
// display()
//------------------------------------------------------------------
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
drawParticles();
glutSwapBuffers();
}
//------------------------------------------------------------------
// TimerCallback(int)
//
// This routine controls the maximum framerate of the program.
// Otherwise it might go too fast on some processors.
//------------------------------------------------------------------
void TimerCallback(int value)
{
glutTimerFunc(TimerDelay, TimerCallback, 0);
Simulate();
glutPostRedisplay();
}