Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Text drawn to renderTexture looks broken (see example)  (Read 9261 times)

0 Members and 1 Guest are viewing this topic.

ChonDee

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Text drawn to renderTexture looks broken (see example)
« on: August 07, 2012, 03:39:50 am »
Hi,

I am working on making an in-game terminal/debug console for my engine, and I wanted to draw all the text once to a renderTexture, then I'll just scroll the sprite it is linked to up, so I don't actually need to render the text every frame.

I have noticed however, that when I directly draw text on my main renderWindow, it looks perfect, but if I draw the text on a renderTexture, and then draw the sprite linked to the renderTexture to the renderWindow, it looks ...broken. I can't really find a better word to describe it, but I have attached a screenshot of what I am talking about.

The top 3 lines are drawn to the renderWindow, and look good, the bottom ones are on the renderTexture and look the way it shows.


EDIT: I uploaded a bigger pic without compression, that better shows this:

In case the direct image link changes, and the image doesn't show, try this:
http://postimage.org/image/7ss9oaj7j/

Here is a minimal and complete (and super sloppy) example that reproduces the output in the screenshot:
(I have attached the font I used)
#include <SFML/Graphics.hpp>

int main()
{
        sf::RenderWindow App;
        sf::VideoMode VM;
        VM.width = 800; VM.height = 400;
        sf::RenderTexture rTexture; sf::Sprite rSprite;
        rTexture.create(800,400);
        rSprite.setTexture(rTexture.getTexture());
        sf::Font ProFont;
        ProFont.loadFromFile("profontwindows.ttf");
        sf::Text Text;
        Text.setFont(ProFont);
        Text.setCharacterSize(9);
        Text.setString("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat \n nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
        App.create(VM, "sfml");
        App.clear(sf::Color(128,128,128));
        App.draw(Text);
        Text.move(0,50);
        rTexture.draw(Text);
        rTexture.display();
        App.draw(rSprite);
        App.display();
        while (1)       {}
        return 0;
}
 

Laurent, if you are reading this, what do you think is causing this? Is there some setting I would need to apply to the renderTexture? I have tried with smooth on and off, and saw no difference.
This "graininess" becomes less visible the bigger the characterSize is, but I would need this font as small as it is now, I want the most possible text displayed on the screen (this is the font and size I use in my IDE as well).

Thank You in advance!
(I am using SFML 2.0, the snapshot I downloaded on 08-03-12 (3 days ago), in Win7)

[attachment deleted by admin]
« Last Edit: August 07, 2012, 08:40:57 am by ChonDee »

lrx

  • Newbie
  • *
  • Posts: 29
    • View Profile
Re: Text drawn to renderTexture looks broken (see example)
« Reply #1 on: August 07, 2012, 06:36:44 am »
Possibly this bug
But to confirm you'll have to wait for someone who actually knows stuff :)

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Text drawn to renderTexture looks broken (see example)
« Reply #2 on: August 07, 2012, 02:58:38 pm »
This is not a bug.

Whenever you use a RenderTexture you must always make sure to clear it before drawing. If not any blending that is done will blend with the wrong background color. Since the text in SFML is smoothed it is also blended with the background and will break if the RenderTexture is not cleared. This only happens if 2 RenderTargets have different background colors, which in your case is gray and transparent (not clearing = transparent).

Also, instead of moving the text, you should move the sprite. This will ensure you don't overdraw anything you previously drew if using a solid background color.

Fixed code:
#include <SFML/Graphics.hpp>

int main()
{
        sf::RenderWindow App;
        sf::VideoMode VM;
        VM.width = 800; VM.height = 400;
        sf::RenderTexture rTexture; sf::Sprite rSprite;
        rTexture.create(800,400);
        rSprite.setTexture(rTexture.getTexture());
        sf::Font ProFont;
        ProFont.loadFromFile("profontwindows.ttf");
        sf::Text Text;
        Text.setFont(ProFont);
        Text.setCharacterSize(9);
        Text.setString("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat \n nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
        App.create(VM, "sfml");
        App.clear(sf::Color(128,128,128));
        App.draw(Text);
        rSprite.move(0,50);
        rTexture.clear(sf::Color(128,128,128));
        rTexture.draw(Text);
        rTexture.display();
        App.draw(rSprite);
        App.display();
        while (1)       {}
        return 0;
}
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

ChonDee

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Re: Text drawn to renderTexture looks broken (see example)
« Reply #3 on: August 07, 2012, 07:51:51 pm »
Thank you for your answer!

I didn't clear the rendertexture on purpose, since I wanted to have the text on a transparent background, and I  only need to clear it when one page gets filled (in my engine), and even then with a transparent color.

So now it appears, that this is caused by drawing text on transparent background, and not from it being a renderTexture.

Do you think there's any way to improve the quality of the text when drawn to a transparent, or semi-transparent renderTexture, so I could have some scrolling text/console overlay above my game?

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Text drawn to renderTexture looks broken (see example)
« Reply #4 on: August 07, 2012, 10:05:10 pm »
Do you think there's any way to improve the quality of the text when drawn to a transparent, or semi-transparent renderTexture, so I could have some scrolling text/console overlay above my game?
No, unless Laurent creates some way to disable font smoothing.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

ChonDee

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Re: Text drawn to renderTexture looks broken (see example)
« Reply #5 on: August 07, 2012, 11:41:04 pm »
I see, that's what I was afraid of. This is a pixelated bitmap font, that otherwise would look great without smoothing, but if there is no solid background behind the text, whatever the smoothing does breaks it. I think if there would be a way to turn off smoothing, it would resolve this.

I see others on the forum have requested this option, I hope an sf::Font::setSmooth(bool) kind of option would be added in the near future.

Thank you for your help!
« Last Edit: August 08, 2012, 12:20:15 am by ChonDee »

ChonDee

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Re: Text drawn to renderTexture looks broken (see example)
« Reply #6 on: August 10, 2012, 08:01:02 am »
My solution

So I kept trying to fix this somehow, and even though this is probably not the cleanest way to do it, I managed to fix the problem I was dealing with, which is the very low quality of text drawn to a transparent background renderTexture if a small character size font is used.

This problem is (most likely) due to the font smoothing SFML uses, and is most visible when the text is so small, that the "lines" the characters are made of are less than a pixel "thick". In that case, the smoothing fades away even that single pixel "thickness" at some places, resulting in the low visual quality.

I was able to fix this, by drawing the text to the renderTexture multiple times (2 is enough), which might significantly decrease performance if the text is redrawn every frame, but in my case I only render the text once, after that I am just dealing with the renderTexture. By drawing the text at least twice, the areas that got lowered alpha values due to the smoothing get to be completely solid this way.

I have modified the previous example code, to show the results:

http://postimage.org/image/e4cympxfr/

#include <SFML/Graphics.hpp>

int main()
{       sf::RenderWindow App;
        sf::VideoMode VM;
        VM.width = 800; VM.height = 400;
        sf::RenderTexture rTexture; sf::Sprite rSprite;
        rTexture.create(800,400);
        rSprite.setTexture(rTexture.getTexture());
        sf::Font ProFont;
        ProFont.loadFromFile("profontwindows.ttf");
        sf::Text Text;
        Text.setFont(ProFont);
        Text.setCharacterSize(9);
        Text.setString("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \n exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in eprehenderit in voluptate velit esse cillum dolore eu fugiat \n nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
        App.create(VM, "sfml");
        App.clear(sf::Color(128,128,128));
        App.draw(Text);
        Text.move(0,100);
        //xrTexture.clear(sf::Color(0,0,0,255));
        rTexture.draw(Text);
        Text.move(0,75); rTexture.draw(Text); rTexture.draw(Text);
        Text.move(0,75); rTexture.draw(Text); rTexture.draw(Text); rTexture.draw(Text); rTexture.draw(Text);
        rTexture.display();
        App.draw(rSprite);
        App.display();
        while (App.isOpen())       {}
        return 0;

}

I hope this helps someone, but still, I think giving an option to disable font smoothing would be a better solution.
« Last Edit: August 10, 2012, 08:11:01 am by ChonDee »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Text drawn to renderTexture looks broken (see example)
« Reply #7 on: August 10, 2012, 08:45:34 am »
A better solution would be to disable alpha-blending when drawing the text to the render-texture. Indeed, you only want to make a 1:1 copy of the text alpha there, and interpret it only when drawing the final render-texture to the screen.

Unfortunately sf::Text currently forces the blending mode to sf::BlendAlpha, but I could remove this, which would allow you to use sf::BlendNone and get the desired result without ugly hacks.

And by the way, you shouldn't rely on an uncleared surface being transparent. As far as I know, the contents are initially undefined. So if you want a transparent background, clear with a transparent color ;)
« Last Edit: August 10, 2012, 08:47:53 am by Laurent »
Laurent Gomila - SFML developer

ChonDee

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Re: Text drawn to renderTexture looks broken (see example)
« Reply #8 on: August 10, 2012, 09:06:41 am »
Thanks for the reply,
It would be great if the blend modes would work for drawing text.

Also thanks for the heads up on having to clear the renderTexture initially.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Text drawn to renderTexture looks broken (see example)
« Reply #9 on: August 10, 2012, 09:11:30 am »
Quote
It would be great if the blend modes would work for drawing text.
Yeah, I think I'll do this little modification. It should be ready soon (it's only a single line of code to remove).
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Text drawn to renderTexture looks broken (see example)
« Reply #10 on: August 10, 2012, 03:05:11 pm »
Done.
Laurent Gomila - SFML developer

ChonDee

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Re: Text drawn to renderTexture looks broken (see example)
« Reply #11 on: August 10, 2012, 11:47:34 pm »
EDIT: Deleted, I was wrong :)
« Last Edit: August 11, 2012, 12:36:54 am by ChonDee »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Text drawn to renderTexture looks broken (see example)
« Reply #12 on: August 10, 2012, 11:54:25 pm »
Sorry, I forgot to push :-[

Quote
I have looked into how the smoothing is applied more, and it seems, that not only does the smoothing lowers the alpha on the base pixels of the font, but adds some very low alpha pictures around it as well (which is completely normal for smoothing, and looks nice with larger character sizes).
In the case of small character sizes, it will mean however, that these very low alpha surrounding pixels will also get to be 255, resulting in something like this:
Yes. And? Do you mean that this could be a problem? Because it's not, since alpha is copied too, the final result is the same as if the text was drawn directly to the window.

Quote
I am wondering, would it be possible to add an option to turn off text smoothing itself?
It's in the task tracker. But for a different purpose (we don't need that here).
« Last Edit: August 10, 2012, 11:57:03 pm by Laurent »
Laurent Gomila - SFML developer

ChonDee

  • Jr. Member
  • **
  • Posts: 62
    • View Profile
Re: Text drawn to renderTexture looks broken (see example)
« Reply #13 on: August 11, 2012, 12:38:47 am »
I tested it, and as you said, with BlendNone the text drawn on a transparent renderTexture now looks as if it was drawn to the window directly.

This completely solves all my concerns written in this thread, thank you very much!