|
Scaling down runtime created bitmaps makes them transparent |
trictonicmp
Member #16,611
December 2016
|
Hi everybody, it's me again with another question. In my spare time, I like to write little pieces of code that could help me in the future, this time I was working on a "vertical game renderer" (I made this thing), you might be asking "what the hell is that?" well, a little time ago I played "Bird climb" (a game that's available on the Microsoft store) on my pc and noticed something really cool, despite that the game is in portrait mode (cause it was first made for mobile phones), the developers found a cool workaround to play this gem on landscape mode, and this by just adding bars to the sides of the game itself but that's not the cool part, the cool part is that you can scale the window and the game scales keeping its aspect ratio, ok I'm not explaining my self as I would like to, take a look at the attachments. my idea to recreate this is to create a bitmap, render everything there and then render this bitmap scaled in the middle of the window, this seemed fine until I realized that if I create a bitmap with higher resolutions (for scale purposes)and then scale this bitmap down to fit the screen, the bitmap (let's call this "game buffer")for some reason turns transparent. here is my code 1//-----------------------------------Main.cpp-----------------------------------
2#define ALLEGRO_UNSTABLE
3
4#include <allegro5/allegro.h>
5
6
7//-----------------------------function declaration----------------------------
8void draw_to_gameBuffer(ALLEGRO_BITMAP *gameBuffer, ALLEGRO_DISPLAY *display);
9//---------------------------function declaration END--------------------------
10
11
12//*****************************************************************************
13//----------------------------------MAIN---------------------------------------
14//*****************************************************************************
15int main()
16{
17 bool done = false;
18 bool redraw = true;
19
20 //----------------------------Screen settings-----------------------------
21 static int WIDTH = 1280;
22 static int HEIGHT = 720;
23
24 static int MIN_WIDTH = 405;
25 static int MIN_HEIGHT = 720;
26
27 static int gameBufferWidth = 720;
28 static int gameBufferHeight = 1280;
29
30 static int gameBufferWidthScaled = 405;
31 static int gameBufferHeightScaled = 720;
32
33 float gameBufferX = (WIDTH / 2) - (gameBufferWidthScaled / 2);
34 float gameBufferY = (HEIGHT / 2) - (gameBufferHeightScaled / 2);;
35
36 static float FPS = 60;
37 //--------------------------Screen settings END---------------------------
38
39
40 //--------------------------Pointers declaration--------------------------
41 ALLEGRO_DISPLAY *display = nullptr;
42 ALLEGRO_EVENT_QUEUE *eventQueue = nullptr;
43 ALLEGRO_TIMER *timer = nullptr;
44
45 ALLEGRO_BITMAP *gameBuffer = nullptr;
46 //------------------------Pointers declaration END------------------------
47
48
49 //--------------------------Initialize elements---------------------------
50 al_init();
51 //------------------------Initialize elements END-------------------------
52
53
54 //----------------------------Display options-----------------------------
55 al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE | ALLEGRO_OPENGL);
56 al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 2, ALLEGRO_SUGGEST);
57 al_set_new_display_option(ALLEGRO_SAMPLES, 4, ALLEGRO_SUGGEST);
58 //--------------------------Display options END---------------------------
59
60
61 //----------------------------Setting Pointers----------------------------
62 display = al_create_display(WIDTH, HEIGHT);
63 al_apply_window_constraints(display, true);
64
65 //limits the window to a minimum width and height
66 al_set_window_constraints(display, MIN_WIDTH, MIN_HEIGHT, 0, 0);
67
68 timer = al_create_timer(1.0f / FPS);
69 eventQueue = al_create_event_queue();
70
71 //creating game buffer
72 al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR | ALLEGRO_MIPMAP);
73 al_set_new_bitmap_samples(4);
74 al_set_new_bitmap_format(0);
75 gameBuffer = al_create_bitmap(gameBufferWidth, gameBufferHeight);
76 //--------------------------Setting Pointers END--------------------------
77
78
79 //----------------------------Register events-----------------------------
80 al_register_event_source(eventQueue, al_get_display_event_source(display));
81 al_register_event_source(eventQueue, al_get_timer_event_source(timer));
82 al_start_timer(timer);
83 //--------------------------Register events END---------------------------
84
85
86 //-------------------------------Main loop--------------------------------
87 while (!done)
88 {
89 do
90 {
91 //------------------------Getting events--------------------------
92 ALLEGRO_EVENT event;
93 al_wait_for_event(eventQueue, &event);
94
95 if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
96 done = true;
97
98 if (event.type == ALLEGRO_EVENT_DISPLAY_RESIZE)
99 {
100 al_acknowledge_resize(display);
101
102 //new game buffer scale
103 float windowHeight = al_get_display_height(display);
104
105 gameBufferHeightScaled = windowHeight;
106 //16:9 aspect ratio
107 gameBufferWidthScaled = (windowHeight / 16) * 9;
108
109 //center the game buffer
110 gameBufferX = (al_get_display_width(display) / 2) - (gameBufferWidthScaled / 2);
111 gameBufferY = (al_get_display_height(display) / 2) - (gameBufferHeightScaled / 2);
112 }
113
114
115 if (event.type == ALLEGRO_EVENT_TIMER)
116 {
117 redraw = true;
118 }
119 //-----------------------Getting events END-----------------------
120 } while (!al_is_event_queue_empty(eventQueue));
121
122
123 //-------------------------Redrawing elements-------------------------
124 if (redraw)
125 {
126 al_clear_to_color(al_map_rgb(235, 235, 235));
127
128 draw_to_gameBuffer(gameBuffer, display);
129
130 al_draw_scaled_bitmap
131 (
132 gameBuffer,
133 0, 0, //source X | Y
134 gameBufferWidth, gameBufferHeight, //source W | H
135 gameBufferX, gameBufferY, //destiny X | Y
136 gameBufferWidthScaled, gameBufferHeightScaled, //destiny W | H
137 0 //flags
138 );
139
140 al_flip_display();
141 redraw = false;
142 }
143 //-----------------------Redrawing elements END-----------------------
144 }
145 //-----------------------------Main loop END------------------------------
146
147
148 //--------------------------Destroying elements---------------------------
149 al_destroy_display(display);
150 al_destroy_event_queue(eventQueue);
151 al_destroy_timer(timer);
152 al_destroy_bitmap(gameBuffer);
153 al_uninstall_mouse();
154 al_uninstall_keyboard();
155 al_uninstall_system();
156 //------------------------Destroying elements END-------------------------
157
158
159 //------------------------------Program END-------------------------------
160 return 0;
161}
162
163
164//-------------------------Functions definitions------------------------------
165void draw_to_gameBuffer(ALLEGRO_BITMAP *gameBuffer, ALLEGRO_DISPLAY *display)
166{
167 al_set_target_bitmap(gameBuffer);
168 al_clear_to_color(al_map_rgb(0, 0, 0));
169 al_set_target_backbuffer(display);
170}
171//-----------------------Functions definitions END----------------------------
any idea of what could be causing this? |
Todd Cope
Member #998
November 2000
|
My guess would be MIP mapping. Try disabling that flag before creating gameBuffer. |
André Silva
Member #11,991
May 2010
|
Todd likely hit the nail on the head. If you want to keep mipmaps on, then after you finish creating your new bitmap, create a clone and use that. The clone will have the mipmaps generated on its creation. Remember to delete the original!
|
trictonicmp
Member #16,611
December 2016
|
It seems that mipmapping is causing this as you both mentioned, but why mipmapping causes this? well, maybe I'll never understand, thank you so much for your fast response guys, you are the best. Now all I need to do is to translate my mouse position to the gameBuffer but I guess that's not gonna be a problem. |
Mark Oates
Member #1,146
March 2001
|
trictonicmp said: but why mipmapping causes this? Mipmapping is when the graphics system creates multiple smaller resized versions of the bitmap for performance (and aesthetics) and cross-fades between them as they transition between the differently needed versions. When a mipmap is not correctly working (because it wasn't setup correctly for whatever reason), then it will sometimes crossfade into a blank bitmap, thus appearing transparent. -- |
Edgar Reynaldo
Major Reynaldo
May 2007
|
This is a known bug as referenced by Mark Oates and myself and SiegeLord. I just opened an issue on github for it. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
trictonicmp
Member #16,611
December 2016
|
It seems that is indeed a well-known issue and it's really nice that you, people that work on the source code of Allegro are working to fix this, I really appreciate this community and the support from you to new developers and adventurers that love to work with Allegro, thank you <3. |
André Silva
Member #11,991
May 2010
|
The "why" is fairly simple. When you load a bitmap from the disk, for instance, the mipmaps get generated then, because it makes sense to do so: there's actually content to create a mipmap with, and chances are you're not going to toy with it any more. So it's the perfect time to both load the bitmap into memory as well as generate and store its mipmaps. When you create a new bitmap, the mipmaps are generated too, but they're empty. Creating a new bitmap is mostly useless unless you're going to make changes. But then how would the system know that it's time to generate the mipmaps based on the changes you've made? It can't generate them every time you make a change to the bitmap, otherwise you'd be kissing your performance goodbye. So... it just never does. I guess the ideal way would be to, after you're done editing the new bitmap, tell Allegro that you're finished, and that it should do cleanup and preparations on the bitmap, like mipmap generation. Since we don't have that, you have to do it manually: cloning the bitmap counts as creating a new one, which triggers the mipmap generation.
|
trictonicmp
Member #16,611
December 2016
|
So many thanks for the code Edgar, it helped me a lot and thanks to you André for the explanation, it seems that this "issue" is something that everybody knew except by me . |
|