|
[A5] Bitmaps to OpenGL textures |
OICW
Member #4,069
November 2003
|
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. [My website][CppReference][Pixelate][Allegators worldwide][Who's online] |
Elias
Member #358
May 2000
|
There is no ->format or ->memory. You need to lock the bitmap with al_lock_bitmap to the format you want. -- |
OICW
Member #4,069
November 2003
|
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: mBitmap: format: 9 pitch: 512 locked: true lock_x: 0 lock_y: 0 lock_w: 128 lock_h: 128 lock_flags: 1 face: format: 17 pitch: -512 pixel_size: 4 {"name":"606868","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/1\/91c186a55a15f92dcbb50e7dd80df6c4.png","w":646,"h":507,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/1\/91c186a55a15f92dcbb50e7dd80df6c4"} [My website][CppReference][Pixelate][Allegators worldwide][Who's online] |
Elias
Member #358
May 2000
|
Try face>data + face->pitch * w. -- |
OICW
Member #4,069
November 2003
|
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 [My website][CppReference][Pixelate][Allegators worldwide][Who's online] |
Elias
Member #358
May 2000
|
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. -- |
OICW
Member #4,069
November 2003
|
Well, yeah. That also explains the pitch being negative. [My website][CppReference][Pixelate][Allegators worldwide][Who's online] |
|