Not logged inGosu Forums
Forum back to Help Search Register Login
Up Topic Gosu / Gosu Exchange / Text Drawing Performance
- - By meustrus Date 2011-02-01 23:33
So I've got a method to draw text onto an image using Texplay. It basically loads the text as an image with Gosu::Image.from_text and splices the image onto the destination. Let's say I have about 100 of these commands. They're called all at once to create an image that draws on the screen. I think it's the Gosu::Image.from_text call that's slowing me down at this point, because I (and plenty of others) have had pretty good results with the splice function. Is it possible to improve the performance of this function?

Secondly, I'm not sure the text is being drawn true to the font. Using Arial 24px, I expect it to have a bit more thickness than I'm seeing. The anti-aliasing isn't too good either. Maybe I'm just too used to seeing sub-pixel anti-aliasing (which would be nice if Gosu could tap into system settings on that).

I hope I'm not barking up the wrong tree here. If there's a better way to my goal (besides RMagick for various reasons) I'm willing to listen.
Parent - - By banister Date 2011-02-02 02:16
The problem is (im guessing) that Gosu::Image.from_text generates a new image each time it's called. In order for TexPlay to read the image data so it can perform a splice it has to cache the images (pull down image data from vram) - these cache operations are very, very expensive. I don't know a way around this, but spooner or jlnr may have some ideas.

Another thing that could be slowing it down is the syncing process after each splice - you can speed this up by passing :sync_mode => :no_sync to the splice calls, and calling a final force_sync at the end to sync the changes to vram all in one go.
Parent - - By Spooner Date 2011-02-02 02:29
Yeah, Gosu::Image#from_text creates a new image each time, which in itself will be prohibitively slow if you have image caching on (in Texplay). Much, much better to use Gosu::Font#draw and then you can avoid splicing altogether!
Parent - - By jlnr (dev) Date 2011-02-02 04:17
Also, Font internally renders everything at 2x size and shrinks it down, which looks nicer and less aliased for a variety of reasons.
Parent - - By Spooner Date 2011-02-02 12:31
Wouldn't the issue in this case be that the AA is applied to the new, blank, image, not the image the text was being spliced into? Thus, it would not look right, depending on what background the final image had.
Parent - - By jlnr (dev) Date 2011-02-02 16:42
Oh, I didn't take backgrounds into account. Anyway, +1 for Font! ;)
Parent - By banister Date 2011-02-02 23:39
out of interest, would RMagick be any faster here? and if so, why?
Parent - - By meustrus Date 2011-02-02 17:36
I'm sure it is better to use Gosu::Font#draw, but I'm trying to preserve an interface where the only means of drawing text is to draw it directly onto an image. So I can't do it that way. Anyway it's a lot easier to keep track of the information once it's drawn to a single image, rather than remembering the coordinates of each piece of text, especially if that image would also include non-text.
Parent - - By Spooner Date 2011-02-02 18:41
Yeah, but you need to remember the coordinates if you want to draw it once or 10000 times.

Anyway, if you must render it to the image, the best way is perhaps to look at Texplay's image rendering system, which allows you to use Image/Font draw methods to render onto another image (render_to_image).
Parent - - By meustrus Date 2011-02-02 19:35
Just tried out Texplay render_to_image. It seems to improve performance, but I lose alpha blending. Is there any way I can get it back, without knowing what's supposed to be drawn behind the text when I render_to_image?
Parent - - By Spooner Date 2011-02-02 19:38
Make sure you draw the background image into the image (the one you will render into) first...The way it actually works is to draw the original image onto the screen, allow you to do all your drawing, then copies the screen buffer back into the image, then finally blanks the screen. So either draw the background into the image before you start or draw it as the first thing inside the render block.
Parent - - By meustrus Date 2011-02-02 19:41
Like I said, is there any way to do preserve alpha transparency *without* knowing what draws behind? Just drawing what's behind it isn't even the same as preserving alpha transparency, because if the image then moves somewhere else it takes its background with it.
Parent - - By Spooner Date 2011-02-02 19:47
Sorry, I thought you meant ensuring text AA worked, regardless of what was behind the image. The problem with this render "workaround" is that the screen buffer doesn't maintain alpha values, so the final image will always have alpha = 255. You could use Image#clear (dest set to only black or some other value deemed to be transparent, but that is messy and doesn't maintain alpha levels).

If you are going to use the image as a transparency once it is composed, you might as well just repeatedly draw the image/fonts each frame. This is something Gosu manages quite quickly and should not impact your frame rate (even if you have a lot of text on the screen). Composing in this case is a very strong case of premature optimisation. The primary use case for render_to_image is so that you can SAVE images that have been generated by your game (this is what I use it for).
Parent - By meustrus Date 2011-02-02 19:56
I don't think that will work either, because what happens if I try to draw something on top of the text? Since the text is supposed to be part of the image, it's no longer possible to, say, make transparent a part of it. I'm starting to think that I'm going to have to use RMagick...
Parent - By meustrus Date 2011-03-03 20:45
I would like to formally request text drawing as a feature of Texplay. There should be two methods, let's call them "draw_text" and "text_size", which operate on a Gosu::Image. The "draw_text" method should take an x,y coordinate and a string, as well as, possibly, an options hash for font options like font name, size, italics, bold, etc. The "text_size" should take the same arguments, except x,y, and return the width and height of that string with those options if it is rendered. There may also possibly be an option in "text_size" as to whether it returns the actual pixel width or the kerned width, so that say you could draw a string one character at a time with the proper kerned width.

I have considered using RMagick for this, and possibly other drawing operations, and concluded that unless there is a capability to modify a Gosu texture every frame with the contents of the RMagick image, my performance would suffer as much or more than the current way I am doing things.

Here's a use case for drawing text directly to the image instead of returning an image containing that image:

Primary use case: draw lots of text on the screen without keeping track of all of it in Gosu::Window.update . For the sake of elegant programming, there could be a function that builds a chat room or some other text-heavy scene, then Gosu::Window only has to display one image. Perhaps this could be done with render_to_image, but then you can't change the background. Drawing from a Font is faster, but requires keeping track of all the different texts and their locations. Drawing a bunch of Gosu:Image's has the same disadvantage, and is slower to start; splicing them all into one image is simpler but still slow. And then what happens if I want to clip the text in a viewport? I'd probably have to either keep track of a call to Gosu::Window.clip_to if I'm using Font.

Ultimately I am trying to preserve an existing interface, and I can see this interface has an advantage when rendering text-heavy scenes. I shouldn't have to build extraneous Gosu textures to combine several text draws into one image.
- - By sadmemories20 Date 2011-04-01 03:25 Edited 2011-04-05 10:27
would RMagick be any faster here? and if so, why?

watch online movies
Parent - - By banister Date 2011-04-05 02:29
watch movies online? are you like a really clever spam spot? or are you paid by those guys?
Parent - - By erisdiscord Date 2011-04-05 04:40
Hah, I was about to reply to you with "The text is copied from one of banister's posts", but lo, that's you!

Anyways, reported it saying as much, but I suspect you've already done too.
Parent - By jlnr (dev) Date 2011-04-05 10:27 Edited 2011-04-05 10:32
Only changed the URL because that spam post was just too curiously on-topic :D -Ah, copied from banister.

Also, I can apparently only delete leaf postings. Lucky Spammer!
Up Topic Gosu / Gosu Exchange / Text Drawing Performance

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill