[SOLVED] Black borders when using resized font-textures

Can anybody confirm this?
Edit: It is confirmed. Scroll down for further details.
I seem to have black borders when using a font texture (Color, Premultiply).
No problem with spritefonts though.

Seems to happen since MG3.6 but I’m not sure since it’s pretty subtle…



Doesn’t seem to be the build pipeline since it happens with pre 3.5 XNB file and 3.6-generated one.

LINKBACK:

Maybe a filtering issue? What does the texture look like? Black borders between the glyphs?

Sorry. Forgot. Here are the textures and they are fine as far as I can tell…
MG is 3.6.0.1488
Project is a WinDx one.

Investigated further…
Recreating the textures didn’t help. Even when adding extra space around the characters.

@Jjagg: What do you mean by filtering issues? PresentationParameters.MultiSampleCount? The draw call is like this:

                    Vector2.Zero, AspectedScale, SpriteEffects.None, 0);```

he is talking about texture filtering.

I couldn’t replicate the problem with standard fonts, and I’m not sure the spritebatch.Begin( … ) parameters make a difference, but you could try point filtering just to see if it removes the borders. The text will look bad if that works though.

Thx.
Hmmm.
###AnisotropicClamp:

###LinearClamp:

###PointClamp:

Looks like it has nothing to do with filtering then.
To me it looks like MG gets the boundaries of glyphs wrong all of a sudden.
I’ll build a test-project.

Ok.
First impression… It only happens when scaling the font.
Here’s an image with size = new Vector2(2,2) and anisotropicClamp:

What am I doing wrong here?

Here is the repo:

This contains various fonts at various sizes drawn using various samplerStates.

This problem can also happen for regular spritefonts that have there xml point size set very low then are scaled up. This occurred in xna as well especially when scaling up. The typical fix is MipMaping and picking sizes and simply not scaling as much as can be avoided.
Here it’s a double edged sword because its a question of does texture.Width * (1 / texture.Width); mean = to the texture width or = to texture.Width -1;? So then you go (1f+float.Min) / texture.Width; problem solved right nopp. Ergo There is a question of floating point precision in the context of error size. How big when scaling up will your rounding error be? More then float.Min so how much correction do you do? If i say draw at 9,9 with a width height of 1,1 do i mean 8,8,0,0? obviously not but then we want width -1 right?.

What you see here though im pretty sure is alpha blending on anti aliased edges between the background and drawn textures. Im guessing your clearing with cornflower blue or black. Set your clear color to green or white and run it and those borders should turn to grey.

You can try the following first turn off Multisample Antialiasing from the graphics device manager early on just before you apply changes. Hopefully that is enough.

If that’s not enough turn on point clamp as well. (doubt this will solve it either, but it might with the above). point shouldn’t sample the interpolation even when scaling this doesn’t mean that antialising wont kick in and alpha blend or sample the edges off the letter though.

That could be and probably is caused by a floating point error in scaling up.
No where in monogames code does the texel width add a float min to calculated position or a error correction value at least no where i saw. sometimes doing that will make you miss a pixel anyways then some letters get trimmed a pixel and it looks weird scaled to far down. So its a case of damned if you do damned if you don’t, but with text you might as well just clamp it anyways.

If that’s not enough and im guessing this is what your going to have to do…

fun fun … time to Edit your font texture.

Make sure that the edges are actually the right color and add a edit: another extra pixel of transparency around each letters bounding square. Yes floating point errors and scaling combined can push a error more then one pixel out i.e 2.

So the real solution as with all user defined sprites when per pixel scaling with a mask is involved, i.e. the pink mask in your font, is MipMaping and picking or some rigged version of this idea and in this case downscaling only.

With non premultiplied everything but the letters themselves can be transparent black and problem solved at least unless multisampling is on with oops antialiased drawn pixels when painting the sprites in your pain’t program ackkk!!!.

I really dislike pre-multiplied alpha i dunno why everyone thinks its so great.

What about ColorKeyEnabled & ColorKeyColor?
It looks like a leak from the edges due to texture filtering.
Normally the magenta mask should be turn into transparent (0,0,0,0) but here t looks like it’s black (0,0,0,255).

EDIT:
OK, the Font texture processor does not have those properties, but still …
The only case you should see leaks is from other characters and the mask is large enough to avoid this.

Thx for that answer.

It indeed still happens with size 1,1 when anisotropic filtering is enabled. When doing linear or point filtering at least the artifacts are gone with size 1,1.

Nope. Still black.

I’ve copied the textures in one of the first posts. They are fine. There are many perfectly transparent pixels above, for example, the letter ‘o’. And it happens just above the letter ‘o’ most of the time.

Everyone seems to think that this is an intrinsic problem of XNA/MG and maybe that is so, but in my case that behavior changed along the way. I have proof. The above is a screenshot from about a year ago.


There is simply no way I wouldn’t have spotted that.

So at some point along the way the game had no artifacts when drawing glyphs.
So now that that’s settled… What can be responsible for such a change.

Presentation parameters

Changed multisampling. No difference.

Spritefont image

I double checked the image, recreated it and even used a very old one and then again the new one. No change. The colors seem right in the image, transparency as well. When increasing the space around the glyphs the content pipeline makes the glyphs bigger and the artifacts are there as well just further away from the glyph.

Content pipeline

That seems to be the culprit. More in the next post.

MG rendering code

Didn’t check.

OK.
I think I found the culprit.
The content pipeline code in the develop branch.

Here’s what happened when I changed the generated XNB files POST compile but PRE load to some really old ones I had lying around in an old project branch (from the time when it still worked).

The thing is that switching the MG releases didn’t help because the CP that gets started when the build process starts is always the same, the one that is installed via the installer, e.g. 3.6.0.1488 in my case.

So the content pipeline seems to get the borders wrong when generating the XNB file.

EDIT: Upgraded to 3.6.0.1551 using the installer. Still no change/same problem. @nkast any ideas when/why that happened?

Have you tried with non-Premultiply?

My guess is that the bug could be somewhere in the Premultiply, ColorKey and Mipmap generation. Maybe the order we process those let’s the Mangenta ColorKey make it into the final texture as Black pixels (0,0,0,255).
Here is the history of FontTextureProssesor for any clues

Ok. Now we’re getting somewhere.
I can confirm that it works with the 3.5.1.1679 pipeline. So the change has to be after the last release.

The only PR fitting the timeline is https://github.com/MonoGame/MonoGame/pull/4996

Ok. I don’t know enough about the pipeline-code to do some decent debugging.

@Tom (sorry to summon you :blush:) ) Since you seem to have made those changes; Is that even possible? I’ve flicked through it; No obvious culprit imo. Unit tests?..

I see that the processor creates a new Texture with GlyphPacker.

Maybe the problem is with those lines

introduces by

Yes. Doesn’t change a thing.

Zooming in some of these lines in this image have turned grey just not all of them.
Which means some are being either multisampled aliased and blended and some are not sampling multiple texels or directly the texel grabbed from the texture is in the pink.

http://community.monogame.net/uploads/default/original/2X/c/cac3410156697fd597623c07ae83daafcc25be76.png

It really appears that the the uv grab positions are landing on the pink areas of the font with some sort of multi-sampling slash anti-aliasing from the texture coordinates.

Can you post a link to your font id like to manually shift the pixel grabs at run time and see what happens i have a project that i can modify to test it.
.
.
.
Looking breifly here.
I also noticed this is putting a one pixel border around the letters.
Is it possible this is not being colored correctly or is not fully aligned with everything in mind ?
Is it possible one texel of padding is not enough ?
This looks suspicious.

// Leave a one pixel border around every glyph in the output bitmap.
glyph.Width = sourceGlyphs[i].Subrect.Width + 2;
glyph.Height = sourceGlyphs[i].Subrect.Height + 2;

then later on…

var sourceGlyph = glyph.Source;
var sourceRegion = sourceGlyph.Subrect;
var destinationRegion = new Rectangle(glyph.X + 1, glyph.Y + 1, sourceRegion.Width, sourceRegion.Height);

    // TODO: This causes artifacts around borders.
    //BitmapUtils.PadBorderPixels(output, destinationRegion);

Sure. Here ya go.
Here is one of them FFF Tusj Font Free by Magnus Cederholm » Font Squirrel

There is a PR on MonoGame from @KonajuGames that should fix this bug.
Thx to all for investigating and @nkast for finding the right line.

1 Like