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

Author Topic: texture.update not working correctly  (Read 2068 times)

0 Members and 1 Guest are viewing this topic.

kepler0

  • Newbie
  • *
  • Posts: 23
    • View Profile
texture.update not working correctly
« on: December 09, 2017, 06:56:35 am »
I'm trying to make a UI blur using a fragment shader. The current route I'm taking is a sf::Sprite with a constantly updating sf::Texture, then the sf::Sprite is drawn with the shader, but instead the screen is just stuck on a single frame when using the shader.

The constructor:
BackgroundBlur::BackgroundBlur(sf::Vector2f _Position, sf::Vector2f _Size, float _Strength)
        : UIElement(_Position, true)
{
        sf::Texture _Texture;

        Textures.push_back(_Texture);

        sf::Sprite _Sprite;
        _Sprite.setTexture(Textures[0]);
        _Sprite.setTextureRect(sf::IntRect(_Position.x, _Position.y, _Size.x, _Size.y));

        Sprites.push_back(_Sprite);

        Blur.loadFromFile("Resource/Data/Shaders/Blur.frag", sf::Shader::Fragment);

        Blur.setUniform("blur_radius", sf::Glsl::Vec2(Strength, Strength));
        Blur.setUniform("texture", Textures[0]);
}

The sf::Texture is created here:
void BackgroundBlur::BeginPlay()
{
        Textures[0].create
        (
                CurrentApp->GetWindow().getSize().x,
                CurrentApp->GetWindow().getSize().y
        );
}

And the problem resides here, not updating, it works, but no blur:
void BackgroundBlur::Tick(float _DeltaTime)
{
        Textures[0].update(CurrentApp->GetWindow());
}

This is the draw function, if I remove the sf::Shader from the draw arguments, it works again, but there isn't blur:
void BackgroundBlur::Draw(sf::RenderTarget & _Target, sf::RenderStates _States) const
{
        _Target.draw(Sprites[0], &Blur);
}

I've tried adding
Blur.setUniform("texture", Textures[0]);
to the Tick function, however it seems to do nothing.

Also, the fragment shader I am using is
uniform sampler2D texture;
uniform vec2 blur_radius;

void main() {
    vec2 textureCoordinates = gl_TexCoord[0].xy;
    vec4 color = vec4(0.0);
    color += texture2D(texture, textureCoordinates - 10.0 * blur_radius) * 0.0012;
    color += texture2D(texture, textureCoordinates - 9.0 * blur_radius) * 0.0015;
    color += texture2D(texture, textureCoordinates - 8.0 * blur_radius) * 0.0038;
    color += texture2D(texture, textureCoordinates - 7.0 * blur_radius) * 0.0087;
    color += texture2D(texture, textureCoordinates - 6.0 * blur_radius) * 0.0180;
    color += texture2D(texture, textureCoordinates - 5.0 * blur_radius) * 0.0332;
    color += texture2D(texture, textureCoordinates - 4.0 * blur_radius) * 0.0547;
    color += texture2D(texture, textureCoordinates - 3.0 * blur_radius) * 0.0807;
    color += texture2D(texture, textureCoordinates - 2.0 * blur_radius) * 0.1065;
    color += texture2D(texture, textureCoordinates - blur_radius) * 0.1258;
    color += texture2D(texture, textureCoordinates) * 0.1330;
    color += texture2D(texture, textureCoordinates + blur_radius) * 0.1258;
    color += texture2D(texture, textureCoordinates + 2.0 * blur_radius) * 0.1065;
    color += texture2D(texture, textureCoordinates + 3.0 * blur_radius) * 0.0807;
    color += texture2D(texture, textureCoordinates + 4.0 * blur_radius) * 0.0547;
    color += texture2D(texture, textureCoordinates + 5.0 * blur_radius) * 0.0332;
    color += texture2D(texture, textureCoordinates + 6.0 * blur_radius) * 0.0180;
    color += texture2D(texture, textureCoordinates - 7.0 * blur_radius) * 0.0087;
    color += texture2D(texture, textureCoordinates - 8.0 * blur_radius) * 0.0038;
    color += texture2D(texture, textureCoordinates - 9.0 * blur_radius) * 0.0015;
    color += texture2D(texture, textureCoordinates - 10.0 * blur_radius) * 0.0012;
    gl_FragColor = color;
}
, taken from https://en.sfml-dev.org/forums/index.php?topic=20155.0

EDIT: I'm so stupid, instead of
Blur.setUniform("texture", Textures[0]);
it should be
Blur.setUniform("texture", sf::Shader::CurrentTexture);
« Last Edit: December 09, 2017, 07:52:04 am by kepler0 »
Zzz

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: texture.update not working correctly
« Reply #1 on: December 09, 2017, 09:22:43 am »
So is it solved?
Laurent Gomila - SFML developer

kepler0

  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: texture.update not working correctly
« Reply #2 on: December 09, 2017, 09:27:48 am »
:/ Not entirely, since the texture is updating every tick, it'll be copying the blurred frame and blurring it, so the blur will keep layering and the window will always show the start frame. I could fire update once and destroy it whenever I don't need the blur, however I want moving things under the blur to still be moving on the window, even if blurred. Any ideas?
Zzz

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: texture.update not working correctly
« Reply #3 on: December 09, 2017, 11:12:47 am »
Quote
since the texture is updating every tick, it'll be copying the blurred frame and blurring it
Where do you do that?

If you want to apply a shader as a post-processing step of your entire scene, you have to render it (the scene) to a render-texture and apply the shader to a sprite that shows that render-texture.
Laurent Gomila - SFML developer

kepler0

  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: texture.update not working correctly
« Reply #4 on: December 09, 2017, 11:18:50 am »
Textures[0].update(CurrentApp->GetWindow());
inside BackgroundBlur::Tick is capturing what's on the screen, which would be blurred, so it would be re-applying the blur, (which it indeed does). I don't want to blur my entire scene, some things will be in front of the blur, some things behind, I just want the blur to affect anything behind it. Updating the texture only once does work, but if anything changes behind the blur, it won't be shown.
Zzz

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: texture.update not working correctly
« Reply #5 on: December 09, 2017, 01:11:03 pm »
So yes, do like I said: render what you want to blur into a sf::RenderTexture, and draw that render-texture to the window with the blur shader.

That will also be more efficient since you won't have to copy the window data to a texture at every tick.
Laurent Gomila - SFML developer