|
[A5] Fullscreen + keep 4:3 ratio |
anto80
Member #3,230
February 2003
|
Hello all, I’m using Allegro 5.0.10 and I have some problems when setting up fullscreen displays on « some configurations » (actually I was not able to detect which configuration makes it work) Here s my code: al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 32, ALLEGRO_REQUIRE); al_set_new_display_flags(ALLEGRO_DIRECT3D| ALLEGRO_FULLSCREEN); ALLEGRO_DISPLAY* _display = al_create_display(640, 480);
My questions: Thank you ___________ |
RPG Hacker
Member #12,492
January 2011
|
From my own experience, I can say that this behavior seems to depend mostly on your graphics card and/or monitor, sometimes even on the video cable you use to connect both. Yeah, no joke. Once I was playing around with a SNES emulator in fullscreen mode, where I had set the resolution to 640x480. When I was using a DVI cable to connect my graphics card to my monitor, it would always stretch the image to the full screen, no matter the actual resolution, so a 4:3 screen was effectively stetched to 16:9. Once I switched to HDMI, though, the same combination of graphics card and monitor actually started accounting for the aspect ratio. So now, when I start the emulator (still with the same resolution), the aspect ratio is actually kept and I get black bars to the left and right. One thing you might want to try: Instead of using ALLEGRO_FULLSCREEN, try using ALLEGRO_FULLSCREEN_WINDOW (or whatever it was called). That option is actually less dependent on the graphics card, so that one might be better at keeping the aspect ratio.
|
Erin Maus
Member #7,537
July 2006
|
I would suggest using the native resolution and implementing the letterboxing and scaling yourself. Running any non-native resolution on flat-screen monitors generally looks terrible, especially if the aspect ratios don't match. --- |
Thomas Fjellstrom
Member #476
June 2000
|
Some cards (nvidia at least) will support faking the mode you want, by scaling and centering the display. Some monitors have scalers that support a bunch of different modes, and will center+scale smaller modes. Some don't support old modes, and some that do, will stretch. Basically, you want to emulate it yourself. Set the mode to the monitor's native mode. Use an ALLEGRO_TRANSFORM to scale up the image to fit within the native mode size, and translate over. May want to clip (`al_set_clipping_rectangle`) drawing to the emulated mode rectangle. -- |
Mark Oates
Member #1,146
March 2001
|
Yea, hardware is consistently inconsistent. You should get and use the native resolution of the display and then scale, stretch, and/or letterbox in your software. -- |
anto80
Member #3,230
February 2003
|
Thanks. If I use bigger (yet native) display, without altering the scene bitmap dimensions, will I have severe performance decrease (FPS drops) ? ___________ |
Mark Oates
Member #1,146
March 2001
|
Uhm, you might, but if you set things up correctly it shouldn't make a difference. What I do is draw everything to a separate ALLEGRO_BITMAP, then scale/stretch to the display on the final pass. So essentially everything in your code is the same as before, except you're drawing to a separate ALLEGRO_BITMAP instead of the bitmap of the ALLEGRO_DISPLAY. Then, all your scaling and stretching and letter boxing and whatnots are of concern only when you draw that bitmap to the display before flipping. I'm not sure if that's the best way, but that's what I'm doing now and it keeps things easy and compartmentalized in my code. There might be equally good alternative solutions. -- |
Thomas Fjellstrom
Member #476
June 2000
|
I think if you make sure your drawing isn't hitting more than the area you're wanting, then it'll work the same as drawing to an offscreen buffer and then copying that to the screen. -- |
anto80
Member #3,230
February 2003
|
Thanks for your answers. Btw how do I detect the fullscreen display size using Allegro 5.0 routines? As for my code: ALLEGRO_DISPLAY* _display; // The display (size: SCREEN_W*SCREEN_H // = Allegro constants) ALLEGRO_BITMAP* _bufferDisplay; // My "scene" (size BITMAP_W*BITMAP_H = 640*480) // ... int nFullScreenH = SCREEN_H; int nFullScreenW = 4*SCREEN_H/3; int nFullScreenOffsetX = (SCREEN_W - nFullScreenW)/2; My Loop : al_set_target_bitmap(_bufferDisplay); al_clear_to_color(COL_BACKGROUND); // equals to color(0,0,0,0) _pGameHelper->Draw(); // all my draws al_set_target_backbuffer(_display); al_draw_scaled_bitmap(_bufferDisplay, 0+nShakeScreenX, 0+nShakeScreenY, // the current screen-shake values BITMAP_W, BITMAP_H, // The size of my "scene" nFullScreenOffsetX, 0, nFullScreenW, nFullScreenH, 0x00); al_flip_display(); Is this what you suggest? @Thomas , you said to use ALLEGRO_TRANSFORM and al_set_clipping_rectangle Thanks again ___________ |
Thomas Fjellstrom
Member #476
June 2000
|
anto80 said: @Thomas , you said to use ALLEGRO_TRANSFORM and al_set_clipping_rectangle Theoretically it should be yes. -- |
anto80
Member #3,230
February 2003
|
Thomas said: Theoretically it should be yes.
OK Then, if it's possible for you to give me an example, I would appreciate. And it is possible to get all fullscreen display sizes for the current video card, using Allegro routines? ___________ |
Thomas Fjellstrom
Member #476
June 2000
|
anto80 said: OK Then, if it's possible for you to give me an example, I would appreciate. Hmm.. Well using the transform api isn't too difficult. You'd just calculate the scaling, and call al_scale_transform to scale drawing with that transform. You'd also want to al_translate_transform to move the origin such that the area you want to draw in is centered in the display. after that you'd al_use_transform. And after that, you just make sure not to draw outside your preferred screen size to cut down on wasted draw calls. (even if you do use clipping) I don't have an example of this handy, and I'm a little busy for the next little while might be able to whip something up later, but don't hold your breath Quote: And it is possible to get all fullscreen display sizes for the current video card, using Allegro routines? Yup. Theres a whole api to query the available display modes. see al_get_display_mode These days, you may actually just want to use the ALLEGRO_FULLSCREEN_WINDOW display driver, and it'll just set the current desktop resolution size. Afterwards you can just use al_get_display_width/height etc. -- |
Chris Katko
Member #1,881
January 2002
|
Definitely do it in software (GPU) not on the TV/monitor. Cheap TVs support very little in terms of letter boxing. My current one (which is cheap) supports centered pixel-for-pixel, or stretched... that's it. There are no boxing modes. [edit] Woah, that's creepy. Someone must have hit send to top, but because my post was last yesterday, it says "Last post was by Chris Katko ~40 minutes ago." -----sig: |
Elias
Member #358
May 2000
|
Here's an example using the transform API. For pixel art you may want to only use integer scaling and then possibly use 4 black bars instead of just two. 1#include <allegro5/allegro.h>
2#include <allegro5/allegro_primitives.h>
3#include <allegro5/allegro_color.h>
4#include <math.h>
5
6void redraw() {
7 al_clear_to_color(al_color_name("black"));
8
9 // actual fullscreen dimensions
10 auto w = al_get_display_width(al_get_current_display());
11 auto h = al_get_display_height(al_get_current_display());
12
13 // dimensions we use for the game
14 auto want_w = 640;
15 auto want_h = 480;
16
17 // scale as big as possible and center
18 auto scale = (double)w / want_w;
19 auto scale_y = (double)h / want_h;
20 if (scale_y < scale)
21 scale = scale_y;
22 auto offset_x = (w - want_w * scale) / 2;
23 auto offset_y = (h - want_h * scale) / 2;
24 ALLEGRO_TRANSFORM transform;
25 al_build_transform(&transform, offset_x, offset_y, scale, scale, 0);
26 al_use_transform(&transform);
27
28 al_set_clipping_rectangle(offset_x, offset_y, want_w * scale,
29 want_h * scale);
30
31 // We can now draw like normal, but 0/0 is the upper left corner
32 // of our virtual boxed screen and want_w/want_h the lower right
33 // corner.
34 al_draw_filled_rectangle(0, 0, want_w, want_h,
35 al_color_name("indigo"));
36 for (int i = 0; i < 100; i++) {
37 int x = (al_get_time() + i) * 120;
38 int y = sin(al_get_time() * 5 + i) * 30 + want_h * i / 100;
39 al_draw_filled_circle(x % (want_w + 20) - 10, y,
40 10, al_color_name("pink"));
41 }
42
43 al_flip_display();
44}
45int main() {
46 al_init();
47 al_init_primitives_addon();
48 al_install_keyboard();
49 al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW);
50 auto display = al_create_display(1, 1);
51 auto queue = al_create_event_queue();
52 auto timer = al_create_timer(1 / 60.0);
53 al_register_event_source(queue, al_get_keyboard_event_source());
54 al_register_event_source(queue, al_get_display_event_source(display));
55 al_register_event_source(queue, al_get_timer_event_source(timer));
56 al_start_timer(timer);
57 auto quit = false;
58 while (!quit) {
59 redraw();
60 auto wait = true;
61 while (wait) {
62 ALLEGRO_EVENT event;
63 al_wait_for_event(queue, &event);
64 if (event.type == ALLEGRO_EVENT_KEY_DOWN) {
65 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
66 quit = true;
67 }
68 if (event.type == ALLEGRO_EVENT_TIMER) {
69 wait = false;
70 }
71 }
72 }
73}
-- |
anto80
Member #3,230
February 2003
|
Thanks very much to all of you. And very good point Elias about the integer scaling when doing pixel art. ___________ |
|