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

Author Topic: how to properly to use this shader?  (Read 9318 times)

0 Members and 1 Guest are viewing this topic.

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
how to properly to use this shader?
« on: October 03, 2013, 06:26:31 pm »
hello everybody. i'm trying to create an outline effect for texts in SFML. since it's not natively possible, i'm trying to use a shader for that, which is found here.

so, i pasted it in a file called outline.shader, and load it in the code like this:
if(sf::Shader::isAvailable()){
    std::cout << "Shaders are avaliable\n";
    text_outline.loadFromFile("images/fonts/outline.shader", sf::Shader::Fragment);
    text_outline.setParameter("outlineColor", sf::Color::White);
    text_outline.setParameter("texSize", sf::Vector2f(2.0, 2.0));
}
[...]
game_window.draw(title_text, &text_outline);
 

and theeen, i get this completely weird result:



i don't have any experience with shaders, so i barely understand what's happening for this strange result shows up.
so, could anyone help me solve this?

thanks in advance!
Visit my game site (and hopefully help funding it? )
Website | IndieDB

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: how to properly to use this shader?
« Reply #1 on: October 03, 2013, 07:26:12 pm »
I guess that the texSize variable is supposed to be the font's texture size, not 2x2.
Laurent Gomila - SFML developer

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: how to properly to use this shader?
« Reply #2 on: October 03, 2013, 10:11:27 pm »
ok, thanks for the answer! i then changed the texSize parameter to:

if(sf::Shader::isAvailable()){
        std::cout << "Shader avaliable\n";
        text_outline.loadFromFile("images/fonts/outline.shader", sf::Shader::Fragment);
        text_outline.setParameter("outlineColor", sf::Color::Black);
        const float t_x = title_font.getTexture(res.y/8).getSize().x; //res.y/8 is the font size
        const float t_y = title_font.getTexture(res.y/8).getSize().y;
        text_outline.setParameter("texSize", sf::Vector2f(t_x, t_y));
    }

and it works!! :D
but it's really ugly:


so, if anyone has a tip on how to make a better outline, please let me know! :)
Visit my game site (and hopefully help funding it? )
Website | IndieDB

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: how to properly to use this shader?
« Reply #3 on: October 03, 2013, 10:20:36 pm »
The trace shader in the SFML examples might be helpful.

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: how to properly to use this shader?
« Reply #4 on: October 03, 2013, 10:46:08 pm »
"trace shader"? i haven't found it. are you talking about the tutorials category?
Visit my game site (and hopefully help funding it? )
Website | IndieDB

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: how to properly to use this shader?
« Reply #5 on: October 03, 2013, 11:03:33 pm »
Download the source code.  For some reason that's the only version that has the example programs.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: how to properly to use this shader?
« Reply #6 on: October 03, 2013, 11:32:13 pm »
Source code of examples are part of the SDK. But I have no idea what "trace shader" is referring to, there's nothing that does text outlining in the official examples.
Laurent Gomila - SFML developer

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: how to properly to use this shader?
« Reply #7 on: October 03, 2013, 11:34:43 pm »
You're right, I got the name wrong.  I was thinking of edge.frag.  Sorry.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: how to properly to use this shader?
« Reply #8 on: October 03, 2013, 11:36:49 pm »
This is not the same effect, I don't think it would fit this use.
Laurent Gomila - SFML developer

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: how to properly to use this shader?
« Reply #9 on: October 04, 2013, 12:12:55 am »
indeed, the results are just a bunch of squares in front of the text.

geez, i'll have to learn a whole new language just to do that..  ???
Visit my game site (and hopefully help funding it? )
Website | IndieDB

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: how to properly to use this shader?
« Reply #10 on: October 04, 2013, 01:28:26 am »
ok, i did a little function to help that, if anyone else have interest in this:
void outlineDraw(sf::RenderWindow &window, sf::Text &text, sf::Color oc, float ot){ //'oc' stands for 'outline color, and 'ot' for 'outline_thickness'
    sf::Text outline = text;
    outline.setColor(oc);
    outline.setPosition(text.getPosition() + sf::Vector2f(-ot, -ot));
    window.draw(outline);
    outline.setPosition(text.getPosition() + sf::Vector2f(0, -ot));
    window.draw(outline);
    outline.setPosition(text.getPosition() + sf::Vector2f(ot, -ot));
    window.draw(outline);
    outline.setPosition(text.getPosition() + sf::Vector2f(-ot, 0));
    window.draw(outline);
    outline.setPosition(text.getPosition() + sf::Vector2f(ot, 0));
    window.draw(outline);
    outline.setPosition(text.getPosition() + sf::Vector2f(-ot, ot));
    window.draw(outline);
    outline.setPosition(text.getPosition() + sf::Vector2f(0, ot));
    window.draw(outline);
    outline.setPosition(text.getPosition() + sf::Vector2f(ot, ot));
    window.draw(outline);

    window.draw(text);
}

it just draws eight copies of the original text around it, with another color :P
the effect is not perfect, but is good enough for now:



i think a smoother effect can be achieved if the number of text copies is increased. maybe il'l do that later (along with polishing the whole code in some for loops  ::) )

but i am STILL interested in the shaders, if anyone know how to use them in this case!
Visit my game site (and hopefully help funding it? )
Website | IndieDB

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: how to properly to use this shader?
« Reply #11 on: October 04, 2013, 01:37:15 am »
If you want a more smoothed outline you can extend that method to move the text in a circle and draw it for the outline. Take a look at this DirectX code (easily converted to SFML) taken from here.

for (int i = 0; i <= intBorderWidth; i += 1)
{
    for (int theta = 0; theta <= 360; theta += angleStep)
    {
        double cos, sin;
        cos = i * Math.Cos((double)((theta) * (Math.PI / 180)));
        sin = i * Math.Sin((double)((theta) * (Math.PI / 180)));

        D3DFontBorder.DrawText(null, text, new Rectangle(rect.Left - (int)sin, rect.Top - (int)cos, rect.Width, rect.Height), dtxtFormat, strokeColour);
    }
}
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: how to properly to use this shader?
« Reply #12 on: October 04, 2013, 02:27:10 am »
here sir, have my like:

it works great now!! have a look:



now, WHY don't we have a "Code Snippets" session?? oh well, i'll share the code here:
#include <math.h>
void outlineDraw(sf::RenderWindow &window, sf::Text &text, sf::Color oc, float ot, int smooth){ //'oc' stands for 'outline color, and 'ot' for 'outline_thickness'
    const float pi = 3.1415;
    sf::Text outline = text;
    outline.setColor(oc);
    for (int theta = 0; theta <= 360; theta += smooth){
        float pos_x = std::cos(theta*pi/180.0) * ot;
        float pos_y = std::sin(theta*pi/180.0) * ot;

        outline.setPosition(text.getPosition() + sf::Vector2f(pos_x, pos_y));
        window.draw(outline);
        std::cout << "pos_x:" << pos_x << "; pos_y:" << pos_y << std::endl;
    }
        window.draw(text);
}

so much cleaner & better looking :D
to use it:
outlineDraw(sfml_renderWindow, text_to_outline, outline_color, outline_thickness, outline_smooth);
outline smooth is inverse: the lower, the smoother.
« Last Edit: October 04, 2013, 02:29:40 am by Stauricus »
Visit my game site (and hopefully help funding it? )
Website | IndieDB

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: how to properly to use this shader?
« Reply #13 on: October 04, 2013, 02:54:24 am »
You can post it to the wiki.

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: how to properly to use this shader?
« Reply #14 on: October 10, 2013, 03:04:05 pm »
sure, i'll do it as soon as i have it polished.

right now i'm trying to optimize it, but had some issues. what i'm trying to do is create a new texture based on the outlined text, so i don't have to make so many copies of the text to re-draw the outline every frame. here is the code:

void createOutline(sf::Texture &texture, sf::Text &text, sf::Color outline_color, float outline_thickness, int smooth){
    sf::RenderTexture render_texture;
    render_texture.create(text.getGlobalBounds().width + outline_thickness*2, text.getGlobalBounds().height + outline_thickness*2);
    render_texture.clear(sf::Color::Transparent);
    text.setPosition(outline_thickness, outline_thickness);
    std::cout << "\ntext size:" << text.getGlobalBounds().width << "," << text.getGlobalBounds().height;
    std::cout << "\nrender_texture size:" << render_texture.getSize().x << "," << render_texture.getSize().y;
    sf::Text outline = text;
    outline.setColor(outline_color);
    const float pi = 3.1415;
    for (int theta = 0; theta <= 360; theta += smooth){
        float pos_x = std::cos(theta*pi/180.0) * outline_thickness;
        float pos_y = std::sin(theta*pi/180.0) * outline_thickness;
        outline.setPosition(text.getPosition() + sf::Vector2f(pos_x, pos_y));
        render_texture.draw(outline);
    }
    render_texture.draw(text);
    render_texture.display();
    texture.create(render_texture.getTexture().getSize().x, render_texture.getTexture().getSize().y);
    texture = render_texture.getTexture();

instead of getting a sf::Window as first argument, i get a sf::Texture. then i create a RenderTexture, draw the text to it, and copy it's texture at the end. drawing a single Texture is much lighter than drawing 72 black texts to create the outline effect, i believe.
but i'm getting a weird result. i don't know if its something related to the font or my code, but even if i change the font i still get this:


the texture is not being cut in the right place. hrere is the output (from the two std::cout lines):
Quote
text size:344,65
render_texture size:364,85

any idea why? maybe i did something wrong in the calculations :P
thanks!
« Last Edit: October 10, 2013, 03:39:34 pm by Stauricus »
Visit my game site (and hopefully help funding it? )
Website | IndieDB