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

Author Topic: Trying to implement a shockwave shader using sf::Shader  (Read 3974 times)

0 Members and 1 Guest are viewing this topic.

Sumzary

  • Guest
Trying to implement a shockwave shader using sf::Shader
« on: January 17, 2014, 09:58:50 pm »
This is the shockwave.frag file:
uniform sampler2D in_Texture; // 0
uniform vec2 in_Center; // Mouse position
uniform float in_Time; // effect elapsed time. Multiply this to affect speed.

// Amplitude?, Refraction?, Width? e.g. 10.0, 0.8, 0.1
uniform vec3 in_ShockParams;

uniform int in_WindowWidth;
uniform int in_WindowHeight;

varying vec2 var_TexCoord;

void main()
{
  vec2 uv = var_TexCoord;
  vec2 texCoord = uv;
  float x = in_Center.x / float(in_WindowWidth);
  float y = (float(in_WindowHeight) - in_Center.y) / float(in_WindowHeight);
  float distance = distance(uv, vec2(x, y));

  if ( (distance <= (in_Time + in_ShockParams.z)) &&
       (distance >= (in_Time - in_ShockParams.z)) )
  {
    float diff = (distance - in_Time);
    float powDiff = 1.0 - pow(abs(diff * in_ShockParams.x),
                                in_ShockParams.y);
    float diffTime = diff * powDiff;
    vec2 diffUV = normalize(uv - in_Center);
    texCoord = uv + (diffUV * diffTime);
  }

  gl_FragColor = texture2D(in_Texture, texCoord);
}

This is all the relevant code:
shader.loadFromFile("Vania/Shaders/shockwave.frag", sf::Shader::Fragment);
shader.setParameter("in_Center", 0.5f, 0.5f);
shader.setParameter("in_ShockParams", 10.f, 0.8f, 0.1f);
shader.setParameter("in_Time", 2.f);
shader.setParameter("in_WindowWidth", conf::res.x);
shader.setParameter("in_WindowHeight", conf::res.y);

...

window.draw(renderSprite, &shader);

Everything seems fine so far, but when i start the game, all I see is one solid color (would put screenshot here but it seems pointless), is there something wrong with my SFML code? Something obvious I'm missing here? Been stuck for a while trying to figure this out, some help would be very much appreciated ;]

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10800
    • View Profile
    • development blog
    • Email
AW: Trying to implement a shockwave shader using sf::Shader
« Reply #1 on: January 17, 2014, 10:31:07 pm »
You never clear or display the drawn thing - at least you didn't post it. Please provide a complete and minimal example, so we can directly test it. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Trying to implement a shockwave shader using sf::Shader
« Reply #2 on: January 17, 2014, 10:35:04 pm »
You should start with a minimal shader and build on top of it until things stop working as expected. Writing the final thing directly and then wondering why it doesn't work often leads nowhere ;)

And where do you set the in_Texture parameter? It's not shown in your code.
Laurent Gomila - SFML developer

Sumzary

  • Guest
Re: Trying to implement a shockwave shader using sf::Shader
« Reply #3 on: January 17, 2014, 10:38:43 pm »
Here you go lad :D
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>


int main() {

        sf::RenderWindow window(sf::VideoMode(640, 360), "Test 123");

        sf::RenderTexture texture;
        texture.create(640, 360);

        sf::Texture tex;
        tex.loadFromFile("Image.png");

        sf::Sprite sprite;
        sprite.setTexture(tex);

        sf::Shader shader;
        shader.loadFromFile("Shockwave.frag", sf::Shader::Fragment);
        shader.setParameter("in_Center", 0.5f, 0.5f);
        shader.setParameter("in_ShockParams", 10.f, 0.8f, 0.1f);
        shader.setParameter("in_Time", 1.f);
        shader.setParameter("in_WindowWidth", 640);
        shader.setParameter("in_WindowHeight", 360);

        // The main loop
        while (window.isOpen()) {

                // Event processing
                sf::Event event;
                while (window.pollEvent(event)) {

                        if (event.type == sf::Event::Closed)
                                window.close();
                }

                texture.clear(sf::Color::Red);
                texture.draw(sprite);
                texture.display();

                sf::Sprite rSprite(texture.getTexture());

                window.clear();
                window.draw(rSprite, &shader);
                window.display();
        }
}
 

Just have a random image around and copy the shader stuff to a file.

EDIT: Didn't actually write this myself, found it on the internet, thats why I'm struggling so much :|
« Last Edit: January 17, 2014, 10:41:18 pm by Sumzary »

cob59

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Trying to implement a shockwave shader using sf::Shader
« Reply #4 on: January 17, 2014, 11:34:10 pm »
About shaders, I came across this topic once. It might help :
http://gmc.yoyogames.com/index.php?showtopic=586380

G.

  • Hero Member
  • *****
  • Posts: 1590
    • View Profile
Re: Trying to implement a shockwave shader using sf::Shader
« Reply #5 on: January 17, 2014, 11:49:46 pm »
var_TexCoord has no value. It's probably initialized in a vertex shader in the code you blindly copied. :p
Also, what Laurent asked.
« Last Edit: January 17, 2014, 11:52:23 pm by G. »

Sumzary

  • Guest
Re: Trying to implement a shockwave shader using sf::Shader
« Reply #6 on: January 18, 2014, 09:43:23 am »
After some googling and testing this is what I got.

The C++ code in "main.cpp":
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>


int main() {

        sf::RenderWindow window(sf::VideoMode(640, 360), "Test 123");

        sf::RenderTexture texture;
        texture.create(640, 360);

        sf::Texture tex;
        tex.loadFromFile("Image.png");

        sf::Sprite sprite;
        sprite.setTexture(tex);

        sf::Shader shader;
        shader.loadFromFile("Shockwave.vert", "Shockwave.frag");
        shader.setParameter("in_Texture", sf::Shader::CurrentTexture);
        shader.setParameter("in_Center", 0.5f, 0.5f);
        shader.setParameter("in_ShockParams", 10.0f, 0.8f, 0.1f);
        shader.setParameter("in_WindowWidth", 640);
        shader.setParameter("in_WindowHeight", 360);

        sf::Clock clock;
        clock.restart();

        // The main loop
        while (window.isOpen()) {

                // Event processing
                sf::Event event;
                while (window.pollEvent(event)) {

                        if (event.type == sf::Event::Closed)
                                window.close();
                }

                shader.setParameter("in_Time", clock.getElapsedTime().asSeconds());

                texture.clear(sf::Color::Red);
                texture.draw(sprite);
                texture.display();

                sf::Sprite rSprite(texture.getTexture());

                window.clear();
                window.draw(rSprite, &shader);
                window.display();
        }
}
 

The "Shockwave.vert":
#version 110

attribute vec4 in_Color;

varying vec4 var_Color;
varying vec2 var_TexCoord;

void main()
{
  gl_Position = ftransform();
  var_Color = in_Color;
  var_TexCoord = gl_MultiTexCoord0.xy;
}

And the "Shockwave.frag":
#version 110

uniform sampler2D in_Texture; // 0
uniform vec2 in_Center; // Mouse position
uniform float in_Time; // effect elapsed time. Multiply this to affect speed.

// Amplitude?, Refraction?, Width? e.g. 10.0, 0.8, 0.1
uniform vec3 in_ShockParams;

uniform int in_WindowWidth;
uniform int in_WindowHeight;

varying vec2 var_TexCoord;

void main()
{
  vec2 uv = var_TexCoord;
  vec2 texCoord = uv;
  float x = in_Center.x / float(in_WindowWidth);
  float y = (float(in_WindowHeight) - in_Center.y) / float(in_WindowHeight);
  float distance = distance(uv, vec2(x, y));

  if ( (distance <= (in_Time + in_ShockParams.z)) &&
       (distance >= (in_Time - in_ShockParams.z)) )
  {
    float diff = (distance - in_Time);
    float powDiff = 1.0 - pow(abs(diff * in_ShockParams.x),
                                in_ShockParams.y);
    float diffTime = diff * powDiff;
    vec2 diffUV = normalize(uv - in_Center);
    texCoord = uv + (diffUV * diffTime);
  }

  gl_FragColor = texture2D(in_Texture, texCoord);
}

The program without the shader:


With shader:



It seems to just show this one pixel from the top-left corner, it's like I'm missing something very simple. Ideas?

the_mean_marine

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: Trying to implement a shockwave shader using sf::Shader
« Reply #7 on: January 18, 2014, 11:00:49 am »
You've made a small mistake in your vertex shader.

The line:
var_TexCoord = gl_MultiTexCoord0.xy;
should be:
var_TexCoord = gl_TextureMatrix[0] * gl_MultiTexCoord0;

Sumzary

  • Guest
Re: Trying to implement a shockwave shader using sf::Shader
« Reply #8 on: January 18, 2014, 03:04:51 pm »
It draws the background image fine, but the effect is just not there, fiddling with different values didn't help.  :(

Sumzary

  • Guest
Re: Trying to implement a shockwave shader using sf::Shader
« Reply #9 on: January 18, 2014, 08:28:48 pm »
Actually, I'm getting some errors:
An internal OpenGL call failed in Shader.cpp (235) : GL_INVALID_OPERATION, the specified operation is not allowed in the current state
An internal OpenGL call failed in Shader.cpp (235) : GL_INVALID_OPERATION, the specified operation is not allowed in the current state

Help meh, i'm stumped :'(

Sumzary

  • Guest
Re: Trying to implement a shockwave shader using sf::Shader
« Reply #10 on: January 18, 2014, 09:50:39 pm »
Well I solved it, these variables were ints:
uniform int in_WindowWidth;
uniform int in_WindowHeight;

Turns out you cant "shader.setParamater(int);", so I had to change the code to make them floats instead:
uniform float in_WindowWidth;
uniform float in_WindowHeight;

A feature to be added mayhaps?  ;)

Sqasher

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Trying to implement a shockwave shader using sf::Shader
« Reply #11 on: January 18, 2014, 10:59:09 pm »
You convert the int to float in the shockwave fragment shader anyway:

float x = in_Center.x / float(in_WindowWidth);
float y = (float(in_WindowHeight) - in_Center.y) / float(in_WindowHeight);
 

Also, graphics cards are made specifically for floating point calculations and can be slow in integer calculations. So I think this won't be added to SFML.