Antialiasing in allegro
kovarex

Hello,

I'm looking for way to draw bitmaps (not primitives) (zoomed and without zoom) antialised.

When I draw bitmap the normal way, allegro functions take floats as position arguments, but the position of the bitmap is rounded to whole pixels, this makes bad effects in the game. The goal would be to be able to draw the bitmap in between two pixels like I show it on this picture:
http://www.kovarex.com/download/bitmap-placement.png

I would expect, that this kind of multisampling setting would do this, but it didn't

  al_set_new_display_flags(ALLEGRO_RESIZABLE);
  al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_SUGGEST);
  al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR);
  al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST);
  al_set_new_display_option(ALLEGRO_SAMPLES, 6, ALLEGRO_SUGGEST);

Elias

If you use 5.0.7 and the D3D driver, multi-sampling does not work.

kovarex

Elias:
I used the 5.1.2 version, and today we updated to 5.1.3 and it is the same.

The goal would be to make it work either for D3D and opengl if possible.

Elias

In 5.1.3 it should work. What happens if you run ex_multisample?

weapon_S
kovarex said:

al_set_new_display_option(ALLEGRO_SAMPLES, 6, ALLEGRO_SUGGEST);

I'm not very familiar with exactly what capabilities Allegro can use, but 6 is a weird number for 'normal' samples, I think. Try 4?

kovarex

weapon_S:
I tried 4 instead of 6 and it is the same, bitmap position is still rounded to pixels.

Elias:
But ex_multisample contains only primitives drawing, I need multisampling for bitmap drawing.

Elias

Yes, but does ex_multisample work? al_draw_bitmap just calls the underlying primitive functions as far as I know so either both should work or neither. Anyway, if ex_multisample works but bitmap drawing does not, it sounds like a bug to me. If ex_multisample doesn't work as well, multisampling simply doesn't work for some reason.

kovarex

Elias:
ex_multisample works

Elias

I'll try modifying it to add an al_draw_bitmap call when I get home and see how it looks here.

weapon_S

I'm just firing ideas.
What does al_get_display_option(display, ALLEGRO_RENDER_METHOD); return?
That shouldn't return 0... but I guess something has to be wrong.

kovarex

weapon_S:
It returns 0.
Does it mean hardware acceleration isn't used?
How could it be possible? The game isn't THAT slow (I can draw up to 20k sprites 60fps, would software acceleration make it?

Elias

I tried adding an al_draw_bitmap call to ex_multisample and it does work.

Double-check that:

- none of your bitmaps are created before al_create_display
- you set ALLEGRO_SAMPLE_BUFFERS and ALLEGRO_SAMPLES before al_create_display
- you set ALLEGRO_MIN_LINEAR and ALLEGRO_MAG_LINEAR before any bitmaps are created/loaded

kovarex

Elas:

This is our display init function
bitmaps are loaded later

#SelectExpand
1 if (!al_init()) 2 throw std::runtime_error("failed to initialize allegro!"); 3 /* vsync 1 means force on, 2 means forced off. */ 4 al_set_new_display_flags(ALLEGRO_RESIZABLE); 5 al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_SUGGEST); 6 al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR); 7 al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST); 8 al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST); 9 10 al_set_new_window_position(global->properties.get<int>("screen.x", 100), 11 global->properties.get<int>("screen.y", 100)); 12 13 this->display = al_create_display(global->properties.get<int>("screen.width", 800), 14 global->properties.get<int>("screen.height", 600)); 15 if (!this->display) 16 throw std::runtime_error("failed to create display!"); 17 al_show_native_message_box(al_get_current_display(), 18 "Window Title", 19 "Content Title", 20 ssprintf("render method = %d", al_get_display_option(display, ALLEGRO_RENDER_METHOD)).c_str(), 21 NULL, ALLEGRO_MESSAGEBOX_ERROR); 22 23 if (!al_init_image_addon()) 24 throw std::runtime_error("Failed to initialize al_init_image_addon!"); 25 if (!al_install_keyboard()) 26 throw std::runtime_error("failed to initialize the keyboard!"); 27 if (!al_install_mouse()) 28 throw std::runtime_error("failed to initialize the mouse!"); 29 al_init_font_addon(); 30 if (!al_init_ttf_addon()) 31 throw std::runtime_error("failed to initialize the ttf addon!"); 32 this->font = al_load_ttf_font((global->resourcePath + "pirulen.ttf").c_str(), 24, 0); 33 if (!Display::font) 34 throw std::runtime_error("Could not load 'pirulen.ttf'."); 35 Display::itemCountFont = al_load_ttf_font((global->resourcePath + "pirulen.ttf").c_str(), 14, 0); 36 if (!Display::itemCountFont) 37 throw std::runtime_error("Could not load 'pirulen.ttf'."); 38 Display::tileLabelFont = al_load_ttf_font((global->resourcePath + "pirulen.ttf").c_str(), 14, 0); 39 if (!Display::tileLabelFont) 40 throw std::runtime_error("Could not load 'pirulen.ttf'."); 41 if (!al_init_primitives_addon()) 42 throw std::runtime_error("failed to load primitives addon!");

Elias

This is my modified ex_multisample. If you either comment out the multi-sampling or the bitmap filtering you can clearly see what both do - the former anti-aliases the outline, the latter filters the inside of the texture. So without multisampling the bitmap seems to jump in one-pixel steps. Without the filtering the texture seems to jump in one-pixel steps. With both on it's all smooth.

I'm using Ubuntu/OpenGL here.

#SelectExpand
1#include <allegro5/allegro.h> 2#include <math.h> 3 4int main(void) 5{ 6 ALLEGRO_DISPLAY *display; 7 ALLEGRO_EVENT_QUEUE *queue; 8 ALLEGRO_TIMER *timer; 9 ALLEGRO_BITMAP *bitmap; 10 float bx, by; 11 bool quit = false; 12 bool redraw = true; 13 unsigned char *rgba; 14 int p; 15 int x, y; 16 17 al_init(); 18 al_install_keyboard(); 19 20 al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_REQUIRE); 21 al_set_new_display_option(ALLEGRO_SAMPLES, 16, ALLEGRO_SUGGEST); 22 display = al_create_display(200, 200); 23 24 al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR); 25 bitmap = al_create_bitmap(16, 16); 26 ALLEGRO_LOCKED_REGION *locked; 27 locked = al_lock_bitmap(bitmap, ALLEGRO_PIXEL_FORMAT_ABGR_8888, 0); 28 rgba = locked->data; 29 p = locked->pitch; 30 for (y = 0; y < 16; y++) { 31 for (x = 0; x < 16; x++) { 32 int c = (((x / 4) + (y / 4)) & 1) * 255; 33 rgba[y * p + x * 4 + 0] = c; 34 rgba[y * p + x * 4 + 1] = c; 35 rgba[y * p + x * 4 + 2] = c; 36 rgba[y * p + x * 4 + 3] = 255; 37 } 38 } 39 al_unlock_bitmap(bitmap); 40 41 timer = al_create_timer(1.0 / 60.0); 42 43 queue = al_create_event_queue(); 44 al_register_event_source(queue, al_get_keyboard_event_source()); 45 al_register_event_source(queue, al_get_display_event_source(display)); 46 al_register_event_source(queue, al_get_timer_event_source(timer)); 47 48 al_start_timer(timer); 49 while (!quit) { 50 ALLEGRO_EVENT event; 51 al_wait_for_event(queue, &event); 52 switch (event.type) { 53 case ALLEGRO_EVENT_DISPLAY_CLOSE: 54 quit = true; 55 56 case ALLEGRO_EVENT_KEY_DOWN: 57 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 58 quit = true; 59 break; 60 61 case ALLEGRO_EVENT_TIMER: 62 bx = fmod(bx + 0.1, 200); 63 by = fmod(by + 0.1, 200); 64 redraw = true; 65 break; 66 } 67 68 if (redraw && al_is_event_queue_empty(queue)) { 69 al_clear_to_color(al_map_rgb_f(0.5, 0.5, 1)); 70 al_draw_bitmap(bitmap, bx, by, 0); 71 al_flip_display(); 72 73 redraw = false; 74 } 75 } 76 77 return 0; 78}

kovarex

In the first post I had only ALLEGRO_MIN_LINEAR, adding ALLEGRO_MAG_LINEAR to new bitmap flags seems to solve the problem.
Could it be, that unscaled bitmaps are affected by the ALLEGRO_MAG_LINEAR flag?

Elias

It doesn't say on MSDN [1]. But you almost always want either both or none (and if you scale your bitmaps down more than about 50% you want to enable mipmaps as well). Maybe we should provide new defines like

#define ALLEGRO_BILINEAR_FILTER ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR
#define ALLEGRO_TRILINEAR_FILTER ALLEGRO_BILINEAR_FILTER | ALLEGRO_MIPMAP

and then you'd just use bi-linear or tri-linear. And now with all the added 3D support, we also should add an anisotropic filtering option.

Thread #611078. Printed from Allegro.cc