Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [a5] rendering to display bitmap with multisampling in directx

This thread is locked; no one can reply to it. rss feed Print
[a5] rendering to display bitmap with multisampling in directx
Mark Oates
Member #1,146
March 2001
avatar

I'm trying to do the following:

  1. draw some stuff to the backbuffer

  2. render the backbuffer to bitmap_a

  3. clear the backbuffer, and draw some different stuff to the backbuffer

  4. render the backbuffer to bitmap_b

  5. clear the backbuffer

  6. draw bitmap_a and bitmap_b to the backbuffer

  7. flip

I'm able to do this just fine, but when 1) multi-sampling is enabled and 2) it's in directx, somehow bitmap_a clears out (becomes transparent or something.) I'm using 5.0.5.

Here's my example program:

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_color.h> 3#include <allegro5/allegro_primitives.h> 4#include <allegro5/allegro_image.h> 5 6 7 8void main() 9{ 10 int screen_w = 320; 11 int screen_h = 240; 12 float shape_size = screen_w/4; 13 bool save_renders = true; 14 15 al_init(); 16 al_init_primitives_addon(); 17 al_init_image_addon(); 18 19 20 al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 2, ALLEGRO_SUGGEST); // works only in opengl 21 al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST); // works only in opengl 22 //al_set_new_display_flags(ALLEGRO_OPENGL); 23 24 25 // create the display and 2 surfaces 26 ALLEGRO_DISPLAY *display = al_create_display(screen_w, screen_h); 27 ALLEGRO_BITMAP *surface_a = al_create_bitmap(screen_w, screen_h); 28 ALLEGRO_BITMAP *surface_b = al_create_bitmap(screen_w, screen_h); 29 30 31 // draw the content of surface_a 32 al_clear_to_color(al_color_name("orange")); 33 al_draw_filled_circle(screen_w/2, screen_h/2, shape_size, al_map_rgba_f(0.2, 0.2, 0.2, 0.2)); 34 35 al_set_target_bitmap(surface_a); 36 al_draw_bitmap(al_get_backbuffer(display), 0, 0, NULL); 37 38 if (save_renders) al_save_bitmap("surface_a_first.png", surface_a); 39 if (save_renders) al_save_bitmap("surface_b_first.png", surface_b); 40 41 42 // reset the surface (oops! forgot to put this in) 44 45 46 47 // draw the content of surface_b 48 al_clear_to_color(al_color_name("dodgerblue")); 49 al_draw_filled_rectangle(screen_w/2-shape_size, screen_h/2-shape_size, 50 screen_w/2+shape_size, screen_h/2+shape_size, al_map_rgba_f(0.2, 0.2, 0.2, 0.2)); 51 52 al_set_target_bitmap(surface_b); 53 al_draw_bitmap(al_get_backbuffer(display), 0, 0, NULL); 54 55 if (save_renders) al_save_bitmap("surface_a_second.png", surface_a); 56 if (save_renders) al_save_bitmap("surface_b_second.png", surface_b); 57 58 59 60 // draw surface_a and surface_b blended together 61 al_set_target_bitmap(al_get_backbuffer(display)); 62 63 al_draw_bitmap(surface_a, 0, 0, NULL); 64 al_draw_tinted_bitmap(surface_b, al_map_rgba_f(0.5, 0.5, 0.5, 0.5), 0, 0, NULL); 65 66 67 if (save_renders) al_save_bitmap("surface_a_final.png", surface_a); 68 if (save_renders) al_save_bitmap("surface_b_final.png", surface_b); 69 70 71 // flip the dip! 72 al_flip_display(); 73 74 75 al_rest(5); 76 77 return; 78}

Here's what surface_a should look like:
{"name":"605444","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/2\/62d9ac52c30ecd7a0aa64a677eed8c90.png","w":320,"h":240,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/2\/62d9ac52c30ecd7a0aa64a677eed8c90"}605444
and surface_b:
{"name":"605445","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/6\/f6c9dcad47059e363812e9693c024084.png","w":320,"h":240,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/6\/f6c9dcad47059e363812e9693c024084"}605445
and the expected result:
{"name":"605443","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/4\/c45fea4057d9b8317ed36c77f9f78b57.png","w":402,"h":324,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/4\/c45fea4057d9b8317ed36c77f9f78b57"}605443

After looking a little deeper, it seems that there's some other strange things going on. When the <code>save_renders=true</code>, configurations of OpenGL/DirectX/multi-sampling produce different resulting saved bitmaps. When it looks like it's working with OpenGL, it actually just appears to be working while the stuff on <code>bitmap_a</code> and <code>bitmap_b</code> are getting swapped in the process. ???

moric haega
Member #13,935
January 2012

I don't know much about DirectX or OpenGL, but I think this is what goes wrong:

-You draw the orange stuff to the backbuffer.
-The target buffer is switched to surface_a.
-The backbuffer is drawn to a
-Then you draw the blue stuff, but not to the backbuffer, because the target is still set to a
-The backbuffer, still containing the orange stuff, is drawn to b
-a & b are in the wrong bitmap!

Reminds me of some program of mine. I read some names and numbers from a file, but forgot to clear the readbuffer between reads. You can guess what kind of mess that became.

PS. I'm a new user, so if there is something wrong with my English or tone, please tell me. :)

J-Gamer
Member #12,491
January 2011
avatar

Yes, you should have another al_set_target_bitmap(al_get_backbuffer(display)); between line 39 and 44.

" There are plenty of wonderful ideas in The Bible, but God isn't one of them." - Derezo
"If your body was a business, thought would be like micro-management and emotions would be like macro-management. If you primarily live your life with emotions, then you are prone to error on the details. If you over-think things all the time you tend to lose scope of priorities." - Mark Oates

Mark Oates
Member #1,146
March 2001
avatar

Yeoops! Silly mistake there. That explains the weird bitmap-swapping. I added the reset on line 43. Thanks.

The OpenGL/DirectX inconsistency is a little more obvious now. By commenting/uncommenting the OpenGL line (22) alone it changes the results. Both work as expected when muti-sampling is disabled (20, 21). So:

This works as expected:

  al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 2, ALLEGRO_SUGGEST);
  al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST);
  al_set_new_display_flags(ALLEGRO_OPENGL);

This does not work as expected (defaults to DirectX):

  al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 2, ALLEGRO_SUGGEST);
  al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST);
  //al_set_new_display_flags(ALLEGRO_OPENGL);

This works as expected (also DirectX):

  //al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 2, ALLEGRO_SUGGEST);
  //al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST);
  //al_set_new_display_flags(ALLEGRO_OPENGL);

In the second case, all of the bitmaps from save_renders are blank. Also, the window only displays what appears in "surface_b."

PS. I'm a new user, so if there is something wrong with my English or tone, please tell me. :)

;D

[edit:] Hmm... no takers?

Matthew Leverton
Supreme Loser
January 1999
avatar

Your posts are too confusing with commented and struck out content. :-/

Mark Oates
Member #1,146
March 2001
avatar

It's a strange problem to describe and might take a little work to figure out. Ignore anything that is struck out as it refers to a minor error I made (and fixed in edits) that is not related to the actual problem.

The example program exposes the problem clearly if you try it. Then with lines 20, 21, and 22, comment/uncomment them out as I did in this post. Each configuration should produce the same results, but they don't.

Go to: