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

Author Topic: Add Shadow to SFML-Objects (including Text) [was Shaded Text]  (Read 10755 times)

0 Members and 3 Guests are viewing this topic.

degski

  • Newbie
  • *
  • Posts: 23
    • View Profile
    • Email
Add Shadow to SFML-Objects (including Text) [was Shaded Text]
« on: February 27, 2016, 11:13:34 am »
I'm trying to create a shade to a text. A sharp shade is obviously no problem, just draw the text twice slightly displaced in the opposite direction of the "light" direction. I would like to blur this shadow around the edges. The answer seems to be "use shaders".

I've looked at the (SFML) shader examples and isolated the blur effect out of the wave+blur effect. This does not give a good result. That's why I'm working on a shader solution...

Other simpeler approaches (to the problem of adding feathered shade to text) are equally appreciated.

[EDIT] I've come to something I'm happy with (for now). It's still slow, but for my purposes I can work around it. I'll post the code in the top post (this one), and attach the result of running the code below it. The attached png is for some reason displayed larger (about 125%) than it is in reality (when clicked) and will therefore look better in an application.

#include <ciso646>
#include <vector>
#include <string>

#include <SFML/Graphics.hpp>


const std::string gaussian_blur_shader { "\
\
        uniform sampler2D texture;\
\
        uniform vec2 pixel_size;\
        uniform int blur_radius;\
        uniform float [ 256 ] weights;\
        uniform bool horizontal;\
\
\
        void main ( ) {\
\
        const vec2 texture_coordinates = gl_TexCoord [ 0 ].xy;\
\
        gl_FragColor = texture2D ( texture, texture_coordinates ) * weights [ 0 ];\
\
        if ( horizontal ) {\
\
                for ( int i = 1; i < blur_radius; ++i ) {\
\
                        const vec2 offset = vec2 ( float ( i ) * pixel_size.x, 0.0f );\
\
                        gl_FragColor += texture2D ( texture, texture_coordinates + offset ) * weights [ i ];\
                        gl_FragColor += texture2D ( texture, texture_coordinates - offset ) * weights [ i ];\
                }\
        }\
\
        else {\
\
                for ( int i = 1; i < blur_radius; ++i ) {\
\
                        const vec2 offset = vec2 ( 0.0f, float ( i ) * pixel_size.y );\
\
                        gl_FragColor += texture2D ( texture, texture_coordinates + offset ) * weights [ i ];\
                        gl_FragColor += texture2D ( texture, texture_coordinates - offset ) * weights [ i ];\
                }\
        }\
}\
\
"
};


template<typename T>
class Shadowed : public sf::Drawable {

        sf::Sprite m_object_sprite;

        const std::vector<float> m_gaussian_weights;
        sf::Shader m_shader;

        sf::RenderTexture m_horz_render_texture;
        sf::Sprite m_horz_sprite;

        sf::RenderTexture m_render_texture;
        sf::Sprite m_sprite;

        std::vector<float> gaussianWeights ( const std::size_t size_ ) const {

                // http://www.cocos2d-x.org/wiki/User_Tutorial-RenderTexture_Plus_Blur

                std::vector<float> gaussian_weights ( size_ );

                double nill = 1.0;

                for ( std::size_t i = 1; i < size_; ++i ) {

                        const double x = ( double ) i / ( double ) ( size_ - 1 ), gwi = 1.196826841204297942 / ( double ) size_ * std::exp ( -x * x * 4.5 );

                        gaussian_weights [ i ] = gwi;
                        nill -= 2.0 * gwi;
                }

                gaussian_weights [ 0 ] = nill;

                return gaussian_weights;
        }

public:

        Shadowed (

                T &object_,

                const std::size_t radius_,
                const sf::Vector2f &displacement_,
                const sf::Color &shadow_color = sf::Color::Black,
                const sf::Color &background_color = sf::Color::Transparent // To be set for better gradient...

                ) :

                m_gaussian_weights ( gaussianWeights ( radius_ ) ) {

                // Finish setting text object...

                const sf::Color original_fill_color ( object_.getFillColor ( ) );
                const sf::Color original_outline_color ( object_.getOutlineColor ( ) );

                const sf::Vector2f original_position ( object_.getPosition ( ) );
                const sf::Vector2f original_origin ( object_.getOrigin ( ) );

                object_.setFillColor ( shadow_color );
                object_.setOutlineColor ( shadow_color );
                object_.setOrigin ( object_.getLocalBounds ( ).left - std::max ( ( float ) radius_, displacement_.x ), object_.getLocalBounds ( ).top - std::max ( ( float ) radius_, displacement_.y ) );
                object_.setPosition ( sf::Vector2f ( 0.0f, 0.0f ) );

                // Init render texture...
                m_render_texture.create ( object_.getLocalBounds ( ).width + ( radius_ > std::abs ( displacement_.x ) ? 2 * radius_ : radius_ + std::abs ( displacement_.x ) ), object_.getLocalBounds ( ).height + ( radius_ > std::abs ( displacement_.y ) ? 2 * radius_ : radius_ + std::abs ( displacement_.y ) ) );
                m_render_texture.clear ( background_color );
                m_render_texture.setSmooth ( true );
                m_render_texture.draw ( object_ );
                m_render_texture.display ( );

                // 1. Create object sprite...

                m_object_sprite.setTexture ( m_render_texture.getTexture ( ) );

                // Load shader...

                m_shader.loadFromMemory ( gaussian_blur_shader, sf::Shader::Fragment );

                // Set shader parameters...

                m_shader.setUniform ( "pixel_size", sf::Vector2f ( 1.0f / m_object_sprite.getLocalBounds ( ).width, 1.0f / m_object_sprite.getLocalBounds ( ).height ) );
                m_shader.setUniform ( "blur_radius", ( int ) m_gaussian_weights.size ( ) );
                m_shader.setUniformArray ( "weights", m_gaussian_weights.data ( ), m_gaussian_weights.size ( ) );

                // 2. Draw it to a RenderTexture with horizontal blur shader...

                m_shader.setUniform ( "horizontal", true );

                m_horz_render_texture.create ( m_object_sprite.getLocalBounds ( ).width, m_object_sprite.getLocalBounds ( ).height );
                m_horz_render_texture.clear ( background_color );
                m_horz_render_texture.setSmooth ( true );
                m_horz_render_texture.draw ( m_object_sprite, &m_shader );

                m_horz_render_texture.display ( );

                // 3. Create a sprite from resulting texture...

                m_horz_sprite.setTexture ( m_horz_render_texture.getTexture ( ) );

                // 4. Draw this sprite to a Render texture with vertical shader...

                m_shader.setUniform ( "horizontal", false );

                m_render_texture.clear ( background_color );

                // Draw the objects's shadow...

                m_render_texture.draw ( m_horz_sprite, &m_shader );

                // Setup the actual object...

                object_.setFillColor ( original_fill_color );
                object_.setOutlineColor ( original_outline_color );
                object_.setPosition ( -displacement_.x, -displacement_.y );

                // Draw object...

                m_render_texture.draw ( object_ );
                m_render_texture.display ( );

                // Create sprite with the object at it's original position, dis-regarding the shadow... (needs more work)

                m_sprite.setTexture ( m_render_texture.getTexture ( ) );
                m_sprite.setPosition ( original_position + displacement_ - sf::Vector2f ( ( float ) radius_, ( float ) radius_ ) );

                object_.setPosition ( original_position );
                object_.setOrigin ( original_origin );
        }

        virtual void draw ( sf::RenderTarget &target_, sf::RenderStates states_ ) const {

                target_.draw ( m_sprite, states_ );
        }
};


int main ( ) {

        sf::ContextSettings settings;
        settings.antialiasingLevel = 8;

        sf::RenderWindow window ( sf::VideoMode ( 600, 800 ), "SFML add Shadow to Objects...", sf::Style::Titlebar | sf::Style::Close, settings );

        window.setVerticalSyncEnabled ( true );
        window.setFramerateLimit ( 60 );

        sf::Font font;

        if ( not ( font.loadFromFile ( "c:/windows/fonts/impact.ttf" ) ) ) {

                return EXIT_FAILURE;
        }

        sf::Text text ( L"SFML", font, 210u );

        text.setFillColor ( sf::Color::Green );
        text.setOutlineColor ( sf::Color::Black );
        text.setOutlineThickness ( 4.0f );
        text.setPosition ( sf::Vector2f ( 100.0f, 100.0f ) );

        Shadowed<sf::Text> shadowed_text (

                text,
                16u,
                sf::Vector2f ( 8.0f, 8.0f ),
                sf::Color::Black
        );

        sf::RectangleShape rect ( sf::Vector2f ( 300.0f, 300.0f ) );

        rect.setFillColor ( sf::Color::Yellow );
        rect.setOutlineColor ( sf::Color::Black );
        rect.setOutlineThickness ( 1.0f );
        rect.setPosition ( sf::Vector2f ( 150.0f, 400.0f ) );

        Shadowed<sf::RectangleShape> shadowed_rect (

                rect,
                16u,
                sf::Vector2f ( -16.0f, 24.0f ),
                sf::Color::Black
        );

        while ( window.isOpen ( ) ) {

                sf::Event event;

                while ( window.pollEvent ( event ) ) {

                        if ( event.type == sf::Event::Closed ) {

                                window.close ( );
                        }
                }

                window.clear ( sf::Color::White );

                window.draw ( shadowed_text );
                window.draw ( shadowed_rect );

                window.display ( );
        }

        return 0;
}
 

The code is self contained, on non-Windhoze platforms you'll have to stick in another font.

PS: What I thought would also be cool is to not just put in the displacement of the shadow, but a direction, elevation, and distance to the "base surface", so as to be able to calculate the displacement required from those three parameters. (need to brush-up my trig, or find something, help accepted :D) The objective would be to make the shadow coincide with the real shadows at the players location at the time of play.
« Last Edit: March 03, 2016, 02:41:59 pm by degski »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Blur Shader
« Reply #1 on: February 27, 2016, 11:34:32 am »
Quote
Other simpeler approaches (to the problem of adding feathered shade to text) are equally appreciated.
The shader is probably the easiest (once you've figured out the right code) and most efficient solution, but there's something else you can try: draw a smaller-sized version of the text to a render-texture, then draw it upscaled (with texture smoothing enabled) to have a blurred result. Or a more direct approach: use a smaller character size and the text scale to achieve the same thing. Might be good enough. Or ugly ;D
« Last Edit: February 27, 2016, 11:36:20 am by Laurent »
Laurent Gomila - SFML developer

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Blur Shader
« Reply #2 on: February 27, 2016, 10:14:02 pm »
I've looked at the (SFML) shader examples and isolated the blur effect out of the wave+blur effect. This does not give a good result, as roughly speaking, it (the shader) greys the text (if it was black) and then sort of draws a lighter grey squarish box around it.
It looks like you're using a blur radius value that is too high. Try a much smaller one e.g. 0.02 (it's not perfect)
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

degski

  • Newbie
  • *
  • Posts: 23
    • View Profile
    • Email
Re: Blur Shader
« Reply #3 on: February 28, 2016, 08:24:19 am »
It looks like you're using a blur radius value that is too high. Try a much smaller one e.g. 0.02 (it's not perfect)

Thanks for that! Indeed the radius needs to be much smaller. I've added a lighter outline as well, which gives the reult below... (it's better, but not perfet, as you said).

degski

  • Newbie
  • *
  • Posts: 23
    • View Profile
    • Email
Re: Blur Shader
« Reply #4 on: February 29, 2016, 01:09:06 pm »
Have been looking at this a bit lot more, and I've got something working. I would like to ask for your comments, suggestions and/or improvements.

The fragment shader is now as follows:

uniform sampler2D texture;

uniform vec2 pixel_size;
uniform int blur_radius;
uniform float[128] weights;
uniform vec2 direction;

void main ( ) {

        const vec2 texture_coordinates = gl_TexCoord [ 0 ].xy;

    gl_FragColor = texture2D ( texture, texture_coordinates ) * weights [ 0 ];

    for ( int i = 1; i < blur_radius; ++i ) {

        const vec2 offset = vec2 ( float ( i ) * pixel_size.x * direction.x, float ( i ) * pixel_size.y * direction.y );

        gl_FragColor += texture2D ( texture, texture_coordinates + offset ) * weights [ i ];
        gl_FragColor += texture2D ( texture, texture_coordinates - offset ) * weights [ i ];
    }
}
 


And the ShadedText class (and a main) is like this:

class ShadedText {

        sf::Text m_text;
        sf::RenderTexture m_text_render_texture;
        sf::Sprite m_text_sprite;

        const std::vector<float> m_gaussian_weights;

        sf::RenderStates m_render_state;
        sf::Shader m_shader;

        sf::RenderTexture m_horz_render_texture;
        sf::RenderTexture m_vert_render_texture;

        sf::Sprite m_horz_sprite;
        sf::Sprite m_final_sprite;

        std::vector<float> gaussianWeights ( const std::size_t size_ ) const {

                // http://www.cocos2d-x.org/wiki/User_Tutorial-RenderTexture_Plus_Blur

                std::vector<float> gaussian_weights ( size_ );

                double nill = 1.0;

                for ( std::size_t i = 1; i < size_; ++i ) {

                        const double x =  ( double ) i / ( double ) ( size_ - 1 ), gwi = 1.196826841204297942 / ( double ) size_ * std::exp ( -x * x * 4.5 );

                        gaussian_weights [ i ] = gwi;
                        nill -= 2.0 * gwi;
                }

                gaussian_weights [ 0 ] = nill;

                return gaussian_weights;
        }

public:

        ShadedText ( const std::wstring &text_, const sf::Font &font_, const std::size_t points_, const std::size_t radius_, const sf::Vector2f &position_ = sf::Vector2f ( 0.0f, 0.0f ) ) :

                m_text ( text_, font_, points_ ),
                m_gaussian_weights ( gaussianWeights ( radius_ ) ) {

                const float dispx = 12.0f, dispy = 13.0f;

                // Finish setting text object...

                m_text.setFillColor ( sf::Color::Black );
                m_text.setOrigin ( m_text.getLocalBounds ( ).left - radius_, m_text.getLocalBounds ( ).top - radius_ ); // Otherwise text is not properly positioned in the rendertexture

                // Init render texture...

                m_text_render_texture.create ( m_text.getLocalBounds ( ).width + 2.0f * radius_ + dispx, m_text.getLocalBounds ( ).height + 2.0f * radius_ + dispx );
                m_text_render_texture.clear ( sf::Color::White );
                m_text_render_texture.setSmooth ( true );

                m_text.setPosition ( dispx, dispy );

                m_text_render_texture.draw ( m_text );
                m_text_render_texture.display ( );

                // 1. Create text sprite...

                m_text_sprite.setTexture ( m_text_render_texture.getTexture ( ) );

                // Load shader...

                if ( not ( m_shader.loadFromFile ( "c:/tmp/resources/blur.frag", sf::Shader::Fragment ) ) ) {

                        exit ( EXIT_FAILURE );
                }

                // Set shader parameters...

                m_shader.setUniform ( "pixel_size", sf::Vector2f ( 2.0f / m_text_sprite.getLocalBounds ( ).width, 2.0f / m_text_sprite.getLocalBounds ( ).height ) );
                m_shader.setUniform ( "blur_radius", ( int ) radius_ );
                m_shader.setUniformArray ( "weights", m_gaussian_weights.data ( ), radius_ );

                m_render_state.shader = &m_shader;

                // 2. Draw it to a RenderTexture with horizontal blur shader...

                m_shader.setUniform ( "direction", sf::Vector2f ( 1.0f, 0.0f ) );

                m_horz_render_texture.create ( m_text_sprite.getLocalBounds ( ).width + 2.0f * radius_, m_text_sprite.getLocalBounds ( ).height + 2.0f * radius_ );
                m_horz_render_texture.clear ( sf::Color::White );
                m_horz_render_texture.setSmooth ( true );
                m_horz_render_texture.draw ( m_text_sprite, m_render_state );
                m_horz_render_texture.display ( );

                // 3. Create a sprite from resulting texture...

                m_horz_sprite.setTexture ( m_horz_render_texture.getTexture ( ) );

                // 4. Draw this sprite to a Render texture with vertical shader...

                m_shader.setUniform ( "direction", sf::Vector2f ( 0.0f, 1.0f ) );

                m_vert_render_texture.create ( m_horz_sprite.getLocalBounds ( ).width, m_horz_sprite.getLocalBounds ( ).height );
                m_vert_render_texture.clear ( sf::Color::White );
                m_vert_render_texture.setSmooth ( true );
                m_vert_render_texture.draw ( m_horz_sprite, m_render_state );

                m_text.setFillColor ( sf::Color::Green );
                m_text.setOutlineColor ( sf::Color::Black );
                m_text.setOutlineThickness ( 1.0f );
                m_text.setPosition ( 0.0f, 0.0f );

                m_vert_render_texture.draw ( m_text );

                m_vert_render_texture.display ( );

                m_final_sprite.setTexture ( m_vert_render_texture.getTexture ( ) );
                m_final_sprite.setPosition ( 50.0f, 50.0f );
        }

        void draw ( sf::RenderWindow &window_ ) {

                window_.draw ( m_final_sprite );
        }
};


int main ( ) {

        sf::ContextSettings settings;
        settings.antialiasingLevel = 8;

        sf::RenderWindow window ( sf::VideoMode ( 500, 300 ), "SFML Shaded Text", sf::Style::Titlebar | sf::Style::Close, settings );

        window.setVerticalSyncEnabled ( true );
        window.setFramerateLimit ( 60 );

        sf::Font font;

        if ( not ( font.loadFromFile ( "c:/windows/fonts/impact.ttf" ) ) ) {

                return EXIT_FAILURE;
        }

        ShadedText text ( L"Text", font, 224u, 8u, sf::Vector2f ( window.getSize ( ).x * 0.5f, window.getSize ( ).y * 0.5f ) );

        while ( window.isOpen ( ) ) {

                sf::Event event;

                while ( window.pollEvent ( event ) ) {

                        if ( event.type == sf::Event::Closed ) {

                                window.close ( );
                        }
                }

                window.clear ( sf::Color::White );

                text.draw ( window );

                window.display ( );
        }

        return 0;
}
 

The image of the resulting text is attached below. The result is reasonably good I would say (but could be improved IMO)...

The constructor runs in about 90ms 80ms on my laptop. It seems long to me... In a real-time situation it might be better, but improvements (or ideas) are welcomed.

[EDIT1] I wonder whether writing the m_text_sprite to an sf::Image, apply the blur on cpu and writing it back to the sf:Image wouln't be much faster (as opposed to creating all those sf::RenderTargets adn other boilerplate). Writing the m_text to sf::Image takes about 1-2ms, so there's time left!

[EDIT2] Eliminated 1 RenderTexture by re-use... The constructor now runs in about 80ms.

[EDIT3] About a quarter of the time is spent in this call:

m_text.setOrigin ( m_text.getLocalBounds ( ).left - radius_, m_text.getLocalBounds ( ).top - radius_ );

That's expensive!

[EDIT4] updated the latest result... looks good now.
« Last Edit: March 01, 2016, 01:36:31 pm by degski »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Shaded Text [was Blur Shader]
« Reply #5 on: February 29, 2016, 08:27:56 pm »
I can't try your code as I don't have access to setUniform() (and therefore passing arrays etc.) yet.
I think that the pixelation is due to the resolution of your sample. If you want to reduce the pixelation, you'll need more weights.
I've just realised that you're now passing the radius as an int and then using that as the control variable for the loop and then using that for indexing the weights array. What happens when you choose a radius greater than the number of weights?
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

degski

  • Newbie
  • *
  • Posts: 23
    • View Profile
    • Email
Re: Shaded Text [was Blur Shader]
« Reply #6 on: March 01, 2016, 07:48:35 am »
I can't try your code as I don't have access to setUniform() (and therefore passing arrays etc.) yet.

It's in the latest developments.

I think that the pixelation is due to the resolution of your sample. If you want to reduce the pixelation, you'll need more weights.

Somehow the forum seems to enlarge the attached image with a factor higher than 100% (i.e. what you see is bigger than what I see on my laptop locally), when you click on it. On my laptop with Full HD screen, the text size is considerably smaller, the pixelation is less. I used M$ Paint and print-screen to capture the image, this might be a contributing factor.

What happens when you choose a radius greater than the number of weights?

The constructor takes care of setting up the correct weights vector for the radius chosen.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Shaded Text [was Blur Shader]
« Reply #7 on: March 02, 2016, 01:18:18 am »
It's in the latest developments.
I am aware of that; that's why I don't currently have access to it  :P

Somehow the forum seems to enlarge the attached image with a factor higher than 100% (i.e. what you see is bigger than what I see on my laptop locally), when you click on it. On my laptop with Full HD screen, the text size is considerably smaller, the pixelation is less. I used M$ Paint and print-screen to capture the image, this might be a contributing factor.
Maybe it's taking in to account your overall desktop display scale size? That said, Paint can never very rarely achieve something good.

What happens when you choose a radius greater than the number of weights?
The constructor takes care of setting up the correct weights vector for the radius chosen.
The number of weights is the number of samples. This is hard-coded (as 128) in the shader.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

degski

  • Newbie
  • *
  • Posts: 23
    • View Profile
    • Email
Re: Shaded Text [was Blur Shader]
« Reply #8 on: March 02, 2016, 08:37:25 am »
The number of weights is the number of samples. This is hard-coded (as 128) in the shader.

Well, yes and no, it is set at 128 (that's a radius in pixels) just to placate the GLSL-compiler, as it apparently does not accept float[], while the code should be usable with different radii. Normal values would be more like 4, 8 or maybe 12... As the c-array decays into a pointer, again apparently, and the blur_radius controls both the size of the weights and the loop in the shader this should not be a problem ASAICS, as the values that are accessed (through the pointer) well and truely exist.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Shaded Text [was Blur Shader]
« Reply #9 on: March 02, 2016, 09:33:40 pm »
To clarify, I meant the number of weights is the maximum number of samples. If you attempt to use a radius of 129, this shader won't be too happy.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

degski

  • Newbie
  • *
  • Posts: 23
    • View Profile
    • Email
Re: Shaded Text [was Blur Shader]
« Reply #10 on: March 03, 2016, 05:35:27 am »
If you attempt to use a radius of 129, this shader won't be too happy.

Correct! One could simply put a bigger number.

This issue was actually already pointed out in the source of the shader http://www.cocos2d-x.org/wiki/User_Tutorial-RenderTexture_Plus_Blur.

There a plenty of those kind of hard-coded numbers in the STL and f.e. Boost as well. I don't see the issue.
« Last Edit: March 03, 2016, 10:44:05 am by degski »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Add Shadow to SFML-Objects (including Text) [was Shaded Text]
« Reply #11 on: March 07, 2016, 01:44:34 pm »
It's fine if you have already planned out what the maximum should be and it's for your own specific use.

Why do you not just use a larger number to begin with?  ;D
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

degski

  • Newbie
  • *
  • Posts: 23
    • View Profile
    • Email
Re: Add Shadow to SFML-Objects (including Text) [was Shaded Text]
« Reply #12 on: March 08, 2016, 07:03:41 am »
It's fine if you have already planned out what the maximum should be and it's for your own specific use.

Why do you not just use a larger number to begin with?  ;D

I've increased it to 256 in the top post. One could just as well put 4k, and be able to blur a full screen (in 4k  HD), but I doubt that is going to be practical as there are already serious running time demands at much smaller values (like 8 or 16), see below.

The pixelation issue, we discussed earlier, was due to not calculating the decimal size of a pixel correctly, and as a consequence only every second pixel got processed. This is also corrected in the top post.

What a would like to ask you with your deep understanding of the matter at hand, whether you see any means of optimising the constructor for speed from where it stands at the moment. At the moment doing this dynamically seems to be out of the question as the constructor takes quite a number of frames (at 1/ 60) to run.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Add Shadow to SFML-Objects (including Text) [was Shaded Text]
« Reply #13 on: March 08, 2016, 09:35:16 am »
Quote
optimising the constructor for speed
First thing: it may not make it faster to execute, but you should use local objects when possible. You're currently storing as class members all the intermediate objects that you only need in the constructor; only the final texture and sprite need to survive the constructor. As a result, a lot of unused resources (memory, OpenGL contexts, ...) are kept alive and released only when the shaded object itself is destroyed.

Regarding speed... If you pre-render all the stuff then you've basically chosen to favor runtime efficiency at the expense of initialization time. Have you tried to just draw the object directly with the blur shader, without all these intermediate drawings to render-textures? And if you really need to pre-render the effect, then you can try to reuse render-textures rather than creating/destroying them for every new shaded object. Creating and releasing a render-texture are expensive operations. You can also load the fragment shader once and use it for all shaded objects, since it will never change.
Laurent Gomila - SFML developer

degski

  • Newbie
  • *
  • Posts: 23
    • View Profile
    • Email
Re: Add Shadow to SFML-Objects (including Text) [was Shaded Text]
« Reply #14 on: March 08, 2016, 12:36:11 pm »
Quote
optimising the constructor for speed
only the final texture and sprite need to survive the constructor.

Thanks for that information, I didn't realise that.

Have you tried to just draw the object directly with the blur shader, without all these intermediate drawings to render-textures?

I have tried that, it creates artifacts, the horizontal pass and the vertical pass will effect each other. I am re-using one RenderTexture once (the latest state of affairs is in the top post, maybe that created some confusion).

With the information about the (required) life-time of the texture/sprite I will see whether I can improve thing. I'll update if relevant.
« Last Edit: March 08, 2016, 01:05:02 pm by Laurent »