I'm trying to program the rendering of a 3D horizontal layer from a 2D image, like the "mode 7" effect from many SNES games.I don't have any problem with the math, the problem I'm having is with Allegro's al_get_pixel and al_put_pixel methods. They seem to be extremely slow, way too slow for real time. It's slow regardless of whether the bitmap is locked or not.

My question is: is there a way to get and set pixels from a bitmap faster than al_get_pixel and al_put_pixel, like accessing the data directly?

Pixel by pixel this is going to be extremely slow. However, all you need to do is create a "cache" bitmap, render your tiles to it in regular 2D, then use a perspective transform (al_perspective_transform in 5.1) and then draw the cache bitmap. It's basically free mode 7 using the 3d hardware.

I'm using the windows binaries, which is only 5.0.8. According to the manual, 5.1 is unstable.al_perspective_transform does indeed seem to what I want, however. Would you recommend switching to 5.1 despite this?

I looked at the 5.1 code, and it seems to set the values of a 4x4 matrix to a projection matrix. When al_use_transform is called, it applies the 3D transformation to the image. It doesn't seem to do this in 5.0.8, instead only using the 2D components of the 4x4 matrix. al_use_transform has the same code in 5.0.8 and 5.1, so one of the functions it calls must be different.

Is there a way I can still use 5.0.8 but still have those nice 3D transformations

I think al_compose_transform is different in 5.1 compared to 5.0. It's exactly as you stated, 5.1 does a "3D" multiplication and I think 5.0 still only does 2D (since it didn't get any of the 3D transforms.) I didn't look at the code but I think you can just copy al_compose_transform from 5.1 and use that to combine your matrices.

al_compose_transform only modifies the matrix, and the matrix itself isn't the problem. The function that actually performs the transformations on the bitmap (which I believe is display->vt->update_transformation from al_use_transform) seems to ignore the 3D components of the matrix in 5.0.8. I tested this by manually modifying the matrix to a set that I know would produce a 3d perspective, but this only effects the bitmap in 2D.

I'm not very familiar with allegro and I can't find where display->vt->update_transformation is in the source code, although it seems to be a lost cause. I'm probably better off switching to 5.1, or finding a different way to produce the 3D effect.

Edit: I've figured out a trick to do it in 5.0.8 without getting or setting pixels However, I would still like to know if there's a faster way to get/set pixels in general, especially get.

Something like that. I couldn't remember if ABGR_8888_LE is alpha first or red first... but just experiment with that.

Things to take note of: you don't have to use that bitmap format. It's a good format if you're using OpenGL and 32 bit bitmaps. Otherwise use something else. Second: the ALLEGRO_PIXEL_FORMAT_ANY means the lr->data block will be formatted in the same format as you created the bitmap. You CAN specify any format there, but if it's not the same as the bitmap format you get two conversions (thus slower.) Last: If you only need to read or write use ALLEGRO_LOCK_READONLY or ALLEGRO_LOCK_WRITEONLY. They're faster if you don't need to read and write.

Thanks for all the help! I got your code to work. It should be faster, plus I do prefer getting an integer from 0-255 rather than a float (checking float equality makes me paranoid). Not sure what the +10 was for, but I didn't seem to need it. The other tips you gave were quite helpful too.

The only problem is that in debug mode I get this error in the console and program crashes:Assertion failed: bitmap != dest && bitmap != dest->parent, file allegro-git\src\bitmap.c, line 210

In release I have no such error and it runs fine.

Edit: I was drawing a bitmap region to itself, causing the error. Thank you for all the help Trent!

The 10 was not important and I forgot to mention why I put it there. I was just going to say this is a way to add brightness to the pixels (though IRL you would check that the value didn't go over 255 with MIN(255, p+10)).