Thread: Reading a pixel from an OpenGL texture (or more than one) with RGBA? (or PNG files)

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    22

    Question Reading a pixel from an OpenGL texture (or more than one) with RGBA? (or PNG files)

    Hello guys, it's me again XD sorry for being an annoyance :P

    I'm trying to do pixel-perfect collision in OpenGL+SDL under Linux. Bounding box collision is working and I have the formulas to get what is the overlapping section in both textures, both relative to the screen and relative to the texture. But now I have to check for every nth pixel in the rectangle to check if the alpha in both textures in that coordinate is 255 (or any other treshold) and return that there was a collision.

    My problem is, how can I read the pixels? I've seen that glReadPixels works on the back buffer or something like that, but I'm not gonna work on the back buffer, I'm gonna work on the textures directly (or that's what I'm wanting, anyways) but I haven't found any related info. There's some talk about "PBOs" and framebuffer, but that isn't what I'm looking for.

    If anybody knows how to read X,Y pixel in a RGBA texture generated with "glTexImage2D(GL_TEXTURE_2D, 0, 4, imgFile->w, imgFile->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, imgFile->pixels);", I would be very, very glad! you all guys rock

    Thanks in advance!

    - DARKGuy

  2. #2
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    imgFile->pixels is an array of unisgned bytes representing pixels values. Have a look at the SDL doc for the imgFile structure type (I'm assuming thats provided by SDL).

  3. #3
    Registered User
    Join Date
    May 2006
    Posts
    22
    Quote Originally Posted by Perspective View Post
    imgFile->pixels is an array of unisgned bytes representing pixels values. Have a look at the SDL doc for the imgFile structure type (I'm assuming thats provided by SDL).
    Yeah, but once I load the texture I free that memory, meaning I don't have any SDL info available but just the OpenGL texture. Else I would read the SDL image info, of course :P.

    An idea would have been to load the image->pixels into another container (I'm using vectors, so it could be something like "vector <uint> pixels" but that would be the same as if I don't free the memory used by IMG_Load (SDL_Image function), and I'm trying to make the game the less memory-hogging possible. However if there's no way to read the pixels out of a GL texture (as oppossed to an SDL image) I guess I have no choice =/
    Last edited by DARKGuy; 05-01-2007 at 03:01 PM.

  4. #4
    Registered User
    Join Date
    May 2006
    Posts
    22
    Alright, I've had my trials and errors and this is what I've came up with:

    It looks like I can't read the pixels after freeing them, so I'm left with an SDL_Surface structure which contains a "Pixels" entry. I've found code around the net (SDL wiki) to get the RGBA from a pixel (though I only need the Alpha value) in a surface. However, I've been having some problems here and after 2 days and 2 consecutive hours in one of them, I'm finally beaten. Could somebody, please, help me? here's the problem:

    I'm trying a code that can read a 10x10 (or any other dimension) region and determine the alpha of each pixel? I'm trying to use this code but I always seem to get wrong data >.<! according to the main code, I should get something like this:

    (Swap the 1's by 255. I just did it here with 1's to make it clearer)

    Code:
    0 0 0 0 1 0 0 0 0
    0 0 0 1 1 1 0 0 0
    0 0 1 1 1 1 1 0 0
    0 1 1 1 1 1 1 1 0
    1 1 1 1 1 1 1 1 1
    But instead I get weird stuff like this:

    Code:
    128 170 255 128 170 255 128 170 255
    128 170 255 128 170 255 128 170 255
    128 170 255 128 170 255 128 170 255
    128 170 255 128 170 255 128 170 255
    128 170 255 128 170 255 128 170 255
    128 170 255 128 170 255 128 170 255
    Which, even if they're alpha values, they aren't the right ones in the positions I'm requesting. Any help would be GREATLY appreciated!

    - DARKGuy

    ------------------------------------------------------------------------------------
    Code:
    ------------------------------------------------------------------------------------
    Code:
    int main()
    {
        ...
    
        Terrain.Load("terrain.png");
    
        Uint32 pixel;
        int px,py;
        Uint8 red,green,blue,alpha2;
    
        SDL_LockSurface(Terrain.pix[0]);
    
        for(py = 200; py <= 210; py++){
            for(px = 200; px <= 230; px++){
                pixel = getpixel(Terrain.pix[0], px, py);   
                SDL_GetRGBA(pixel, Terrain.pix[0]->format, &red,&green,&blue,&alpha2);
                printf("%u ",alpha2);
            }
            printf("\n");
        }
        SDL_UnlockSurface(Terrain.pix[0]);
    
        exit(0);
    }
    ------------------------------------------------------------------------------------
    FUNCTIONS
    ------------------------------------------------------------------------------------
    Code:
    Uint32 getpixel(SDL_Surface *surface, int x, int y)
    {
        int bpp = surface->format->BytesPerPixel;
        /* Here p is the address to the pixel we want to retrieve */
        Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp / 8;
        switch(bpp) {
        case 1:
            return *p;
        case 2:
            return *(Uint16 *)p;
        case 3:
            if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
                return p[0] << 16 | p[1] << 8 | p[2];
            else
                return p[0] | p[1] << 8 | p[2] << 16;
        case 4:
            return *(Uint32 *)p;
        default:
            return 0;       /* shouldn't happen, but avoids warnings */
        }
    }
    Terrain.pix[0] is generated from this:

    Code:
        void Texture::Load(const char filename[]){
            GLuint texture;
            SDL_Surface * image2 = IMG_Load(filename);
            SDL_Surface * imgFile = SDL_DisplayFormatAlpha(image2);
    
            width = (GLfloat)image2->w;
            height = (GLfloat)image2->h;
    
            imgF = image2;   // here. Look below for further info
    
            glGenTextures(1, &texture);
            glBindTexture(GL_TEXTURE_2D, texture);
    
            if(imgFile->format->BitsPerPixel == 32 || imgFile->format->BitsPerPixel == 24){
                glTexImage2D(GL_TEXTURE_2D, 0, 4, imgFile->w, imgFile->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, imgFile->pixels);
            } else { glTexImage2D(GL_TEXTURE_2D, 0, 4, imgFile->w, imgFile->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgFile->pixels); }
       
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        }
    imgF is this:

    Code:
        class Texture {
           public:
                GLuint id;
                GLfloat width, height;
                SDL_Surface * imgF;
              void Load(const char filename[]);
        };
    And pix[0] is this:

    Code:
        class Sprite {
            public:
                    ...
                vector <SDL_Surface*> pix; 
        };
    When I create a sprite, I do this:

    Code:
        int Sprite::Load(const char texfilename[]) {
            Texture tex;
            tex.Load(texfilename);
            img.push_back(tex.id);
            width.push_back(tex.width);
            height.push_back(tex.height);
            alpha.push_back(1.0f);
            pix.push_back (tex.imgF);
            animImg=0;
            animCounter=0;
            angle=0;
            Mirror=false;
            Flip=false;
            return img.size()-1;
        }
    So, what's wrong with my code, could anybody assist me now?... I'm not asking just because some of you give me code and that's all, I do my part too... to the farthest I can =/

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    22
    Actually, I solved it! someone in the SDL mailing list pointed out that I was dividing bpp in GetPixel() by 8. That's what the SDL wiki tells to do though, since the bpp I was getting were 8, 16, 32 instead of 2, 4, 8... but I removed the division and it worked perfectly!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem reading tiff image files?
    By compz in forum C++ Programming
    Replies: 9
    Last Post: 10-30-2009, 04:17 AM
  2. opengl help
    By heat511 in forum Game Programming
    Replies: 4
    Last Post: 04-05-2004, 01:08 AM
  3. problem with open gl engine.
    By gell10 in forum Game Programming
    Replies: 1
    Last Post: 08-21-2003, 04:10 AM
  4. OpenGL and Windows
    By sean345 in forum Game Programming
    Replies: 5
    Last Post: 06-24-2002, 10:14 PM
  5. opengl code not working
    By Unregistered in forum Windows Programming
    Replies: 4
    Last Post: 02-14-2002, 10:01 PM