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

Author Topic: Motion Blur GLSL  (Read 5341 times)

0 Members and 1 Guest are viewing this topic.

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
Motion Blur GLSL
« on: March 13, 2016, 05:57:37 pm »
Hello,

I'm trying to load a motion blur shader in GLSL using sf::Shader, however I'm having some trouble applying it to a sprite, as it seems to be completely hide it (i.e. the sprite isn't even drawn, maybe it's loosing its alpha value?) instead of blurring on movement. I've implemented a minimal snippet that reproduces this problem, but I'm inclined to say the problem relies with the GLSL shaders. I've also attached the shaders and resources to this post.

#include <cmath>
#include <iostream>
#include <SFML/Graphics.hpp>

const double PI = std::atan(1.0) * 4;

int main()
{
        sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Shader",
                sf::Style::Titlebar | sf::Style::Close);

        window.setFramerateLimit(60.f);

        sf::Texture m_texture;
        if (!m_texture.loadFromFile("eff08b.png"))
                return EXIT_FAILURE;

        sf::Sprite m_sprite;
        m_sprite.setTexture(m_texture);
        m_sprite.setOrigin(m_sprite.getGlobalBounds().width / 2.f, m_sprite.getGlobalBounds().height / 2.f);

        sf::Shader m_shader;
        if (!m_shader.loadFromFile("motionblur.vert", "motionblur.frag"))
                return EXIT_FAILURE;

        m_shader.setParameter("scene", sf::Shader::CurrentTexture);

        sf::Clock time;
        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed)
                                window.close();
                }

                float amplitude = 100.f;
                m_sprite.setPosition(amplitude * std::sin(PI * 0.5 * time.getElapsedTime().asSeconds()) + 400.f, 300.f);
                m_sprite.rotate(5.f);

                window.clear(sf::Color(255, 255, 255));
                window.draw(m_sprite, &m_shader);
                window.display();
        }

        return EXIT_SUCCESS;
}

Sadly I'm not too experienced in GLSL, so ended up using this implementation (slide 29): http://www.stevenlu.net/files/motion_blur_2d/Fragment_shader_dynamic_blur.pdf .

Am I missing something really simple?

Best regards
« Last Edit: March 13, 2016, 06:02:44 pm by Contadotempo »

Hapax

  • Hero Member
  • *****
  • Posts: 3386
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Motion Blur GLSL
« Reply #1 on: March 14, 2016, 12:06:02 am »
The vertex shader doesn't seem to be setting gl_TexCoord[0] or gl_FrontColor
http://www.sfml-dev.org/tutorials/2.3/graphics-shader.php#minimal-shaders

Nor, are you setting any of the uniforms.
What are the values of:
uniform mat4 projection_mat;
uniform mat4 modelview_mat;
uniform vec2 viewport;

Your setting of gl_Position relies on projection_mat.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Contadotempo

  • Full Member
  • ***
  • Posts: 167
  • Firelink Shrine
    • View Profile
Re: Motion Blur GLSL
« Reply #2 on: March 23, 2016, 01:32:37 am »
Thank you, I believe my lack of knowledge about GLSL got me stumped here.

I tried replacing the
mat4 proj_modelview_mat = projection_mat * modelview_mat;
with
mat4 proj_modelview_mat = gl_ModelViewProjectionMatrix;

And added accordingly:
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;

But didn't have much success.

What I was trying to accomplish was a trailing effect like the image bellow:


However I didn't know where to start. I thought learning per object motion blur with GLSL would be a good start, but not knowing the language is a barrier. Could anyone guide me on how to achieve this?

Also, some examples suggest acquiring the previous framebuffer or the previous view-projection matrix. How could I do this with or without SFML? I hope this isn't a stupid question...


grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
Re: Motion Blur GLSL
« Reply #3 on: March 23, 2016, 07:54:19 am »
You, possibly, can achieve that using another approach, not dealing with shaders.
Store a stack of a few (1-3, for example) previous rendered scenes and render all of them with an appropriate alpha.
If all you have is several shapes/sprites which move, then you might just store a stack of their previous positions and render them several times, looping through them. (in other words, no need to store *all* data related to the scene in the stack, just a few positions vectors).

Of course, it might be overkill, just a guess.
« Last Edit: March 23, 2016, 07:59:06 am by grok »

gamepopper

  • Newbie
  • *
  • Posts: 35
    • View Profile
    • Email
Re: Motion Blur GLSL
« Reply #4 on: March 30, 2016, 05:43:17 pm »

What I was trying to accomplish was a trailing effect like the image bellow:


However I didn't know where to start. I thought learning per object motion blur with GLSL would be a good start, but not knowing the language is a barrier. Could anyone guide me on how to achieve this?

Also, some examples suggest acquiring the previous framebuffer or the previous view-projection matrix. How could I do this with or without SFML? I hope this isn't a stupid question...

There's two ways you could do this without the use of a shader, and it depends on whether you only want one or many objects to have a trail effect at the same time.

You can either use grok's method of keeping a list of previous render data, and have them render behind the main graphic while gradually fading out over time, starting from full alpha at the start and going to zero alpha, when it becomes ready to use again. This is a straightforward method that can be easy to adjust, although it can be overkill if you want multiple objects to trail since you'll be increasing the draw call amount for each trailing object.

The alternative method (and one that I'm using for my game project) is to have a trail area instead of trail object. How it works (or at least how I implement it) is you render the objects you want to trail onto a RenderTexture, and then you render that texture onto another RenderTexture, but with a bit of transparency and swap the textures. This one allows you to render multiple trailing objects with fewer draw calls, so it's better on performance. Plus it's also an area, so you can have parts where there are no trails. However depending on the amount you set that transparency, you can get some visual artefacts from trails that haven't fully disappeared, so it's a bit more of a case of experimentation.