Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sf::Font::SetSmooth() #526

Closed
hsdk123 opened this issue Jan 14, 2014 · 12 comments
Closed

sf::Font::SetSmooth() #526

hsdk123 opened this issue Jan 14, 2014 · 12 comments

Comments

@hsdk123
Copy link

hsdk123 commented Jan 14, 2014

I'm realising for different fonts, font textures give a blurry touch that I'd rather head away from.

Here's a past thread that also proposes sf::Font::SetSmooth(), saying this is due to the default smoothing of fonts.
http://en.sfml-dev.org/forums/index.php?topic=5346.0

If the visual look of a font is different for each font, I think it's justifiable to say that having sf::Font::SetSmooth() would give users a clean convenient option to manage this themselves and their own fonts.

Example)

screenshot

I'm currently working on a game for a Japanese audience and all the japanese fonts I'm using appear just blurry.
The text inside the red square show the blur clearly, especially the 1st and 3rd lines; I'm doing nothing special, just loading the font from the file (.ttf) and attaching it to an sf::Text.

@Foaly
Copy link
Contributor

Foaly commented Jan 14, 2014

What version of SFML are you using? If you are using 2.1 I recommend switching to the latest source, because of this fix. It has been added recently and improves text rendering quiet a bit.

@hsdk123
Copy link
Author

hsdk123 commented Jan 14, 2014

@Foaly I'm using the github source, downloaded a week ago. Thanks for the help;

@LaurentGomila
Copy link
Member

Could you provide the font that you're using, as well as a code sample (especially the text) which looks blurry?

@hsdk123
Copy link
Author

hsdk123 commented Feb 4, 2014

Files:
https://github.com/hsdk123/mis_upload/master/btn_sel.png
https://github.com/hsdk123/mis_upload/master/msgothi0.ttf

The code's slightly long due to a peculiarity found while preparing the sample.

sf::RenderWindow* renderWindow;
void DrawShadowText( const sf::Text* pNText );
int main()
{
    renderWindow = new sf::RenderWindow( sf::VideoMode( 800, 600 ), "Window" );

    sf::Font font;
    if ( !font.loadFromFile( "msgothi0.ttf" ) )
    {
        return 0;
    }
    sf::Text text1;
    text1.setFont( font );
    text1.setString( L"テキストチュートリアル" );
    text1.setPosition( sf::Vector2f( 0, 60 ) );
    text1.setCharacterSize( 24 );
    text1.setStyle( sf::Text::Bold );

    sf::Text text2 = text1;
    text2.setString( L"イメージ、移動 チュートリアル" );
    text2.setPosition( sf::Vector2f( 0, 120 ) );

    sf::Text text3 = text1;
    text3.setString( L"ゲームを終了する" );
    text3.setPosition( sf::Vector2f( 0, 180 ) );

    sf::Text text4 = text3;
    text4.setPosition( sf::Vector2f( 0, 240 ) );

    renderWindow->setVerticalSyncEnabled( true );

    sf::Sprite bg;
    sf::Texture texture;
    texture.loadFromFile( "btn_sel.png" );
    bg.setTexture( texture );
    bg.setPosition( sf::Vector2f( -60, 90 ) );

    sf::Sprite bg3 = bg;
    bg3.setPosition( sf::Vector2f( -60, 150 ) );

    sf::Sprite bg4 = bg;
    bg4.setPosition( sf::Vector2f( -60, 210 ) );

    auto btnSize = bg3.getGlobalBounds();
    auto textSize = text3.getLocalBounds();
    text3.setPosition(
        (btnSize.left + 0.5f * (btnSize.width - textSize.width) - textSize.left),
        (btnSize.top + 0.5f * (btnSize.height - textSize.height) - textSize.top)
        );

    while ( renderWindow->isOpen() )
    {
        // check all the window's events that were triggered since the last iteration of the loop
        sf::Event event;
        while ( renderWindow->pollEvent( event ) )
        {
            // "close requested" event: we close the window
            if ( event.type == sf::Event::Closed )
                renderWindow->close();

            renderWindow->clear( sf::Color( 0, 0, 255, 255 ) );
            renderWindow->draw( bg );
            renderWindow->draw( bg3 );
            renderWindow->draw( bg4 );

            DrawShadowText( &text1 );
            DrawShadowText( &text2 );
            DrawShadowText( &text3 );
            DrawShadowText( &text4 );
            //renderWindow->draw( text2 );
            //renderWindow->draw( text3 );
            renderWindow->display();
        }
    }

    return 0;
}

void DrawShadowText( const sf::Text* pNText )
{
    //[CREATE OULINE COLOUR: BLACK + ORIGINAL TEXT ALPHA]
    static sf::Color outlineColour;
    outlineColour = sf::Color( sf::Color::Black.r, sf::Color::Black.g, sf::Color::Black.b, pNText->getColor().a );
    sf::Text m_tempTextOutline;

    //[DRAW OUTLINES(BLACK)]
    {
        m_tempTextOutline = sf::Text( *pNText );
        m_tempTextOutline.setColor( outlineColour );
        m_tempTextOutline.setPosition( sf::Vector2f( m_tempTextOutline.getPosition().x + 2, m_tempTextOutline.getPosition().y ) );
        renderWindow->draw( m_tempTextOutline );

        m_tempTextOutline = sf::Text( *pNText );
        m_tempTextOutline.setColor( outlineColour );
        m_tempTextOutline.setPosition( sf::Vector2f( m_tempTextOutline.getPosition().x - 2, m_tempTextOutline.getPosition().y ) );
        renderWindow->draw( m_tempTextOutline );

        m_tempTextOutline = sf::Text( *pNText );
        m_tempTextOutline.setColor( outlineColour );
        m_tempTextOutline.setPosition( sf::Vector2f( m_tempTextOutline.getPosition().x, m_tempTextOutline.getPosition().y + 2 ) );
        renderWindow->draw( m_tempTextOutline );

        m_tempTextOutline = sf::Text( *pNText );
        m_tempTextOutline.setColor( outlineColour );
        m_tempTextOutline.setPosition( sf::Vector2f( m_tempTextOutline.getPosition().x, m_tempTextOutline.getPosition().y - 2 ) );
        renderWindow->draw( m_tempTextOutline );

        m_tempTextOutline = sf::Text();
    }

    //[DRAW ORIGINAL TEXT]
    renderWindow->draw( *pNText );

}

DrawShadowText() is just a function that draws a basic outline on the text just to see the blur clearer. You can comment out it's contents if you'd rather check without the outline.

The peculiar thing I've noticed while preparing this sample, is that text3 and text4, despite having completely equal strings and font settings, one appears blurry while the other doesn't.

The only difference between the two is that text3 has it's position changed to centre itself within the image sprite, while text4 has it's position set without any calculation.

Screenshot:
bug_ss

As you can see, text3 (the 3rd line) is blurry while text4 (4th line) is not, despite same string and font.

@kimci86
Copy link
Contributor

kimci86 commented Feb 4, 2014

Hi,
The problem is that text3 might have non-integer coordinates. (i.e. the fractional part is not zero)
Having non-integer coordinates implies some interpolation on render, causing this blur.
Rounding text3 coordinates should solve your issue.

@hsdk123
Copy link
Author

hsdk123 commented Feb 4, 2014

@kimci86 Nice, that solves it! Thanks! So I guess this wasn't a font problem.

It'd be nice though if the thing about interpoloation could be stated in the comments of sf::Transformable::setPosition(float x, float y) . The float arguments just naturally made me give floats without having a clue that interpolation could be involved.

@LaurentGomila
Copy link
Member

That's right, it should be documented. By the way it's a more complex issue, there are many other things that could produce this artifact: the view, the size of the window, etc. I've tried to solve it by many ways, but it seems that it's unavoidable. Rounding coordinates automatically would produce other (worse) problems.

@Bromeon
Copy link
Member

Bromeon commented Feb 5, 2014

I can add a note to sf::Drawable and refer to it in sf::Text and sf::Sprite, but should I also mention it in every setter method of sf::Transformable and sf::View? The issue is not only affected by position, but also origin, scale, rotation, view center, view size, view rotation...

@LaurentGomila
Copy link
Member

Yes, I think there are too many functions involved to put a note there. It should be done either in the tutorial, or in the general description of the sf::Transformable and sf::View classes.

@Foaly
Copy link
Contributor

Foaly commented Feb 5, 2014

I think it would also be helpful to mention it in the tutorial.
Sorry, but I am interested, Laurent could you explain why rounding the coordinates automatically would be even worse?

@Bromeon
Copy link
Member

Bromeon commented Feb 5, 2014

There are a lot of use cases where this scenario (interpolating pixels) is a feature, namely when you need smooth transitions. Consider an object that is being scaled or rotated: Without interpolation, the transition would look very discrete and blocky.

Let alone the fact that a simple rounding of the position will only fix the most simple cases: As stated above, all other transforms and the whole view has to be taken into account. There have been several forum threads on the topic:

@Bromeon
Copy link
Member

Bromeon commented Feb 6, 2014

I clarified this issue in the documentation, see commit e074b67.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants