Clearing integer textures

Hi,
I’m using a texture to store integer indices for a particle system (I’m using unsigned short integers).
I need to clear it before every update (using an fbo). But I can’t use glClear, so should I use a specific shader program before the update or switch back to floating point data and use glclear again, or is there perhaps another way ? What’s the fastest technique?

Thanks :slight_smile:

use glClearBuffer*() instead of glClear()

I hadn’t seen this function in the specs :o , thanks a lot ^^

Well my application crashes with the ClearBuffer call… Anything wrong with my code ?


glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glDrawBuffer(GL_COLOR_ATTACHMENT4);

GLuint clearcolor[] = {0,0,0,0};
glClearBufferuiv(GL_COLOR, 0, clearcolor);

// texture generation
glTexImage2D(   GL_TEXTURE_2D,
                0,
                GL_RGBA16I,
                GRID_WIDTH  * GRID_DEPTH_SQRT,
                GRID_HEIGHT * GRID_DEPTH_SQRT,
                0,
                GL_RGBA,
                GL_UNSIGNED_SHORT,
                0 );


I’m using an Ati 5450 with ubuntu lucid and catalyst 10.6

You’ll need a GL3.0 context (or greater) in order to use glClearBuffer. I’m guessing you don’t?

I do :slight_smile: (I’m using the gl3 header)

Okay here’s a simple program using the functions I’m having problems with (requires sdl1.3):


#include <string>
#include <iostream>
#include <SDL.h>
#define GL3_PROTOTYPES 1
#include "gl3.h"

#define PROGRAM_NAME "GL3"

#define PROGRAM_WIDTH   400
#define PROGRAM_HEIGHT  300

#define TEXTURE_GRID        0
#define TEXTURE_COUNT       1

// gl resources
GLuint fbo = 0;
GLuint textures[TEXTURE_COUNT];  // textures

void build()
{
    glDisable(GL_DEPTH_TEST);
    //////////////////////////////////
    // textures
    glGenTextures(TEXTURE_COUNT, textures);

    //  spatial grid
    glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_GRID]);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

    glTexImage2D(   GL_TEXTURE_2D,
                    0,
//                    GL_RGBA32F,
                    GL_RGBA16UI,
                    PROGRAM_WIDTH,
                    PROGRAM_HEIGHT,
                    0,
                    GL_RGBA,
//                    GL_FLOAT,
                    GL_UNSIGNED_SHORT,
                    0 ); // no data sent, alloc only

    glBindTexture(GL_TEXTURE_2D, 0);
    //////////////////////////////////
    // fbo + rbo (holds depth buffer ?)
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    // bind textures to fbo.
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[TEXTURE_GRID],0);
    glDrawBuffer(GL_COLOR_ATTACHMENT1);

    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    switch(status)
    {
    case GL_FRAMEBUFFER_COMPLETE:
        std::cout << "Framebuffer complete." << std::endl;
        break;

    case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
        std::cout << "[ERROR] Framebuffer incomplete: Attachment is NOT complete." << std::endl;
        break;

    case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
        std::cout << "[ERROR] Framebuffer incomplete: No image is attached to FBO." << std::endl;
        break;


    case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
        std::cout << "[ERROR] Framebuffer incomplete: Draw buffer." << std::endl;
        break;

    case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
        std::cout << "[ERROR] Framebuffer incomplete: Read buffer." << std::endl;
        break;

    case GL_FRAMEBUFFER_UNSUPPORTED:
        std::cout << "[ERROR] Unsupported by FBO implementation." << std::endl;
        break;

    default:
        std::cout << "[ERROR] Unknow error." << std::endl;
        break;
    }

    // release fbo
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

// draw final result
void draw()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    glDrawBuffer(GL_COLOR_ATTACHMENT1);
    glReadBuffer(GL_COLOR_ATTACHMENT1);
//    GLfloat clearcolor[] = {0,0.5,0,0};
    GLuint clearcolor[] = {0,1,0,0};
//    glClearBufferfv(GL_COLOR, GL_COLOR_ATTACHMENT1, clearcolor);
    glClearBufferuiv(GL_COLOR, GL_COLOR_ATTACHMENT1, clearcolor);
//    std::cout << glGetError() << "
";

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

	glBlitFramebuffer(  0,0,PROGRAM_WIDTH,PROGRAM_HEIGHT,
                        0,0,PROGRAM_WIDTH,PROGRAM_HEIGHT,
                        GL_COLOR_BUFFER_BIT, GL_LINEAR
                    );
//    std::cout << glGetError() << "
";
	glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
//	std::cout << "
";
}

void clean()
{
    glDeleteFramebuffers(1, &fbo);

    glDeleteTextures(TEXTURE_COUNT, textures);
}

/* A simple function that prints a message, the error code returned by SDL,
 * and quits the application */
void sdldie(std::string msg)
{
    printf("%s: %s
", msg.c_str(), SDL_GetError());
    SDL_Quit();
    exit(1);
}

/* Our program's entry point */
int main(int argc, char *argv[])
{
    SDL_WindowID mainwindow; /* Our window handle */
    SDL_GLContext maincontext; /* Our opengl context handle */

    if (SDL_Init(SDL_INIT_VIDEO) < 0) /* Initialize SDL's Video subsystem */
        sdldie("Unable to initialize SDL"); /* Or die on error */

    /* Request an opengl 3.2 context.
     * SDL doesn't have the ability to choose which profile at this time of writing,
     * but it should default to the core profile */
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);


    /* Turn on double buffering with a 24bit Z buffer.
     * You may need to change this to 16 or 32 for your system */
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    /* Create our window centered  resolution */
    mainwindow = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                                  PROGRAM_WIDTH, PROGRAM_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );
    if (!mainwindow) /* Die if creation failed */
        sdldie("Unable to create window");


    /* Create our opengl context and attach it to our window */
    maincontext = SDL_GL_CreateContext(mainwindow);

    /* This makes our buffer swap syncronized with the monitor's vertical refresh */
    // 0 not , 1 sync'd
    SDL_GL_SetSwapInterval(0);

    build();

    bool loop = true;

    while (loop)
    {
        SDL_Event event;
        while (SDL_PollEvent(&event))
        {
            // check for messages
            switch (event.type)
            {
                case SDL_KEYDOWN:
                {
                    // exit if ESCAPE is pressed
                    if (event.key.keysym.sym == SDLK_ESCAPE)
                        loop = false;
                }
                break;

                default :
                break;
            }

        }

        draw();

        /* Swap our back buffer to the front */
        SDL_GL_SwapWindow(mainwindow);

        /* Wait 1 milliseconds */
        SDL_Delay(1);
    }

    /* Delete our opengl context, destroy our window, and shutdown SDL */
    SDL_GL_DeleteContext(maincontext);
    SDL_DestroyWindow(mainwindow);
    SDL_Quit();

    clean();

    return 0;
}

The program works when I use floating point format for the texture, but with the integer format I get an error : the frame buffer is incomplete : the texture is not attached to the fbo. But the format is compatible from the specs… Am I missing something ?

Before attaching the integer texture buffer, you will need to set its filtering correctly. The GL spec has the default filtering be GL_LINEAR on the magnification and GL_LINEAR_MIPMAP_NEAREST on the minification filter. Set both filters to GL_NEAREST before attaching the integer texture to the FBO.

I’ve set the mag/minification filters to nearest but I still get the GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT error …

The format is not GL_RGBA but GL_RGBA_INTEGER!
Finally got it to work! Thanks for your help :slight_smile: