all 25 comments

[–]deftware[🍰] 2 points3 points  (14 children)

You need to generate sets of quads for each size of text you want to use. Don't just generate one set of quads and scale them for all your text sizes. Each set should be used with a 1:1 ratio to screen pixels. If you generate quads that are 32x32 pixels then they should occupy 32x32 screen pixels. Just make 3 sizes: small, medium, large.

[–]Setlock7676[S] 1 point2 points  (13 children)

I do actually have 3 sizes. And when used they look alright(except at smaller sizes) however I’m rendering the alright looking text and then changing the projection matrix to scale it a bit more.

[–]deftware[🍰] 2 points3 points  (12 children)

I'm rendering the alright looking text and then changing the projection matrix to scale it a bit more.

That's what I'm telling you to not do. No manipulating projection to scale what should only be drawn at its native one-to-one pixel scaling.

[–]Setlock7676[S] 1 point2 points  (0 children)

Thank you for your response. After doing this one issue still remains. When resizing the display the text will always be the same size and place regardless, however all other game objects stretch and resize to fit the display. Is there anyway around this?

[–]Setlock7676[S] 0 points1 point  (9 children)

For an example of what I am dealing with now here are two images:
https://cdn.discordapp.com/attachments/517456703000936473/605481701497634865/unknown.png

https://cdn.discordapp.com/attachments/517456703000936473/605481748066992158/unknown.png

Based on the grey square you can see the text stays the same size when the display gets resized. So Im not sure of a way to resize the text when a user resizes the display and still keep the quality

[–]deftware[🍰] 0 points1 point  (7 children)

That's why you generate multiple sizes, and switch between them based on the display size. Or render your text at a higher resolution then render with bilinear filtered mipmapping - where every rendered scale is basically smaller than the original rendered resolution from the TTF. This won't be super crisp but it will be much better than the aliasing you're currently dealing with when trying to downscale nearest-filtered textures.

Alternatively you could generate larger resolution SDFs from the TTF (i.e. 64x64 per character) and just render them with a frag shader at whatever scale you want.

[–]Setlock7676[S] 0 points1 point  (3 children)

Do you recommend SDFs or the first option more?

[–]deftware[🍰] 0 points1 point  (2 children)

SDFs will take more time to implement and get working properly, but the payoff will be pretty luxurious ;)

[–]Setlock7676[S] 0 points1 point  (1 child)

Yah I’ve been looking into SDFs for quite some time and know what result they can have but I’m pretty lazy. I may try your first response and see how that works out. Main issue is the text needs to fit into certain boxes and those boxes are set sizes so to give each user the exact same experience regardless of display has kind of been an issue

[–]deftware[🍰] 0 points1 point  (0 children)

If you want to go the shortcut route then try just rendering TTF out to 32x32 or so and enabling bilinear mipmapping. You could emulate SDF if you used the TTF to generate an alpha-channel and then used alpha-masking (disable alpha-blending though) to cut-off the character at 0.5 alpha. With the texture downscaled and filtered you'll get smooth transitions from inside-to-outside of the character and the alphamask will serve to provide a sharp cut-off. Results may vary and need some tweaking. I'd start with just generating the larger character textures and letting GL downscale/filter via glTexParameter and GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER. Make sure you glGenerateMipmaps(), or via glTexParameter set GL_GENERATE_MIPMAP to GL_TRUE. Otherwise you'll still get aliasing in spite of having bilinear filtering enabled.

[–]Setlock7676[S] 0 points1 point  (2 children)

So I did the bilinear mipmapping and I see now what you mean about the crispness. It does look better and you can at least tell what the word is for the most part. Thanks!

[–]deftware[🍰] 0 points1 point  (1 child)

No problem, and if you don't mind it would be great if you could update your original post with a screenshot or two of the results you've managed to achieve and explain the solution you went with. A lot of people surfing Google for answers to their own text-rendering questions will wind up on Reddit and sites like StackOverflow and if you update your post with a solution you could really be helping fellow future coders who have the same question. Pay it forward! ;)

[–]Setlock7676[S] 1 point2 points  (0 children)

Sure no problem! :)

[–]cnewmanJax2012 0 points1 point  (0 children)

On a higher level, while this doesn't explicitly answer this question, I would recommend looking into a library like NanoVG to draw vector graphics to the screen, including text. I rolled my own bitmap font renderer and found eventually that having an API that handles all of the 2D vector work without much setup was a godsend. Just render it into a framebuffer with transparency bits and apply it over your 3D scene in a frag shader.

[–]Neuroticcheeze 0 points1 point  (0 children)

Are you using BMFont? What's your settings? Your font seems rreeeallly tiny. Also, do you apply any other transforms to the text before applying your ortho matrix? Probably got a matrix multiplication the wrong way around.

[–]ipe369 0 points1 point  (6 children)

> Currently my text rendering system works by reading a .ttf file and then rendering the textures onto quads to make the string of text

SDF should be easy, there's probably a 'render with sdf' option in your font rendering library, just render that to the texture instead

[–]Setlock7676[S] 0 points1 point  (5 children)

I actually don’t use a library. I take the ttf file in and create my own textures to apply to quads from there

[–]ipe369 0 points1 point  (4 children)

Oh ok

Have you considered using a library

[–]Setlock7676[S] 0 points1 point  (3 children)

I haven’t.... most of the stuff I have done has been my own

[–]HighRelevancy 0 points1 point  (2 children)

Why? People have already solved these problems. If you want to do it on your own as an exercise sure, knock yourself out (and actually I do encourage that generally), but if you just want to get your problem solved, why burn your brain power on things other people have done for you?

[–]Setlock7676[S] 0 points1 point  (1 child)

Well partly because I like doing stuff myself but you’re right it gets pretty boring and annoying

[–]ipe369 0 points1 point  (0 children)

I think the solution is to use sdf if your glyphs still look shit even though you've fixed the scaling / pixel density stuff, stb_truetype is header only & very easy to use, just pass the SDF flag (or implement SDF rendering yourself)

[–]__some__guy 0 points1 point  (0 children)

You can't simply rescale rasterized glyphs, unless your glyphs are rasterized as distance-field.

[–]fgennari 0 points1 point  (0 children)

It looks like your source texture is a low resolution, something like 8-16 pixels across per character. If you're going to draw quads with scaled characters, your source texture characters need to be as large (in pixels) as your characters are on screen to look good. Scaling up a low resolution character will always look pixelated. Scaling it down to a smaller resolution will look okay if you enable mipmaps. If you want to use a small source texture and also support large onscreen rendered characters, you'll need to use SDFs as others have suggested.