Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm working on a project rendering water simulated through smoothed-particle hydrodynamics (SPH) with a non-photorealistic look to use in games.

In the actual stage of the project everything about this rendering is done through OpenGL and GLSL in C++, with many shader steps that stores intermediate textures in FBOs, which are later used in a final shader that brings everything together.

Everything is working fine, except for the framerate, which lies below between 25 and 30 FPS in the better case, rendering everything, including the intermediate textures, in 1024x768 pixels. So, since some of these intermediate steps involve image smoothing algorithms that are time consuming, I thought of reducing the dimensions of the textures generated in intermediate steps to make them faster, trying to find a sweet spot between the level of reduction/performance (divided by 2, 4, 8...) and the rendering final visual.

My question lies precisely here: How can I work with smaller textures in intermediate steps and use them on a final shader step to render to a image in a bigger dimension?

share|improve this question
2  
Just checking: Before you optimise too early, are you sure the low framerate is caused by high-res textures? Have you profiled it? –  Anko Feb 12 at 13:45
2  
Thanks for your answer, @Anko. I didn't profiled it with a specialized tool (and by the way I would love to get some suggestions on these), but first I assumed it because of the main algorithm of the method, which is a separated bilateral filter (repeated 3 times with reducing kernel size to remove artifacts). Also the base of my method is a paper that uses smaller textures in intermediate steps to make it faster, and while I was testing the application with smaller textures for everything (including the final rendering) it worked faster too. I would love to know if I'm wrong, though. –  Liordino Neto Feb 12 at 14:34

1 Answer 1

up vote 0 down vote accepted

All you have to do is create the FBOs textures with the desired width and height and adjust the viewport accordingly when rendering, as shown in this Shadow Map tutorial by Fabien Sanglard.

First create the FBO and it's textures with the desired dimensions. Here fbo_intermediary_colortexture is the FBO id, window_width and window_height are what the name implies and intermediaryTextureSizeRatio is a float that tells how much the FBO texture dimensions should be reduced:

void createFrameBuffer()
{
    // Color texture
    glGenTextures(1, &fbo_intermediary_colortexture);
    glBindTexture(GL_TEXTURE_2D, fbo_intermediary_colortexture);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, window_width * intermediaryTextureSizeRatio, window_height * intermediaryTextureSizeRatio, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    glBindTexture(GL_TEXTURE_2D, 0);

    // FBO
    glGenFramebuffersEXT(1, &fbo_intermediary);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_intermediary);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo_intermediary_colortexture, 0);

    // Test
    if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
        cout << "Couldn't create frame buffer" << endl;

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

After that, when rendering, just adjust the viewport dimensions accordingly to where it's being done (in that case, first on the FBO, and then on the screen):

// Rendering on the FBO, first bind the created FBO and then adjust the viewport dimensions
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_intermediary);
glViewport(0,0, window_width * intermediaryTextureSizeRatio, window_height * intermediaryTextureSizeRatio);

/** rendering to off screen FBO goes here **/

// Then bind the screen frame buffer, adjust the viewport dimensions again, and render
// Notice that the window dimensions are not being multiplied by the reducing factor here
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glViewport(0,0, window_width, window_height);

/** rendering to screen goes here **/

You can check the generated textures dimensions with gDEBugger or some similar application.

One last thing: be warned that, as shown in the aforementioned tutorial, some artifacts may rise from a small texture being rendered on a bigger screen, which can be a bad outcome depending on the scenario.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.