Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Drawing Scaled Bitmaps Or Using Transformations

This thread is locked; no one can reply to it. rss feed Print
Drawing Scaled Bitmaps Or Using Transformations
GaryT
Member #14,875
January 2013

I've spent some time adding two variables 'float scalex' and 'float scaley' throughout my game, and have successfully made it so I can transform all my bitmaps and animations sizes simply by adjusting just these two variables, and it's working great so far, although I still haven’t dealt with adjusting the size of the fonts yet. I've had to use: scaled, scaled_rotated, and tinted_scaled_rotated to get this done.

I've found various threads discussing this topic, but I'm still hoping to find out more. The Wiki link below states which is the preferred method for primitives and bitmaps, but I was just hoping someone could explain exactly why they are the preferred methods.

Moving on, as a test I decided to set my scalex and scaley to 1.0 so they make no difference, and use just the following few lines from the Wiki (https://wiki.allegro.cc/index.php?title=Achieving_Resolution_Independence) to see how it compares. The result is the same as when using my variables.

#SelectExpand
1ALLEGRO_TRANSFORM trans; 2al_identity_transform(&trans); 3al_scale_transform(&trans, 0.6, 0.6); 4al_use_transform(&trans);

Question 1) Is there any reason for me to use stretching now I've discovered scale transforming seems to achieve the same visual result. Apart from the fact that my variables are already in place :)

Question 2) What's the best way to change the size of the fonts. I suppose I could draw the fonts onto a bitmap and scale the bitmap, allow them to be transformed by the scale_transform above, or select a different font size. Any advise would be great.

jmasterx
Member #11,410
October 2009

I personally never understood why that person wrote one way is better for bitmaps and another for primitives.

One thing this person seriously omitted is that when you use the stretched bitmap method instead of scaling, you create and draw a buffer, thus creating triple buffering (graphics are already double buffered). That in itself takes a decent chunk of extra vram. In addition, the graphics card has to draw all those extra pixels to draw the bitmap. This can in some cases bring you closer to your fill limit. When you hit that, the framerate drops a lot.

All this to say that I much prefer a scale transformation. The graphics card is happy to multiply by your scale because it already was doing that anyways. So in theory, the only cost of scaling should be transforming your scale request into a matrix the graphics card can use to multiply all the coordinates by.

Thus, I would think scaling using transformations would be faster and better.

The way I deal with fonts is by loading them all in at once:

#SelectExpand
1 GuiFontManager::~GuiFontManager(void) 2 { 3 for(size_t i = 0; i < m_fonts.size(); ++i) 4 { 5 delete m_fonts[i]; 6 } 7 8 delete m_tempFont; 9 m_tempFont = NULL; 10 } 11 12 agui::Font* GuiFontManager::getDefaultFont() 13 { 14 return getFont((int)m_defaultSize); 15 } 16 17 agui::Font* GuiFontManager::getFont( int size ) 18 { 19 if(m_fonts.empty()) 20 { 21 return NULL; 22 } 23 24 int pos = size - m_beginRange; 25 26 if(pos < 0) 27 { 28 return getFontAt(0); 29 } 30 else if(pos >= (int)m_fonts.size()) 31 { 32 return getFontAt(m_fonts.size() - 1); 33 } 34 35 return getFontAt(pos); 36 37 } 38 39 agui::Font* GuiFontManager::getFont( float scale ) 40 { 41 int size = (int)((float)m_defaultSize * scale); 42 return getFont(size); 43 } 44 45 agui::Font* GuiFontManager::getFont(const agui::Font* ref, float scale ) 46 { 47 int fontSz = -1; 48 for(size_t i = 0; i < m_fonts.size(); ++i) 49 { 50 if(m_fonts[i] == ref) 51 { 52 fontSz = i; 53 break; 54 } 55 } 56 57 if(fontSz == -1) 58 { 59 return NULL; 60 } 61 62 fontSz += m_beginRange; 63 64 int size = (int)((float)fontSz * scale); 65 66 return getFont(size); 67 } 68 69 GuiFontManager::GuiFontManager( 70 const std::string& fontPath, int beginRange, int endRange, int defaultSize ) 71 : m_beginRange(beginRange), m_endRange(endRange), m_defaultSize(defaultSize), 72 m_fontPath(fontPath),m_tempFont(NULL) 73 { 74 75 } 76 77 void GuiFontManager::loadTempFont( float scale ) 78 { 79 if(m_tempFont) 80 { 81 delete m_tempFont; 82 m_tempFont = NULL; 83 } 84 85 m_tempFont = agui::Font::load(m_fontPath,m_defaultSize * scale); 86 } 87 88 agui::Font* GuiFontManager::getTempFont() 89 { 90 return m_tempFont; 91 } 92 93 void GuiFontManager::_loadFonts() 94 { 95 for(int i = m_beginRange; i <= m_endRange; ++i) 96 { 97 m_fonts.push_back(agui::Font::load(m_fontPath,i)); 98 } 99 } 100 101 agui::Font* GuiFontManager::getFontAt( int index ) 102 { 103 agui::Font* f = m_fonts[index]; 104 if(f == NULL) 105 m_fonts[index] = agui::Font::load(m_fontPath, m_beginRange + index); 106 107 return m_fonts[index]; 108 }

I load font sizes 6 to 60, then I have a base font size, and I scale that by the current resolution to get what I want, but I consider other factors like aspect ratio.

The way Allegro5 works is it does not do on-the-fly vector font rendering. It caches the letters (glyphs) into big bitmaps. So Adding more fonts will just cost you more vram.

You can of-course use a big font and scale it, I'm sure that works too, but fonts tend to render differently at smaller sizes to make it more readable. Things like thickness and stuff change. That's why I prefer to use the fonts rather than scale a big one, but it depends on your needs.

pkrcel
Member #14,001
February 2012

BTW, I think it would be okay to say that if you scale EVERYTHING to fit the resizable display, it makes sense that the best way is to use a scale tranformation.

This is what the gfx card ALREADY does in any case so basically it costs nothing in terms of GPU computation.

The "scaled" "tinted" "rotated" version of the draw routines exist for the purpose of being handy ways to transform single objects, but not to apply GLOBAL tranformations.

For that, allegro transforms and blending modes are the way to go I guess.

It is unlikely that Google shares your distaste for capitalism. - Derezo
If one had the eternity of time, one would do things later. - Johan Halmén

Arvidsson
Member #4,603
May 2004

jmasterx said:

I personally never understood why that person wrote one way is better for bitmaps and another for primitives.

I wrote that in 2012 due to misinformation in this very forum. It's a wiki. You know what to do. :)

GaryT
Member #14,875
January 2013

Thank you both that's exactly the information I was looking for ;)

It's so incredibly helpful receiving advice like this.

Honestly you've answered my questions so well I can't think of any else to say except thank you very much indeed :-*

And that, using transformations is making everything so much easier than rewriting every draw() call :)

I am using a separate bitmap for a large part of the graphics, but I've still got various other draw() calls.

Go to: