hlsl shader optimization

Thanks again :slight_smile: ! Forgot to change the texelsize…
The outlines on the sand texture are the same but the UI is temporary.
The shader performance seems about the same as before, probably because the extra spritebatch begin calls?

Edit: I’ll probably have some performance improvements against a fullscreen render target on very big resolutions.

Hmm, I’m surprised an additional sprite batch call brought you back to your old performance where you said you had 30+ :frowning:

Not 30+ spritebatch begin calls, 30+ spritebatch.drawstring calls per string drawn on screen.
I mean the old shader method (fullscreen render target). The shader is much faster than the drawstring method because each new string needs 30+ additional drawstring calls. The shader performance stays the same with more strings.

Oh I see. Interesting.

1 Like

So you don’t have the loops anymore now? I think you can use ddx and ddy instructions to replace some or maybe even all of the texture fetches.

Instead of alpha = max(alpha, sample) you can do alpha += sample. Not sure if that will have an impact, the compiler might have optimized it.

What does the shader look like right now?

Nvm, this won’t work. You can use ddx/ddy to get the texelsize so you don’t have to pass it into the shader.

I’ve updated the original post with my current shader.
There are no loops anymore but there’s an additional boolean value for the font shadow. How would I use ddx and ddy to get the texelsize?

As a recommendation, you might consider passing in each colour you want to set as a parameter. Then you don’t have to change the shader if you want to change colours.

1 Like

Very true. I’m currently still searching for an efficient way to draw multiple strings in different styles (ex.: some have a shadow and some don’t) without creating different render targets for each group of strings with a certain style. I don’t know if this is possible.

I’m not sure if that’s possible either, unless you bake the effect into the font itself. If they were always going to be the same colour this wouldn’t be a problem, but I remember your screenshots showing the inner colour being different.

I think the best you can do here is to just batch styles and render all text of each style to a render target, post process the effect, then layer them all together.

That said, with the graphics you’ve shown thus far (quite pixelated), and using down-scaled render targets, modern computers should be able to handle a lot without significant performance losses. If it does, you might just have to rethink how many text effects you want, or limit the colours for some of the effects and bake those visuals into sprites so you can avoid post processing?

1 Like

Thank you for the advice.

That was the drawstring() operation that is executed once per string before applying the outline shader. The main two are just the default outlines and a version without the outer outline when the text is being used as a button.

Most of the expense in your shader is all the samples. Look up “distance field font rendering”, if every pixel in the texture has, as lets say its alpha value, its distance in pixels from the border (the shortest distance) … then you only have to do one sample to know if its within the specified border range.

However, to answer the question about how people tend to generally do this…

Lets say your game has a TextControl which can be any one style. So if you want this sentence “Deals 300 damage!”, that is built from three text controls – since they need to be different styles. “Deals 300 damage!” could be just one.

Each text control is its own spritebatch.drawstring call … each style is a separate SpriteFont. You just have to emit controls in an efficient way, and it will be efficient.

You may or may not even need your own custom shader (colorized outlines might be a uniform). Anyhow there are also cool things you can do if you -do- have your own shader.

Actually though, unless you are having trouble hitting 60 fps or whatever your target is, and you know this is the culprit – move on to other things :smiley: I kind of doubt it is, considering how few pixels on the screen have text on them in a typical game.

@Dismiss

I already discussed using “distance field font rendering” for this in another thread, but used this shader because the implementation seemed overkill for what I wanted to achieve. (see 2D outline pixel shader on a pixel font)

I actually tested the performance difference between the shader and not drawing text at all. It was almost no difference. I currently have 400 - 500 fps on a 3440 x 1440 resolution (while also drawing 33k tiles) so framerate is not a problem (yet).
But thanks for the advice :slight_smile: .

Actually, this is really good advice. It’s easy to get caught up in performance tweaks. As someone who has gotten lost in this before, trust me… just make content. You can optimize these things later :smiley:

(Plus i’m looking forward to seeing what you’re building! :P)

1 Like

Hey. Late to the party I know.

I was curious if you could post your final usage of this shader (with render targets, sprite batch begin/end). I’m trying to put these pieces together to try it out.

Thanks!

EDIT: I would also love to know how you made your pixel font and got it to render pixel perfect

I’m not sure what Jelle did (this thread is quite old haha), but I ran into problems with pixel perfect fonts. There’s an issue with the monogame text renderer I logged here:

Unfortunately, it hasn’t been addressed. To work around this in my own projects, I just switched over to using MonoGame.Extended.BitmapFonts. I found it to work great for pixel fonts.

I talk a bit about it in a video I posted back then:

I change topics a bit later, but you can see the difference.

I hope that helps! :slight_smile:

1 Like

Hi @wazawoo

I remember I did some hacky stuff to get it right/less laggy, but if it helps you, I can open-source a part of the code for you (if I can retrieve it haha).

Like @Trinith said, this thread is quite old and my Monogame knowledge has decreased over the years, but I’ll be happy to help!

EDIT: I think I made my shader pixel perfect by accident, by rendering the font and shader with a very small scale and resizing the result again later (This was initially done for performance issues).

@Trinith Thanks much, and awesome video! I actually ended up going with BitmapFonts as well and it works great.

If anyone reading is on a Mac, the only app I could find that could make the bitmap font file is bmGlyph. All the docs mention using BMFont which is windows only. I don’t know the best approach for linux :confused:

@Jelle No worries. I’d be curious to check it out but if you have to sift through the archives it’s probably not worth. Thanks for the reply after 4 years :sweat_smile:

1 Like

@wazawoo

Damn I forgot to reply, for another year…

If you want the source code of the text renderer, you can send me a DM! I found it.

Regards