Author Topic: OGL: Loading Images From Memory  (Read 17689 times)

0 Members and 1 Guest are viewing this topic.

Offline mrmudlord

  • ZX 81
  • *
  • Posts: 18
  • Karma: 1
    • View Profile

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: OGL: Loading Images From Memory
« Reply #21 on: November 02, 2012 »
The screen is obviously being rendered to something other than a texture.

No idea how to use that as it doesn't tell have any examples. Maybe have to set the view to ortho and grab the pixels some how.

But thanks for the link. Appreciate it.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Knurz

  • Atari ST
  • ***
  • Posts: 121
  • Karma: 25
    • View Profile
    • GitHub Repository
Re: OGL: Loading Images From Memory
« Reply #22 on: November 13, 2012 »
The screen is obviously being rendered to something other than a texture.

No idea how to use that as it doesn't tell have any examples. Maybe have to set the view to ortho and grab the pixels some how.

But thanks for the link. Appreciate it.

Offscreen Rendering using OGL is very very simple and you can use generic functions to generate everything you need.

Here you have an example how I create a FrameBufferObject:
Code: [Select]
struct FBOELEM {
    GLuint fbo;
    GLuint depthbuffer;
    GLuint texture;
    GLuint colorbuf;
    GLint status;
};

...

int createFBO ( int count, struct FBOELEM *buffers, int width, int height, int filter ) {
    int current, enderr = 1;
    GLenum error;

    for (current = 0; current < count; current++) {
        glGenFramebuffersEXT (1, &buffers[current].fbo);
        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, buffers[current].fbo);
        glGenRenderbuffersEXT (1, &buffers[current].depthbuffer);
        glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, buffers[current].depthbuffer);
        glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
        glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, buffers[current].depthbuffer);
        glGenTextures (1, &buffers[current].texture);
        glBindTexture (GL_TEXTURE_2D, buffers[current].texture);
        glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, filter);
        glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, filter);
        glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8,  width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
        glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, buffers[current].texture, 0);
        // check if everything was ok with our requests above.
        error = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
        if (error != GL_FRAMEBUFFER_COMPLETE_EXT) {
            buffers[current].status = 0;
            enderr = 0;
        }
        else
            buffers[current].status = 1;
    }
    // set Rendering Device to screen again.
    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
    return (enderr);
}

void enableFBO ( int fbo, int width, int height ) {
    // thus cannot have a larger request than tex size!
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    glPushAttrib(GL_VIEWPORT_BIT);
    glViewport(0, 0, width, height);
}

inline void disableFBO () {
    glPopAttrib();
    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
}

I think this is self-explaining what it does.

Just call createFB() to create n FBO's and if you want to render something to one of the screens call enableFBO(myFBO[n].fbo), render your stuff to offscreen and don't forget to switch to the backscreen after you've finished using disableFBO().

If you want to use the rendered texture call glBindTexture(GL_TEXTURE_2D, myFBO[n].texture). You can use it like a loaded Texture Bitmap.

Hope this example helps :).

Brgds.
Remember what the dormouse said: Feed your head

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: OGL: Loading Images From Memory
« Reply #23 on: November 15, 2012 »
Cheers Knurz!! Will see how I get  on with FBO's
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline Knurz

  • Atari ST
  • ***
  • Posts: 121
  • Karma: 25
    • View Profile
    • GitHub Repository
Re: OGL: Loading Images From Memory
« Reply #24 on: November 15, 2012 »
BTW there is just ooooone little "nasty" thing with FBOs:

You don't have any FSAA effects with Framebuffers and the rendering quality is in my opinion (without FSAA) very shitty. There are several solutions to this problem, I found one with shaders but it seems an overkill for just applying a "normal" behaviour with FBO. After hours of googeling I found that the good guys at Khronos Group have already solved this problem for us by extending OpenGL with FSAA-FBOs.

And before you start searching again for examples, here is what I've found on the web - I packed this stuff into a function again:

Code: [Select]
#define FRAMEBUFFER_MULTISAMPLE 8
...

int createMSAAFBO ( struct FBOELEM *store, int width, int height) {
    unsigned int fbo, cbo, dbo;
    int maxsamples;
    GLenum error;

    glGetIntegerv (GL_MAX_SAMPLES_EXT, &maxsamples);

    if ( maxsamples > FRAMEBUFFER_MULTISAMPLE )
        maxsamples = FRAMEBUFFER_MULTISAMPLE;

    glGenFramebuffersEXT (1, &store->fbo);
    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, store->fbo);
    glGenRenderbuffersEXT (1, &store->colorbuf);
    glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, store->colorbuf);
    glRenderbufferStorageMultisampleEXT (GL_RENDERBUFFER_EXT, maxsamples, GL_RGBA, width, height);
    glGenRenderbuffersEXT (1, &store->depthbuffer);
    glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, store->depthbuffer);
    glRenderbufferStorageMultisampleEXT (GL_RENDERBUFFER_EXT, maxsamples, GL_DEPTH_COMPONENT, width, height);
    glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, store->colorbuf);
    glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, store->depthbuffer);

    error = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
    if (error != GL_FRAMEBUFFER_COMPLETE_EXT) {
        switch (error) {
            case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
                MessageBox(NULL, "GL_FRAMEBUFFER_UNSUPPORTED_EXT", "FBO-ERROR", MB_OK | MB_ICONINFORMATION);
                break;
            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
                MessageBox(NULL, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT", "FBO-ERROR", MB_OK | MB_ICONINFORMATION);
                break;
            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
                MessageBox(NULL, "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT", "FBO-ERROR", MB_OK | MB_ICONINFORMATION);
                break;
            case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
                MessageBox(NULL, "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT", "FBO-ERROR", MB_OK | MB_ICONINFORMATION);
                break;
            case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
                MessageBox(NULL, "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT", "FBO-ERROR", MB_OK | MB_ICONINFORMATION);
                break;
            case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
                MessageBox(NULL, "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT", "FBO-ERROR", MB_OK | MB_ICONINFORMATION);
                break;
            case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
                MessageBox(NULL, "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT", "FBO-ERROR", MB_OK | MB_ICONINFORMATION);
                break;
            case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
                MessageBox(NULL, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT", "FBO-ERROR", MB_OK | MB_ICONINFORMATION);
                break;
            default:
                MessageBox(NULL, "default:", "FBO-ERROR", MB_OK | MB_ICONINFORMATION);
                break;
        }
    }
    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
    return (store->fbo);
}

The difference between FSAA FBO's and non-FSAA FBO's is (as you can see in the example above) that you can't bind any textures to this Buffer but you can do a "Blit" to another FBO which has a texture object bound.

Code: [Select]
void texturizeMSAAFBO ( int source, int dest, int width, int height) {
    glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source);
    glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dest);
    glBlitFramebufferEXT(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
    glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
    glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
}

This "Blits" (how I missed this term from good old Amiga) the source-MSAA (or any FBO if you need that) to dest FBO (created by the function of my first posting).

I found another "solution" several days ago, where some guy wrote that he "antialiases" his Screen by creating a FBO with twice size of the Backbuffer. I didn't like the solution so I didn't really tried it out, but I readed in some OGL Specs that FBO Rendering on newer cards should be the fastest solution.
« Last Edit: November 15, 2012 by Knurz »
Remember what the dormouse said: Feed your head

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: OGL: Loading Images From Memory
« Reply #25 on: November 15, 2012 »
I found another "solution" several days ago, where some guy wrote that he "antialiases" his Screen by creating a FBO with twice size of the Backbuffer.
That's actually a pretty bad solution because it's sampling a regular grid which has bad slope coverage.
For proper image quality you'll also need a rather complex downsampling filter to attenuate frequencies above nyquist (which bilinear/bicubic filtering won't) and which is probably already implemented somewhere in the hardware - but would require one (or two) additional rendering passes.
Challenge Trophies Won:

Offline Knurz

  • Atari ST
  • ***
  • Posts: 121
  • Karma: 25
    • View Profile
    • GitHub Repository
Re: OGL: Loading Images From Memory
« Reply #26 on: November 15, 2012 »
That's actually a pretty bad solution because it's sampling a regular grid which has bad slope coverage.
For proper image quality you'll also need a rather complex downsampling filter to attenuate frequencies above nyquist (which bilinear/bicubic filtering won't) and which is probably already implemented somewhere in the hardware - but would require one (or two) additional rendering passes.

I got really good quality by using the stuff provided from OGL, I didn't really tried out the shader solution to the FSAA problem - maybe the shader would be a good fallback solution for some older cards ?


Remember what the dormouse said: Feed your head

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: OGL: Loading Images From Memory
« Reply #27 on: November 15, 2012 »
Quote
I got really good quality by using the stuff provided from OGL
Well, the "build in" anti-aliasing has some drawbacks, too - mainly that it only works for colors.
If you're using deferred rendering, averaged normals and depth-values at boundary-edges can really take you into trouble.
That's why post-production filters for anti-aliasing (like smaa) got more popular lately.
Challenge Trophies Won:

Offline Knurz

  • Atari ST
  • ***
  • Posts: 121
  • Karma: 25
    • View Profile
    • GitHub Repository
Re: OGL: Loading Images From Memory
« Reply #28 on: November 17, 2012 »
Quote
I got really good quality by using the stuff provided from OGL
Well, the "build in" anti-aliasing has some drawbacks, too - mainly that it only works for colors.
If you're using deferred rendering, averaged normals and depth-values at boundary-edges can really take you into trouble.
That's why post-production filters for anti-aliasing (like smaa) got more popular lately.

I just watched some demonstration videos, SMAA looks really great. But I'm far away from understandig this :)
Remember what the dormouse said: Feed your head