Thread: glAccum to FBO ? Help for change over

1. glAccum to FBO ? Help for change over

I've been looking at this example online of how to get motion trail on points but can't work out what I should use instead of glAccum buffer to use the trail.

I've just started learning about framebuffers and these deprecated functions don't make it any easier.

void drawGLScene()
{
// These are to calculate our fps... (remember: static vars only get assigned once!)
static GLint t0 = 0;
static GLint frames = 0;

// Clear the draw and depth buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Take the contents of the current accumulation buffer and copy it to the colour buffer with each pixel multiplied by a factor
// i.e. we clear the screen, draw the last frame again (which we saved in the accumulation buffer), then draw our stuff at its new location on top of that
glAccum(GL_RETURN, 0.95f);

// Clear the accumulation buffer (don't worry, we re-grab the screen into the accumulation buffer after drawing our current frame!)
glClear(GL_ACCUM_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);

// Translate everything into the screen (z-axis) by -windowDepth
glTranslatef(0.0f, 0.0f, -windowDepth);

// Apply oscillating rotation to the matrix around the Z-axis.
// Multiplying by 100 is just a fudge factor to increase the total rotation amount
glRotatef(cos(deg2rad(Star::rotationAmount)) * 100, 0.0f, 0.0f, 1.0f);

vector<Star>::iterator starIter; // This needs to be a standard iterator not a constant iterator so we can modify what's being pointed to!!

// Do the actual drawing...
for (starIter = stars.begin(); starIter != stars.end(); starIter++)
{
// Change the point size to the stars size property
glPointSize(starIter->getStarSize());

glBegin(GL_POINTS); // This needs to be inside the loop so the PointSize change (above) takes effect

// Set the colour
glColor3f(starIter->getRedComponent(), starIter->getGreenComponent(), starIter->getBlueComponent());

// Draw the point
glVertex3f(starIter->getX(), starIter->getY(), starIter->getZ());

glEnd();

// Move the star closer (or reset it if it's too close) ready for the next frame
starIter->moveStar();
}

// Swap the buffers so we can see what we've drawn without -watching- it being drawn
SDL_GL_SwapBuffers();

// Take the contents of the current draw buffer and copy it to the accumulation buffer with each pixel modified by a factor
// The closer the factor is to 1.0f, the longer the trails... Don't exceed 1.0f - you get garbage.
glAccum(GL_ACCUM, 0.9f);

// Calcualate our FPS and display it in the console every five seconds
frames++;
{
GLint t = SDL_GetTicks();
if (t - t0 >= 5000)
{
GLfloat seconds = (t - t0) / 1000.0;
GLfloat fps = frames / seconds;
printf("%d frames in %g seconds = %g FPS\n", frames, seconds, fps);
t0 = t;
frames = 0;
}
}

// Add to the star rotation for the next frame
if (Star::rotationAmount < 360.0f)
{
// How quickly this value goes up will controll how quickly it rotates...
// i.e. higher values == faster rotation
Star::rotationAmount += Star::ROTATION_SPEED;
}
else
{
Star::rotationAmount = 0.0f;
}

}

I'm really struggling of how to get this working, someone help!

2. This thread is somewhat odd since your questions seems unrelated to the thread title, or the forum topic. Let me try to answer anyway.

First of all, you don't normally want to draw in the reshape function. The drawing goes into the display function.

There's multiple ways of doing what you're trying to do. I think the main problem with the code you posted is that you call glClear() after disabling the scissor test. glClear() clears the whole window, not only the viewport, unless you have an enabled scissor rectangle. So your second glClear() will wipe out the rendering you did for your first sub-view.

The easiest approach I can think of is that you only set up your projection in the reshape function. It's the same for all the sub-views, so there's no need to set it more than once.

Then in the display function, call glClear() at the start to clear the entire window. Then for each of your sub-views, call glViewport(), and then do the rendering for the sub-view. I don't think you need the scissor test at all with this approach. Even though there's conflicting information on the internets, there's automatic clipping to the viewport rectangle if I read the spec correctly ("

A couple more things: The code you copied only draws twice. I assume that you shorted it for posting, and it draws 4 times? There's no need to call glFlush() before glutSwapBuffers(). The commented out code for setting the viewport depending on the comparison of width and height would most likely not do what you had in mind.

3. Just as a general warning, I think the message board is still in bad shape after the outage. I initially got a "database error" when trying to post the answer that hopefully shows up above. Then a post from somebody else showed up under my name, instead of my post. I think it got fixed by editing the post, and coping the correct content. We'll see...

4. i'm really confused as well! I didn't write the top message. I wanted to ask about framebuffers! aahhhh Here's what I wanted to ask..

I'm trying to change from glAccum to FBO's and have been looking at this code online but can't seem to figure out what to use instead of glAccum for a particle trail sort of effect. I've just started to learn about framebuffer's so it's still a bit new to me and the deprecated functions don't make it any easier :/ What am i supposed to use instead, could you give an example.

void drawGLScene()
{
// These are to calculate our fps... (remember: static vars only get assigned once!)
static GLint t0 = 0;
static GLint frames = 0;

// Clear the draw and depth buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Take the contents of the current accumulation buffer and copy it to the colour buffer with each pixel multiplied by a factor
// i.e. we clear the screen, draw the last frame again (which we saved in the accumulation buffer), then draw our stuff at its new location on top of that
glAccum(GL_RETURN, 0.95f);

// Clear the accumulation buffer (don't worry, we re-grab the screen into the accumulation buffer after drawing our current frame!)
glClear(GL_ACCUM_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);

// Translate everything into the screen (z-axis) by -windowDepth
glTranslatef(0.0f, 0.0f, -windowDepth);

// Apply oscillating rotation to the matrix around the Z-axis.
// Multiplying by 100 is just a fudge factor to increase the total rotation amount
glRotatef(cos(deg2rad(Star::rotationAmount)) * 100, 0.0f, 0.0f, 1.0f);

vector<Star>::iterator starIter; // This needs to be a standard iterator not a constant iterator so we can modify what's being pointed to!!

// Do the actual drawing...
for (starIter = stars.begin(); starIter != stars.end(); starIter++)
{
// Change the point size to the stars size property
glPointSize(starIter->getStarSize());

glBegin(GL_POINTS); // This needs to be inside the loop so the PointSize change (above) takes effect

// Set the colour
glColor3f(starIter->getRedComponent(), starIter->getGreenComponent(), starIter->getBlueComponent());

// Draw the point
glVertex3f(starIter->getX(), starIter->getY(), starIter->getZ());

glEnd();

// Move the star closer (or reset it if it's too close) ready for the next frame
starIter->moveStar();
}

// Swap the buffers so we can see what we've drawn without -watching- it being drawn
SDL_GL_SwapBuffers();

// Take the contents of the current draw buffer and copy it to the accumulation buffer with each pixel modified by a factor
// The closer the factor is to 1.0f, the longer the trails... Don't exceed 1.0f - you get garbage.
glAccum(GL_ACCUM, 0.9f);

// Calcualate our FPS and display it in the console every five seconds
frames++;
{
GLint t = SDL_GetTicks();
if (t - t0 >= 5000)
{
GLfloat seconds = (t - t0) / 1000.0;
GLfloat fps = frames / seconds;
printf("%d frames in %g seconds = %g FPS\n", frames, seconds, fps);
t0 = t;
frames = 0;
}
}

// Add to the star rotation for the next frame
if (Star::rotationAmount < 360.0f)
{
// How quickly this value goes up will controll how quickly it rotates...
// i.e. higher values == faster rotation
Star::rotationAmount += Star::ROTATION_SPEED;
}
else
{
Star::rotationAmount = 0.0f;
}

}

5. You probably want to look at frame buffer objects (FBO).

The way I read the old code, to render each frame, it takes the previous frame, multiplies it by 0.95 (see first glAccum call, with GL_RETURN), then renders new points on top of it, displays that, and saves it away multiplied by 0.9 (see second glAccum call, with GL_ACCUM). Frankly, I don't quite understand why they multiply twice. Also, the second glAccum call is after SwapBuffers, so it almost looks like it would accumulate the previous frame, and not the one that was just rendered. Either I'm just being slow, or this might not be great sample code.

In any case, to emulate similar principles with non-deprecated functionality, I would try using an FBO and two textures. In each iteration, use one of the two textures as the render target by attaching it to the FBO. Bind the other texture, and render a screen sized quad with a pass-through vertex shader and a fragment shader that simply samples the texture and multiplies by the desired value. Then render the geometry with shaders that apply the transformation, etc. Then, if you want to display the frame, copy the content you rendered from your FBO attachment to the back buffer using glBlitFramebuffer.

Then, for the next frame, reverse the role of the two textures. The texture that was your render target, and now contains your latest frame, is now bound as a texture, and used to retrieve the previous frame. The one that was bound as a texture is now bound as the render target for the next frame.

Then, repeat this for each frame, swapping the role of the two textures each time.

Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•