[A5+OpenGL] How to render OpenGL to a bitmap
Roy Balela

How to render OpenGL to a bitmap instead of display backbuffer?

That's what I was going to ask you after I spent almost two days on this problem. But I managed to figure it out! :)
So I decided to go on and post my findings here, as other people might be having similar problems.

Rendering to bitmap was quite simple. Just set the bitmap as target and then call the OpenGL routines. That's it!

#SelectExpand

{"name":"610814","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/d\/6d11b307d6fc138cb8e3229463480532.png","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/d\/6d11b307d6fc138cb8e3229463480532"}610814

But, as you can see, the polygons are being displayed in the order of drawing.
If you are drawing 2D shapes, that's exactly what you want. But for 3D objects, you want to draw closer objects on top of the farther ones.
First of all, Allegro does not enable depth buffer by default. It must be set before creating the display.

#SelectExpand
1 al_set_new_display_flags(ALLEGRO_OPENGL); 2 al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 16, ALLEGRO_SUGGEST);

Then you have to enable it manually and clear it's buffer everytime you want to redraw your scene.

#SelectExpand
1 glEnable(GL_DEPTH_TEST); 2 glClear(GL_DEPTH_BUFFER_BIT);

{"name":"610815","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/5\/2515b37b8e21ce0475047a758badd0a9.png","w":1282,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/5\/2515b37b8e21ce0475047a758badd0a9"}610815

This corrects the depth buffer for the display backbuffer, but rendering to bitmap still doesn't work.
I tried to mess around with backface culling. This corrects the rendering of the cube, a convex solid, but as soon as I add a new cube behind the first, we can see the problem is there yet.

{"name":"610816","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/9\/d9cde8e8741ee0536ef25f51f1de34fc.png","w":1282,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/9\/d9cde8e8741ee0536ef25f51f1de34fc"}610816

A simple workaround is simply to render on the display backbuffer and then transfer to your bitmap.
Just remember to set the OpenGL viewport to the bitmap dimensions prior to rendering any objects.
Note that OpenGL viewport vertical coordinates are inverse to Allegro.

#SelectExpand
1 al_set_target_backbuffer(display); 2 glViewport(0, DISPLAY_HEIGHT-BUFFER_HEIGHT, BUFFER_WIDTH, BUFFER_HEIGHT); 3 // Draw your stuff 4 5 ... 6 7 // Back to the original viewport 8 glViewport(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); 9 // Need to disable depth test for Allegro drawing routines 10 glDisable(GL_DEPTH_TEST); 11 al_set_target_bitmap(buffer); 12 al_draw_bitmap(al_get_backbuffer(display), 0, 0, 0);

{"name":"610817","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/d\/2da7cfbe74d640aae7fbbafbd09f44b9.png","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/d\/2da7cfbe74d640aae7fbbafbd09f44b9"}610817

This works just fine! But I still was after the answer to why depth buffer was not enabled on the bitmap itself. Also, keep in mind you cannot draw images larger than your current display size.

A little bit more of search, and I found a tutorial on how to render to texture using OpenGL.
So I figured it out that depth buffer is not created for Allegro internal OpenGL textures.
Setting the bitmap as the target, and then creating the depth buffer worked gracefully.

#SelectExpand
1 // Creates your bitmap 2 buffer = al_create_bitmap(BUFFER_WIDTH, BUFFER_HEIGHT); 3 if (!buffer) abort_on_error("Failed to create bitmap"); 4 al_set_target_bitmap(buffer); 5 { // Creates depth buffer for the bitmap 6 GLuint buffer_depth_render; 7 glGenRenderbuffers(1, &buffer_depth_render); 8 glBindRenderbuffer(GL_RENDERBUFFER, buffer_depth_render); 9 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, BUFFER_WIDTH, BUFFER_HEIGHT); 10 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, buffer_depth_render); 11 }

This also makes the ALLEGRO_DEPTH_SIZE option obsolete, as you are explicitly creating the buffer for the bitmap, though you should still use it if you are rendering to the backbuffer, of course.

I continued my tests and ended up mixing Allegro and OpenGL drawing routines. Here is my final result.

{"name":"610818","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/1\/014ae07796b6ff198e6a82dd042a408d.png","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/1\/014ae07796b6ff198e6a82dd042a408d"}610818

You can download the working code, if you want to try it out.

OpenGLTest.zip

I don't know if this is the right way to do it, just that it worked for me.
I will continue testing on the subject, but I am happy with the results so far.

I'm not sure on how freeing the bitmap works, nor if I have to free the depth buffer myself. As I will be using the bitmap throughout the application lifetime, it's not a problem.
Also, the program fails to create a display on Windows, though it compile without errors.

Any feedback is welcome.

SiegeLord

To enable the depth buffer for bitmaps you call al_set_new_bitmap_depth. Note that we haven't implemented it for Direct3D, so you'll want to make sure you force the driver to be OpenGL via the display flags.

Roy Balela

Sweet! Thank you very much.

I was using version 5.0, the last one available on my repository, and so was the manual I was consulting.
Just updated to 5.2.

Also, one needs to add #define ALLEGRO_UNSTABLE to use the function.

Here's my corrected code.

OpenGLTest_5.2.zip

Thread #616793. Printed from Allegro.cc