Multisampled rendering to texture

1.2k views Asked by At

I am working with the following architecture:

  • OpenGL ES 2 on iOS
  • Two EAGL contexts with the same ShareGroup
  • Two threads (server, client = main thread); the server renders stuff to textures, the client displays the textures using simple textured quads.

Additional detail to the server thread (working code)

An fbo is created during initialization:

void init(void) {
    glGenFramebuffer(1, &fbo);
}

The render loop of the server looks roughly like this:

GLuint loop(void) {
    glBindFrameBuffer(GL_FRAMEBUFFER, fbo);
    glViewport(0,0,width,height);

    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    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_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);

    // Framebuffer completeness check omitted

    glClear(GL_COLOR_BUFFER_BIT);

    // actual drawing code omitted

    // the drawing code bound other textures, so..
    glBindTexture(GL_TEXTURE_2D, tex);
    glGenerateMipmap(GL_TEXTURE_2D);

    glBindTexture(GL_TEXTURE_2D, GL_NONE);
    glFlush();

    return tex;
}

All this works fine so far.

New (buggy) code

Now i want to add Multisampling to the server thread, using the GL_APPLE_framebuffer_multisample extension and modified the the initialization code like this:

void init(void) {
    glGenFramebuffer(1, &resolve_fbo);
    glGenFramebuffers(1, &sample_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo);
    glGenRenderbuffers(1, &sample_colorRenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, sample_colorRenderbuffer);
    glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_RGBA8_OES, width, height);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, sample_colorRenderbuffer);

    // Framebuffer completeness check (sample_fbo) omitted

    glBindRenderbuffer(GL_RENDERBUFFER, GL_NONE);
    glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
}

The main loop has been changed to:

GLuint loop(void) {
    glBindFrameBuffer(GL_FRAMEBUFFER, sample_fbo);
    glViewport(0,0,width,height);

    GLuint tex;
    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    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_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

    glClear(GL_COLOR_BUFFER_BIT);

    // actual drawing code omitted

    glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);

    // Framebuffer completeness check (resolve_fbo) omitted

    // resolve multisampling
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, resolve_fbo);
    glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, sample_fbo);
    glResolveMultisampleFramebufferAPPLE();

    // the drawing code bound other textures, so..
    glBindTexture(GL_TEXTURE_2D, tex);
    glGenerateMipmap(GL_TEXTURE_2D);

    glBindTexture(GL_TEXTURE_2D, GL_NONE);
    glFlush();

    return tex;
}

What i see now is that a texture contains data from multiple loop() calls, blended together. I guess I'm either missing an 'unbind' of some sort, or probably a glFinish() call (I previously had such a problem at a different point, I set texture data with glTexImage2D() and used it right afterwards - that required a glFinish() call to force the texture to be updated).

However inserting a glFinish() after the drawing code didn't change anything here..

1

There are 1 answers

0
Pontomedon On BEST ANSWER

Oh nevermind, such a stupid mistake. I omitted the detail that the loop() method actually contains a for loop and renders multiple textures, the mistake was that i bound the sample fbo only before this loop, so after the first run the resolve fbo was bound..

Moving the fbo binding inside the loop fixed the problem.

Anyway, thanks @ all the readers and sorry for wasting your time :)