Why are my SDL_ttf fonts so pixelated and ugly? Are there better ways of rendering fonts?









up vote
0
down vote

favorite












Here is an example:



example Here is the corresponding code:



TTF_Font *Sans = TTF_OpenFont("resources/fonts/lato/Lato-Semibold.ttf", 36);

if( Sans == NULL )

std::cout << "Failed to load font! SDL_ttf Error: " << TTF_GetError() << std::endl;


else

SDL_Color White = 255, 255, 255;

SDL_Surface *surfaceMessage = TTF_RenderText_Blended(Sans, "GAME OVER", White);

SDL_Texture *Message = SDL_CreateTextureFromSurface(renderer_, surfaceMessage);

SDL_Rect Message_rect;
Message_rect.x = 100;
Message_rect.y = 100;
Message_rect.w = 500;
Message_rect.h = 500;

SDL_RenderCopy(renderer_, Message, NULL, &Message_rect);
SDL_RenderPresent(renderer_);




(yes, I free the surface later)










share|improve this question





















  • 36 is not very large font size, and you're scaling it to 500x500 output with bilinear interpolation. It's no wonder result is, well, interpolated. Rendering with bigger font size would probably be easiest solution (not saying it is the best though).
    – keltar
    Nov 10 at 17:32










  • @keltar I tried that. Certainly better, but even at very large sizes, while it's a lot less pixelated it's still... rather mediocre looking. Are there better ways?
    – ubadub
    Nov 10 at 22:45






  • 1




    Rescaling will always produce blurier image. This text is unlikely to be square, but you putting it into square image, so it will be tilted on vertical direction. Why use scaling at all if you're going for font quality? Take dimensions from surfaceMessage and use that as target width/height, adjust font size if required. Other ways would be prerended image in some graphics editor, or SDF fonts (may be very hard to use with SDL as no shaders exposed).
    – keltar
    Nov 11 at 7:16










  • @keltar ah! that's exactly what I was looking for! I didn't know you could query SDL_Texture for a width and height to ensure a proper resolution. If you post that as an answer, I'll accept it. Thank you so much!
    – ubadub
    Nov 11 at 8:23














up vote
0
down vote

favorite












Here is an example:



example Here is the corresponding code:



TTF_Font *Sans = TTF_OpenFont("resources/fonts/lato/Lato-Semibold.ttf", 36);

if( Sans == NULL )

std::cout << "Failed to load font! SDL_ttf Error: " << TTF_GetError() << std::endl;


else

SDL_Color White = 255, 255, 255;

SDL_Surface *surfaceMessage = TTF_RenderText_Blended(Sans, "GAME OVER", White);

SDL_Texture *Message = SDL_CreateTextureFromSurface(renderer_, surfaceMessage);

SDL_Rect Message_rect;
Message_rect.x = 100;
Message_rect.y = 100;
Message_rect.w = 500;
Message_rect.h = 500;

SDL_RenderCopy(renderer_, Message, NULL, &Message_rect);
SDL_RenderPresent(renderer_);




(yes, I free the surface later)










share|improve this question





















  • 36 is not very large font size, and you're scaling it to 500x500 output with bilinear interpolation. It's no wonder result is, well, interpolated. Rendering with bigger font size would probably be easiest solution (not saying it is the best though).
    – keltar
    Nov 10 at 17:32










  • @keltar I tried that. Certainly better, but even at very large sizes, while it's a lot less pixelated it's still... rather mediocre looking. Are there better ways?
    – ubadub
    Nov 10 at 22:45






  • 1




    Rescaling will always produce blurier image. This text is unlikely to be square, but you putting it into square image, so it will be tilted on vertical direction. Why use scaling at all if you're going for font quality? Take dimensions from surfaceMessage and use that as target width/height, adjust font size if required. Other ways would be prerended image in some graphics editor, or SDF fonts (may be very hard to use with SDL as no shaders exposed).
    – keltar
    Nov 11 at 7:16










  • @keltar ah! that's exactly what I was looking for! I didn't know you could query SDL_Texture for a width and height to ensure a proper resolution. If you post that as an answer, I'll accept it. Thank you so much!
    – ubadub
    Nov 11 at 8:23












up vote
0
down vote

favorite









up vote
0
down vote

favorite











Here is an example:



example Here is the corresponding code:



TTF_Font *Sans = TTF_OpenFont("resources/fonts/lato/Lato-Semibold.ttf", 36);

if( Sans == NULL )

std::cout << "Failed to load font! SDL_ttf Error: " << TTF_GetError() << std::endl;


else

SDL_Color White = 255, 255, 255;

SDL_Surface *surfaceMessage = TTF_RenderText_Blended(Sans, "GAME OVER", White);

SDL_Texture *Message = SDL_CreateTextureFromSurface(renderer_, surfaceMessage);

SDL_Rect Message_rect;
Message_rect.x = 100;
Message_rect.y = 100;
Message_rect.w = 500;
Message_rect.h = 500;

SDL_RenderCopy(renderer_, Message, NULL, &Message_rect);
SDL_RenderPresent(renderer_);




(yes, I free the surface later)










share|improve this question













Here is an example:



example Here is the corresponding code:



TTF_Font *Sans = TTF_OpenFont("resources/fonts/lato/Lato-Semibold.ttf", 36);

if( Sans == NULL )

std::cout << "Failed to load font! SDL_ttf Error: " << TTF_GetError() << std::endl;


else

SDL_Color White = 255, 255, 255;

SDL_Surface *surfaceMessage = TTF_RenderText_Blended(Sans, "GAME OVER", White);

SDL_Texture *Message = SDL_CreateTextureFromSurface(renderer_, surfaceMessage);

SDL_Rect Message_rect;
Message_rect.x = 100;
Message_rect.y = 100;
Message_rect.w = 500;
Message_rect.h = 500;

SDL_RenderCopy(renderer_, Message, NULL, &Message_rect);
SDL_RenderPresent(renderer_);




(yes, I free the surface later)







macos sdl sdl-ttf






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 10 at 7:03









ubadub

1,960821




1,960821











  • 36 is not very large font size, and you're scaling it to 500x500 output with bilinear interpolation. It's no wonder result is, well, interpolated. Rendering with bigger font size would probably be easiest solution (not saying it is the best though).
    – keltar
    Nov 10 at 17:32










  • @keltar I tried that. Certainly better, but even at very large sizes, while it's a lot less pixelated it's still... rather mediocre looking. Are there better ways?
    – ubadub
    Nov 10 at 22:45






  • 1




    Rescaling will always produce blurier image. This text is unlikely to be square, but you putting it into square image, so it will be tilted on vertical direction. Why use scaling at all if you're going for font quality? Take dimensions from surfaceMessage and use that as target width/height, adjust font size if required. Other ways would be prerended image in some graphics editor, or SDF fonts (may be very hard to use with SDL as no shaders exposed).
    – keltar
    Nov 11 at 7:16










  • @keltar ah! that's exactly what I was looking for! I didn't know you could query SDL_Texture for a width and height to ensure a proper resolution. If you post that as an answer, I'll accept it. Thank you so much!
    – ubadub
    Nov 11 at 8:23
















  • 36 is not very large font size, and you're scaling it to 500x500 output with bilinear interpolation. It's no wonder result is, well, interpolated. Rendering with bigger font size would probably be easiest solution (not saying it is the best though).
    – keltar
    Nov 10 at 17:32










  • @keltar I tried that. Certainly better, but even at very large sizes, while it's a lot less pixelated it's still... rather mediocre looking. Are there better ways?
    – ubadub
    Nov 10 at 22:45






  • 1




    Rescaling will always produce blurier image. This text is unlikely to be square, but you putting it into square image, so it will be tilted on vertical direction. Why use scaling at all if you're going for font quality? Take dimensions from surfaceMessage and use that as target width/height, adjust font size if required. Other ways would be prerended image in some graphics editor, or SDF fonts (may be very hard to use with SDL as no shaders exposed).
    – keltar
    Nov 11 at 7:16










  • @keltar ah! that's exactly what I was looking for! I didn't know you could query SDL_Texture for a width and height to ensure a proper resolution. If you post that as an answer, I'll accept it. Thank you so much!
    – ubadub
    Nov 11 at 8:23















36 is not very large font size, and you're scaling it to 500x500 output with bilinear interpolation. It's no wonder result is, well, interpolated. Rendering with bigger font size would probably be easiest solution (not saying it is the best though).
– keltar
Nov 10 at 17:32




36 is not very large font size, and you're scaling it to 500x500 output with bilinear interpolation. It's no wonder result is, well, interpolated. Rendering with bigger font size would probably be easiest solution (not saying it is the best though).
– keltar
Nov 10 at 17:32












@keltar I tried that. Certainly better, but even at very large sizes, while it's a lot less pixelated it's still... rather mediocre looking. Are there better ways?
– ubadub
Nov 10 at 22:45




@keltar I tried that. Certainly better, but even at very large sizes, while it's a lot less pixelated it's still... rather mediocre looking. Are there better ways?
– ubadub
Nov 10 at 22:45




1




1




Rescaling will always produce blurier image. This text is unlikely to be square, but you putting it into square image, so it will be tilted on vertical direction. Why use scaling at all if you're going for font quality? Take dimensions from surfaceMessage and use that as target width/height, adjust font size if required. Other ways would be prerended image in some graphics editor, or SDF fonts (may be very hard to use with SDL as no shaders exposed).
– keltar
Nov 11 at 7:16




Rescaling will always produce blurier image. This text is unlikely to be square, but you putting it into square image, so it will be tilted on vertical direction. Why use scaling at all if you're going for font quality? Take dimensions from surfaceMessage and use that as target width/height, adjust font size if required. Other ways would be prerended image in some graphics editor, or SDF fonts (may be very hard to use with SDL as no shaders exposed).
– keltar
Nov 11 at 7:16












@keltar ah! that's exactly what I was looking for! I didn't know you could query SDL_Texture for a width and height to ensure a proper resolution. If you post that as an answer, I'll accept it. Thank you so much!
– ubadub
Nov 11 at 8:23




@keltar ah! that's exactly what I was looking for! I didn't know you could query SDL_Texture for a width and height to ensure a proper resolution. If you post that as an answer, I'll accept it. Thank you so much!
– ubadub
Nov 11 at 8:23












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










TTF_RenderText_Blended and other SDL_ttf font rendering functions produces surface based on font size specified when font was opened (along with font style itself and symbols in the text line). You rescale that result to 500x500 rectangle, which causes both proportions distortion and blurier image, as source image have different dimensions.



To avoid that you should avoid rescaling first - use surfaceMessage->w and surfaceMessage->h (or SDL_QueryTexture on Message) to get original dimensions, then RenderCopy to the same sized rectangle.



Of course if text is static and not localised pre-rendering this static image in some graphics editor is also a good option.



As a side note, it may be copy-paste oversimplification, but it appears you opening font and recreating your target texture on each frame. This is very slow and provides almost no benefits.






share|improve this answer




















  • FYI surfaceMessage->w doesn't seem to work, you have to use SDL_QueryTexture. Anyways, thanks a lot!
    – ubadub
    Nov 11 at 9:26










  • I can't imagine implementation where texture dimensions will differ from surface's it was created from. Are you saying that's the case for you?
    – keltar
    Nov 11 at 11:16










  • No, that's not the issue; surfaceMessage->w makes the compiler throw an error that says "Member access into incomplete type SDL_Texture"
    – ubadub
    Nov 11 at 19:58











  • I've used the same variable names as was in question, implying types are the same. So SDL_Surface *surfaceMessage have type SDL_Surface*, which can be accessed directly for its dimensions (defined in SDL_surface.h, included automatically via SDL.h), while SDL_Texture *Message is opaque type SDL_Texture* that you can't dereference (something like typedef SDL_Texture SDL_Texture; - your side don't know what fields it have or even its size).
    – keltar
    Nov 12 at 4:50










  • I don't follow- isn't there only a single definition of SDL_Surface available if I include SDL2.h?
    – ubadub
    Nov 12 at 5:47










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53236762%2fwhy-are-my-sdl-ttf-fonts-so-pixelated-and-ugly-are-there-better-ways-of-renderi%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










TTF_RenderText_Blended and other SDL_ttf font rendering functions produces surface based on font size specified when font was opened (along with font style itself and symbols in the text line). You rescale that result to 500x500 rectangle, which causes both proportions distortion and blurier image, as source image have different dimensions.



To avoid that you should avoid rescaling first - use surfaceMessage->w and surfaceMessage->h (or SDL_QueryTexture on Message) to get original dimensions, then RenderCopy to the same sized rectangle.



Of course if text is static and not localised pre-rendering this static image in some graphics editor is also a good option.



As a side note, it may be copy-paste oversimplification, but it appears you opening font and recreating your target texture on each frame. This is very slow and provides almost no benefits.






share|improve this answer




















  • FYI surfaceMessage->w doesn't seem to work, you have to use SDL_QueryTexture. Anyways, thanks a lot!
    – ubadub
    Nov 11 at 9:26










  • I can't imagine implementation where texture dimensions will differ from surface's it was created from. Are you saying that's the case for you?
    – keltar
    Nov 11 at 11:16










  • No, that's not the issue; surfaceMessage->w makes the compiler throw an error that says "Member access into incomplete type SDL_Texture"
    – ubadub
    Nov 11 at 19:58











  • I've used the same variable names as was in question, implying types are the same. So SDL_Surface *surfaceMessage have type SDL_Surface*, which can be accessed directly for its dimensions (defined in SDL_surface.h, included automatically via SDL.h), while SDL_Texture *Message is opaque type SDL_Texture* that you can't dereference (something like typedef SDL_Texture SDL_Texture; - your side don't know what fields it have or even its size).
    – keltar
    Nov 12 at 4:50










  • I don't follow- isn't there only a single definition of SDL_Surface available if I include SDL2.h?
    – ubadub
    Nov 12 at 5:47














up vote
1
down vote



accepted










TTF_RenderText_Blended and other SDL_ttf font rendering functions produces surface based on font size specified when font was opened (along with font style itself and symbols in the text line). You rescale that result to 500x500 rectangle, which causes both proportions distortion and blurier image, as source image have different dimensions.



To avoid that you should avoid rescaling first - use surfaceMessage->w and surfaceMessage->h (or SDL_QueryTexture on Message) to get original dimensions, then RenderCopy to the same sized rectangle.



Of course if text is static and not localised pre-rendering this static image in some graphics editor is also a good option.



As a side note, it may be copy-paste oversimplification, but it appears you opening font and recreating your target texture on each frame. This is very slow and provides almost no benefits.






share|improve this answer




















  • FYI surfaceMessage->w doesn't seem to work, you have to use SDL_QueryTexture. Anyways, thanks a lot!
    – ubadub
    Nov 11 at 9:26










  • I can't imagine implementation where texture dimensions will differ from surface's it was created from. Are you saying that's the case for you?
    – keltar
    Nov 11 at 11:16










  • No, that's not the issue; surfaceMessage->w makes the compiler throw an error that says "Member access into incomplete type SDL_Texture"
    – ubadub
    Nov 11 at 19:58











  • I've used the same variable names as was in question, implying types are the same. So SDL_Surface *surfaceMessage have type SDL_Surface*, which can be accessed directly for its dimensions (defined in SDL_surface.h, included automatically via SDL.h), while SDL_Texture *Message is opaque type SDL_Texture* that you can't dereference (something like typedef SDL_Texture SDL_Texture; - your side don't know what fields it have or even its size).
    – keltar
    Nov 12 at 4:50










  • I don't follow- isn't there only a single definition of SDL_Surface available if I include SDL2.h?
    – ubadub
    Nov 12 at 5:47












up vote
1
down vote



accepted







up vote
1
down vote



accepted






TTF_RenderText_Blended and other SDL_ttf font rendering functions produces surface based on font size specified when font was opened (along with font style itself and symbols in the text line). You rescale that result to 500x500 rectangle, which causes both proportions distortion and blurier image, as source image have different dimensions.



To avoid that you should avoid rescaling first - use surfaceMessage->w and surfaceMessage->h (or SDL_QueryTexture on Message) to get original dimensions, then RenderCopy to the same sized rectangle.



Of course if text is static and not localised pre-rendering this static image in some graphics editor is also a good option.



As a side note, it may be copy-paste oversimplification, but it appears you opening font and recreating your target texture on each frame. This is very slow and provides almost no benefits.






share|improve this answer












TTF_RenderText_Blended and other SDL_ttf font rendering functions produces surface based on font size specified when font was opened (along with font style itself and symbols in the text line). You rescale that result to 500x500 rectangle, which causes both proportions distortion and blurier image, as source image have different dimensions.



To avoid that you should avoid rescaling first - use surfaceMessage->w and surfaceMessage->h (or SDL_QueryTexture on Message) to get original dimensions, then RenderCopy to the same sized rectangle.



Of course if text is static and not localised pre-rendering this static image in some graphics editor is also a good option.



As a side note, it may be copy-paste oversimplification, but it appears you opening font and recreating your target texture on each frame. This is very slow and provides almost no benefits.







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 11 at 9:06









keltar

12.2k12534




12.2k12534











  • FYI surfaceMessage->w doesn't seem to work, you have to use SDL_QueryTexture. Anyways, thanks a lot!
    – ubadub
    Nov 11 at 9:26










  • I can't imagine implementation where texture dimensions will differ from surface's it was created from. Are you saying that's the case for you?
    – keltar
    Nov 11 at 11:16










  • No, that's not the issue; surfaceMessage->w makes the compiler throw an error that says "Member access into incomplete type SDL_Texture"
    – ubadub
    Nov 11 at 19:58











  • I've used the same variable names as was in question, implying types are the same. So SDL_Surface *surfaceMessage have type SDL_Surface*, which can be accessed directly for its dimensions (defined in SDL_surface.h, included automatically via SDL.h), while SDL_Texture *Message is opaque type SDL_Texture* that you can't dereference (something like typedef SDL_Texture SDL_Texture; - your side don't know what fields it have or even its size).
    – keltar
    Nov 12 at 4:50










  • I don't follow- isn't there only a single definition of SDL_Surface available if I include SDL2.h?
    – ubadub
    Nov 12 at 5:47
















  • FYI surfaceMessage->w doesn't seem to work, you have to use SDL_QueryTexture. Anyways, thanks a lot!
    – ubadub
    Nov 11 at 9:26










  • I can't imagine implementation where texture dimensions will differ from surface's it was created from. Are you saying that's the case for you?
    – keltar
    Nov 11 at 11:16










  • No, that's not the issue; surfaceMessage->w makes the compiler throw an error that says "Member access into incomplete type SDL_Texture"
    – ubadub
    Nov 11 at 19:58











  • I've used the same variable names as was in question, implying types are the same. So SDL_Surface *surfaceMessage have type SDL_Surface*, which can be accessed directly for its dimensions (defined in SDL_surface.h, included automatically via SDL.h), while SDL_Texture *Message is opaque type SDL_Texture* that you can't dereference (something like typedef SDL_Texture SDL_Texture; - your side don't know what fields it have or even its size).
    – keltar
    Nov 12 at 4:50










  • I don't follow- isn't there only a single definition of SDL_Surface available if I include SDL2.h?
    – ubadub
    Nov 12 at 5:47















FYI surfaceMessage->w doesn't seem to work, you have to use SDL_QueryTexture. Anyways, thanks a lot!
– ubadub
Nov 11 at 9:26




FYI surfaceMessage->w doesn't seem to work, you have to use SDL_QueryTexture. Anyways, thanks a lot!
– ubadub
Nov 11 at 9:26












I can't imagine implementation where texture dimensions will differ from surface's it was created from. Are you saying that's the case for you?
– keltar
Nov 11 at 11:16




I can't imagine implementation where texture dimensions will differ from surface's it was created from. Are you saying that's the case for you?
– keltar
Nov 11 at 11:16












No, that's not the issue; surfaceMessage->w makes the compiler throw an error that says "Member access into incomplete type SDL_Texture"
– ubadub
Nov 11 at 19:58





No, that's not the issue; surfaceMessage->w makes the compiler throw an error that says "Member access into incomplete type SDL_Texture"
– ubadub
Nov 11 at 19:58













I've used the same variable names as was in question, implying types are the same. So SDL_Surface *surfaceMessage have type SDL_Surface*, which can be accessed directly for its dimensions (defined in SDL_surface.h, included automatically via SDL.h), while SDL_Texture *Message is opaque type SDL_Texture* that you can't dereference (something like typedef SDL_Texture SDL_Texture; - your side don't know what fields it have or even its size).
– keltar
Nov 12 at 4:50




I've used the same variable names as was in question, implying types are the same. So SDL_Surface *surfaceMessage have type SDL_Surface*, which can be accessed directly for its dimensions (defined in SDL_surface.h, included automatically via SDL.h), while SDL_Texture *Message is opaque type SDL_Texture* that you can't dereference (something like typedef SDL_Texture SDL_Texture; - your side don't know what fields it have or even its size).
– keltar
Nov 12 at 4:50












I don't follow- isn't there only a single definition of SDL_Surface available if I include SDL2.h?
– ubadub
Nov 12 at 5:47




I don't follow- isn't there only a single definition of SDL_Surface available if I include SDL2.h?
– ubadub
Nov 12 at 5:47

















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53236762%2fwhy-are-my-sdl-ttf-fonts-so-pixelated-and-ugly-are-there-better-ways-of-renderi%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Barbados

How to read a connectionString WITH PROVIDER in .NET Core?

Node.js Script on GitHub Pages or Amazon S3