[A5] Bitmaps to OpenGL textures

I've ran into some problems when creating OGL textures from Allegro bitmaps. For the classic 2D texture I'm currently using this code which runs fine:

ALLEGRO_BITMAP *bitmap = al_load_bitmap(path);
GLuint texName = al_get_opengl_texture(bitmap);

After that I can just use texName everywhere I want to use GL_TEXTURE2D. But, I also want to use cubemap textures, which are essentially 6 2D textures. Therefore to load it I have a function that loads single bitmap containing all six cube faces and creates a GL_TEXTURE_CUBE_MAP from it:

1// Omitted sanity checks etc. the textures are +x, -x, +y, -y, +z, -z in one column 2// of size w * w, mBitmap is the bitmap containing them (either loaded from disk 3// or procedurally generated 4unsigned int w = al_get_bitmap_width(mBitmap); 5unsigned int h = al_get_bitmap_height(mBitmap); 6 7glGenTextures(1, &mName); 8glBindTexture(GL_TEXTURE_CUBE_MAP, mName); 9glActiveTexture(GL_TEXTURE0); 10 11glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 12glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 13glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 14glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 15glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 16 17glPixelStorei(GL_UNPACK_ALIGNMENT, al_get_pixel_size(mBitmap->format)); 18 19GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; // Followed by -x, y, -y, z, -z 20for (unsigned int i = 0; i < TextureCubemap::FACE_COUNT; ++i) 21{ 22 al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE); 23 ALLEGRO_BITMAP *face = al_create_sub_bitmap(mBitmap, 0, i * w, w, w); 24 25 glTexImage2D(target, 0, GL_RGBA, w, w, 0, GL_RGBA, GL_UNSIGNED_BYTE, face->memory); 26 27 al_destroy_bitmap(face); 28 target++; 29}

This code works, but produces garbage. My guess is wrong data formats. I've been also taking a look at ogl_bitmap.c in allegro sources. So, essentially two questions are at hand:

1. What am I doing wrong.
2. Is there a better way of doing this, i.e., creating a cubemap texture from bitmap/bitmaps?


There is no ->format or ->memory. You need to lock the bitmap with al_lock_bitmap to the format you want.


Allright, seems I haven't understood bitmap locking. This time I think I have everything correct, but it still produces garbage:

1unsigned int w = al_get_bitmap_width(mBitmap); 2unsigned int h = al_get_bitmap_height(mBitmap); 3 4glGenTextures(1, &mName); 5glBindTexture(GL_TEXTURE_CUBE_MAP, mName); 6glActiveTexture(GL_TEXTURE0); 7 8glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 9glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 10glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 11glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 12glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 13 14GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; // Followed by -x, y, -y, z, -z 15for (unsigned int i = 0; i < TextureCubemap::FACE_COUNT; ++i) 16{ 17 ALLEGRO_LOCKED_REGION *face = al_lock_bitmap_region(mBitmap, 0, i * w, w, w, ALLEGRO_PIXEL_FORMAT_ABGR_8888, ALLEGRO_LOCK_READONLY); 18 19 glPixelStorei(GL_UNPACK_ALIGNMENT, face->pixel_size); 20 glTexImage2D(target, 0, GL_RGBA, w, w, 0, GL_RGBA, GL_UNSIGNED_BYTE, face->data); 21 22 al_unlock_bitmap(mBitmap); 23 24 target++; 25}

The first cubemap face (positive x) is full of garbage (see attached image below). Inspecting mBitmap and face in debugger provides following interesting bits for the first iteration:

 format: 9
 pitch: 512
 locked: true
 lock_x: 0
 lock_y: 0
 lock_w: 128
 lock_h: 128
 lock_flags: 1

 format: 17
 pitch: -512
 pixel_size: 4



Try face>data + face->pitch * w.


This did the trick:

(face->data + (int)w * face->pitch)

Thanks for help. One more question though, should I understand it that the actual pixel data are prepended by pitch * height of something else?

The only thing I need to solve now, is that apparently each face gets one line from the previous one accidentally. Anyway cookies :)


No, face->data simply points to the beginning of the last row (because in Allegro bitmaps row 0 is the top-most row while in OpenGL textures row 0 is the bottom-most row).

The correct and only documented way of accessing the data is row-by-row, so face->data + row * face->pitch where row can go from 0 to (h-1). Since in your case you know that the data is an OpenGL texture it's not a horrible hack to just access the whole memory I'd say.


Well, yeah. That also explains the pitch being negative.

Thread #611449. Printed from Allegro.cc