Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Sprite text help  (Read 3992 times)

0 Members and 2 Guests are viewing this topic.

bobingabout

  • Newbie
  • *
  • Posts: 47
    • View Profile
Sprite text help
« on: May 29, 2012, 12:39:38 pm »
Currently using SFML1.6 on my Asus EEE 1000h netbook. You know the one, 1.6GHz single core with a really crap intel graphics card.

anyway, here's my issue. My font system works as follows. The font is a single image fille, aranged with 16x16 ASCII symbols, loaded into an image. when you send text to the function, it can calculate a subrect, and a position, then draws it on the screen. it then re-uses the same sprite over and over for each charactor.
when you start displaying over 100 charactors on the screen, it starts to really slow down.

Most of this text never changes between frames, is there any way that when its been drawn once, it remains on the screen without having to redraw it?

Something I'll probably be working on next actually is a text object. This would store the image subrect and position of entire strings or char arrays in a sprite for each charactor, and just redraw it every frame, i imagine this would be a bit faster than doing all those calculations all the time. Problem though is that when i need to move it on the screen, i'd have to recalculate the position for every single sprite. Perhaps there's a way to merge these subrects into a single sprite object of some kind, or make them move together automaticly?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Sprite text help
« Reply #1 on: May 29, 2012, 01:09:19 pm »
You won't be able to do something satisfying with SFML 1.6, you should switch to SFML 2 if you can.
Laurent Gomila - SFML developer

bobingabout

  • Newbie
  • *
  • Posts: 47
    • View Profile
Re: Sprite text help
« Reply #2 on: May 29, 2012, 01:43:13 pm »
I could, but I'd rather not untill it has been officially released.

But assuming I do, what would you sugest I do with SFML2 to improve it?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Sprite text help
« Reply #3 on: May 29, 2012, 01:45:04 pm »
With SFML 2 you can easily gather all your characters into a single drawable entity.

But drawing 100 sprites should not be slow, even with the crappiest graphics card. Can you show a complete and minimal code that reproduces the problem?
Laurent Gomila - SFML developer

bobingabout

  • Newbie
  • *
  • Posts: 47
    • View Profile
Re: Sprite text help
« Reply #4 on: May 29, 2012, 06:06:17 pm »
Basicaly... it reuses the same sprite over and over for every char, and calculates and sets a new subrect and position. and it does this every frame.

Simply adding a dprintf with 100 chars in the passed char array, or multiple small ones is enough to drop the framerate from 60fps(VSync) to 20fps.

This is the actual drawing code.

void dprintf(char *str, ...)
{
        if(fontdata.font!=NULL)
        {
...
                sf::IntRect fontrect;
                sf::Vector2f destpos;
                sf::Vector2f destsize;

... formatting crap removed

                for(uint16 i=0;i<len;i++) // iterate through every char to draw it
                {
                        if(string[i] == '\r' || string[i] == '\n')
                        {
... new line crap here
                        }
                        else
                        {
// This part does the drawing for every char
                                fontrect.Left = string[i]%16*fontdata.font->w;
                                fontrect.Top = ((byte)string[i]/16)*fontdata.font->h;
                                fontrect.Right = fontrect.Left + fontdata.font->widths[string[i]];
                                fontrect.Bottom = fontrect.Top + fontdata.font->h;
                                fontdata.font->font.SetSubRect(fontrect);
                                fontdata.font->font.SetPosition(destpos);

                                fontdata.window->Draw(fontdata.font->font); // draw it!

                                destpos.x += fontdata.font->widths[string[i]];
                        }
                }
...
        }
}

 

the referenced image and sprite objects.

class Cfont
{
        public:
                sf::Image fontimage;
                sf::Sprite font;
... other crap removed
};

 

edit: removed most of it for you
« Last Edit: May 30, 2012, 09:58:31 am by bobingabout »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Sprite text help
« Reply #5 on: May 29, 2012, 06:48:55 pm »
Well, basically we don't care about your text drawing logic, all we want to see is the problem itself -- drawing 100 sprites (and if it's more complex and involves more code, try to find the minimum required).

Please read this carefully:
http://en.sfml-dev.org/forums/index.php?topic=5559.msg36368#msg36368
« Last Edit: May 29, 2012, 06:50:41 pm by Laurent »
Laurent Gomila - SFML developer

bobingabout

  • Newbie
  • *
  • Posts: 47
    • View Profile
Re: Sprite text help
« Reply #6 on: May 30, 2012, 10:15:07 am »
... I get your point. Edited to simplify, and show only the relevant code block.
in the main loop, you have this one line that will drop the framerate from 60fps to 20fps. yes, this one line and one line added alone kills the performance. It is a total bullshit line just for testing purposes.

dprintf("iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii");
 

okay, you can't run it, you don't need to... all i was wondering is if there was a "Faster" way to do it, and what SFML 2 might offer as an alternative to speed it up.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Sprite text help
« Reply #7 on: May 30, 2012, 10:25:12 am »
Like I said, drawing 100 sprites should never be slow even on the oldest graphics card. So before trying to find other drawing techniques, I'd like to make sure that your code doesn't contain mistakes :)

So you really need to write this very simple program that just draws 100 sprites, to see whether it's enough to get the bad performances or if it's your own code that slows the application down.

You need to clearly identify the problem before starting to optimize things.
Laurent Gomila - SFML developer

bobingabout

  • Newbie
  • *
  • Posts: 47
    • View Profile
Re: Sprite text help
« Reply #8 on: June 13, 2012, 10:29:20 am »
Okay, I've run some basic tests under your advice to basicly see if drawing 100 sprites slows down performance.

a quick rundown of what I did:
I basicly created a new text object class, for ever charactor, it creates a sprite, on object creation. it deletes and recreates all sprites when you change the text, and also holds some useful functions such as changing colour and position.
My test program contains a FPS counter too, so I can sort of Benchmark my results.
Also note: I didn't write a new program, I just stuck this inside my existing program, so there's a few sprites drawn already.

With the basic sprites of the program, it runs happily at around 60FPS.
Create the text object with a few sprites: Still runs happily around 60FPS.
Increase the number of sprites to 100+: Speed drops to around 30 - 40FPS. Remember, these are not changed between frames, simply created once then redrawn every frame with Window.Draw(Sprite).
Add a move location (Actual SF::Sprite::Move() function sent to every sprite in the vector): No noticable change
Set a new Position every frame (SF::Sprite::SetPosition() on every sprite every frame): No noticable change.
Change the colour, or specificly the Alpha on every frame: Slight reduction, but not really noticable.

In conclusion, the only thing that really made a difference was adding more sprites. I would've expected more of a change from some of these changes than I did.

« Last Edit: June 13, 2012, 10:32:19 am by bobingabout »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10998
    • View Profile
    • development blog
    • Email
Re: Sprite text help
« Reply #9 on: June 13, 2012, 03:53:14 pm »
So you really need to write this very simple program that just draws 100 sprites, to see whether it's enough to get the bad performances or if it's your own code that slows the application down.

If you create some text object class, I don't see how this is very simple...
Also like Laurent stated it would really really help if we saw the code, because most of the time it's not SFML nor the OS it's mostly the programmer that does things unefficently.

Also chaning color or anything like that will logically not decrese the FPS since it's a very cheap operation (changeing some float or integers) and hard work is then done by the draw call.
But why you get such a FPS drop is not (yet) that obvious.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

bobingabout

  • Newbie
  • *
  • Posts: 47
    • View Profile
Re: Sprite text help
« Reply #10 on: June 13, 2012, 05:18:51 pm »
You're right, some code...
This is the drawing routine.
void Ctext::edraw()
{
        unsigned short textsprites=textsprite.size();
        unsigned short effectsprites=effectsprite.size();
        unsigned short i;
        for(i=0; i < effectsprites; i++)
        {
                window->Draw(effectsprite[i]->sprite);
        }
        for(i=0; i < textsprites; i++)
        {
                window->Draw(textsprite[i]->sprite);
        }
}
 
thats it, that simple.
you just called Ctext.edraw() every frame. the long code that creates the sprites is run once. its not in the main loop so can't be called again.

textsprite and effectsprite are both vectors of pointers to offsetsprite objects.
std::vector<offsetsprite*> textsprite;
std::vector<offsetsprite*> effectsprite;


struct offsetsprite
{
        sf::Sprite sprite;
        sf::Vector2f offset;
};
 
again, very simple.  the offset vector variable contains the offset relative to the Ctext objects top left corner, so when you use my setposition() function, the position is set to the position fed into the function call, plus the offset.
textsprite[i]->sprite.SetPosition(pos.x + textsprite[i]->offset.x, pos.y + textsprite[i]->offset.y);
 
though not really that important to drawing the sprites.

Just in case it helps, and i doubt it, here is a few extracts from the textsprite creation function

void Ctext::createtextobjects()
{
        if(font!=NULL)
        {
                deletetextobjects(); //just to make sure we're clean
                sf::IntRect fontrect;
                sf::Vector2f destpos(0,0);
                offsetsprite *newtextsprite;

... lots of removed crap for calculating destpos
                for(uint16 i=0; i < len; i++)
                {
... more calculations

                        {
                                newtextsprite = new offsetsprite;
                                newtextsprite->offset.x = destpos.x;
                                newtextsprite->offset.y = destpos.y;
                                newtextsprite->sprite.SetImage(font->fontimage);
                                newtextsprite->sprite.SetColor(textcolour);
                               
... removed fontrect calculations
                                newtextsprite->sprite.SetSubRect(fontrect);
                                newtextsprite->sprite.SetPosition(destpos.x + pos.x, destpos.y + pos.y);
                                textsprite.push_back(newtextsprite);
                        }
                }
        }
}
 
« Last Edit: June 13, 2012, 05:42:47 pm by bobingabout »