Dark Bit Factory & Gravity

PROGRAMMING => C / C++ /C# => Topic started by: Clyde on September 22, 2010

Title: OGL: Loading Images From Memory
Post by: Clyde on September 22, 2010
I've seen how to load bmps from a file.
However I'm having a bit of bother.

I'd like to using the method I've used previously of a gfx_buffer class and rbz's bmp2raw / bin2c, to load and create images from memory.
 
some code to illustrate.
 
Code: [Select]
#include "media\image_raw.cpp"
#include "media\image_pal.cpp"
class gfx_buffer
{
 public:
 int wwidth, height;
 
 unsigned int *pixels;
 
};

void load_texture()
{
 texture_one=create_gfx_buffer(128,128);//load_gfx_buffer( image_pal, image_raw, 128, 128 );
 for ( int x=0; x<128; x++ )
 {
  for ( int y=0; y<128; y++)
  {
   texture_one->pixels[ x+y*texture_one->wwidth ]=0xff00f0;
  }
 }
 
 glGenTextures(1, &texture_one->pixels[0]);     // Create The Texture
 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
 
 glBindTexture(GL_TEXTURE_2D, texture_one->pixels[0]);
}

gfx_buffer *create_gfx_buffer( int wwidth, int height, unsigned int mask_colour=0 )
{
 gfx_buffer *buffer = new gfx_buffer;
 
 buffer->pixels = new unsigned int [wwidth*height];
 buffer->wwidth = wwidth;
 buffer->height = height;
 return buffer;
}

Thankyou.
Title: Re: OGL: Loading Images From Memory
Post by: Jim on September 22, 2010
glGenTextures doesn't create a texture, it creates an id for a texture.
You use it like this:
Code: [Select]
int texture_id;
glGenTextures(1, &texture_id);
Then you use glTexImage2D to load the texture into video memory (and make it the current texture)
Code: [Select]
glTexImage2d(GL_TEXTURE_2D, GL_RGB8, texture_one->width, texture_one->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_one->pixels);
Remember to set the alpha in your texture to 0xff.  Remember the width and height should be powers of 2.
Then, when you want to use your texture, you can just do
Code: [Select]
glBindImage(GL_TEXTURE_2D, texture_id);

Jim
 
Title: Re: OGL: Loading Images From Memory
Post by: Clyde on September 22, 2010
Thanks Jim :D

Is glTexImage2d apart of glaux.h or another include i need to put in or download?
As it tells me it's undefined. I've allready got gl and glu headers included.

And glGenTextures(1, &texture_id); say Im going to in total make 4 textures, does that increase to 4? or remain 1 per whenever I want to create a texture.
 
Thanks Dude!
Title: Re: OGL: Loading Images From Memory
Post by: Clyde on September 22, 2010
I see, the d should be a capital.

It now tells me that it doesn't take 8 arguments.
glTexImage2D(GL_TEXTURE_2D, GL_RGB8, texture_one->wwidth, texture_one->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_one->pixels );

 
Title: Re: OGL: Loading Images From Memory
Post by: Jim on September 22, 2010
You can do
Code: [Select]
int texture_id1;
int texture_id2;
int texture_id3;
int texture_id4;
glGenTextures(1, &texture_id1);
glGenTextures(1, &texture_id2);
glGenTextures(1, &texture_id3);
glGenTextures(1, &texture_id4);
or
Code: [Select]
int texture_id[4];
glGenTextures(4, texture_id);

Sorry about this one, I'm typing it in from memory...:P  Missed out the mipmap level (0 for none)
Code: [Select]
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture_one->wwidth, texture_one->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_one->pixels );

Jim
Title: Re: OGL: Loading Images From Memory
Post by: Jim on September 22, 2010
http://www.opengl.org/sdk/docs/man/ (http://www.opengl.org/sdk/docs/man/)
Title: Re: OGL: Loading Images From Memory
Post by: Clyde on September 23, 2010
Here's an update project, but the texture / image isn't being used, it's white. I've made it make a coloured textured in a for loop for the time being.
 
Im also using ie9beta, and I can't get the xml pages to open on that link.
 
Title: Re: OGL: Loading Images From Memory
Post by: Jim on September 23, 2010
The links you want on that page are in the left-hand side bar.
Title: Re: OGL: Loading Images From Memory
Post by: Jim on September 23, 2010
You need
Code: [Select]
glEnable(GL_TEXTURE_2D);
somewhere!

Jim
Title: Re: OGL: Loading Images From Memory
Post by: Clyde on September 23, 2010
yep, it's on line 15 in the nehe - setup.h of InitGL.
perhaps it's because of different colour formats.
Title: Re: OGL: Loading Images From Memory
Post by: Jim on September 23, 2010
2 problems.

1. Between
glGenTextures()
and
glTexImage2D
you need to do a
glBindTexture(GL_TEXTURE_2D, texture_id );   

2. You need to load the texture!!
Between
CreateGLWindow
and
while(!done)
you need to call
load_texture();

Working for me now...I've attached the main cpp file with my changes.

Jim

            
Title: Re: OGL: Loading Images From Memory
Post by: Clyde on September 23, 2010
Am I right in thinking the texture needs to be loaded / reloaded each frame?
Just trying to think why in init_demo that won't work.

Cheers Jim.
Title: Re: OGL: Loading Images From Memory
Post by: Jim on September 23, 2010
Only if you want the image to change, otherwise you load it once using glTexImage2D and it sits in video memory (usually).

If you want to change the image, don't call glGenTextures again, just do
glBindTexture(GL_TEXTURE_2D, id_of_the_texture_you_want_to_update);
then
glTexImage2D
or
glTexSubImage2D
to load the new data.

Jim
Title: Re: OGL: Loading Images From Memory
Post by: Clyde on September 23, 2010
the image i've loaded isn't as should be, the main difference from the original images is it's blue where red should be. it's a usual a 256 colour bitmap converted with bmp2raw.

can't quite get why the load_texture in init_demo wouldnt work, but putting it into winmain. maybe it's a static thing.
Title: Re: OGL: Loading Images From Memory
Post by: Jim on September 23, 2010
To fix the colours try GL_BGRA_EXT instead of GL_RGBA in the glTexImage2D call.

It wasn't working because you never called init_demo anywhere.

Jim
Title: Re: OGL: Loading Images From Memory
Post by: Clyde on September 23, 2010
oops, I thought I had.
Thanks again!
I can now texture a cube in CPP!!
Title: Re: OGL: Loading Images From Memory
Post by: Jim on September 23, 2010
Bonza!
Title: Re: OGL: Loading Images From Memory
Post by: Clyde on April 18, 2012
Is there a way to copy the contents of a glTexture back into a buffer?

an example:

Code: [Select]
    unsigned int *colour_buffer=new unsigned int[ texture_wwidth * texture_height ];
   
    // Set Our Viewport (Match Texture Size)
    glViewport(0,0,texture_wwidth,texture_height);

    render_scene();
   
    // Bind To The Texture
    glBindTexture(GL_TEXTURE_2D, texture_id_num );
   
    // copy over texture contents to colour buffer.


Cheers!!
Title: Re: OGL: Loading Images From Memory
Post by: Jim on April 18, 2012
Quote
Is there a way to copy the contents of a glTexture back into a buffer?
Specifically, no.

But it depends what you really want to do.
You can draw it and then use glReadPixels to read the pixels off the screen. reading back from video memory is incredibly slow.
You can draw to something that isn't the screen (a video memory buffer) and use that as a texture later.



Jim
Title: Re: OGL: Loading Images From Memory
Post by: Clyde on October 16, 2012
I just wondered as it would be quite cool for trying blurring and other fx, as at the moment I can't get the hang of shaders. Most examples on google use ps 3.0 and higher, and aren't really written for novices.

when you say a video memory buffer, do you mean like for example argb_buffer[x+y]=glReadPixels(x,y,col) , similarly to blitz's read and writepixels?

Cheers.
Title: Re: OGL: Loading Images From Memory
Post by: mrmudlord on October 17, 2012
http://www.opengl.org/sdk/docs/man/xhtml/glGetTexImage.xml

Title: Re: OGL: Loading Images From Memory
Post by: Clyde 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.
Title: Re: OGL: Loading Images From Memory
Post by: Knurz 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.
Title: Re: OGL: Loading Images From Memory
Post by: Clyde on November 15, 2012
Cheers Knurz!! Will see how I get  on with FBO's
Title: Re: OGL: Loading Images From Memory
Post by: Knurz 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.
Title: Re: OGL: Loading Images From Memory
Post by: hellfire 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.
Title: Re: OGL: Loading Images From Memory
Post by: Knurz 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 ?


Title: Re: OGL: Loading Images From Memory
Post by: hellfire 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.
Title: Re: OGL: Loading Images From Memory
Post by: Knurz 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 :)