-
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 ;]
-
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. ;)
-
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.
-
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 :|
-
About shaders, I came across this topic once. It might help :
http://gmc.yoyogames.com/index.php?showtopic=586380
-
var_TexCoord has no value. It's probably initialized in a vertex shader in the code you blindly copied. :p
Also, what Laurent asked.
-
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:
(http://s8.postimg.org/vev9087zp/image.png)
With shader:
(http://s8.postimg.org/kqri1dy0l/image.png)
It seems to just show this one pixel from the top-left corner, it's like I'm missing something very simple. Ideas?
-
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;
-
It draws the background image fine, but the effect is just not there, fiddling with different values didn't help. :(
-
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 :'(
-
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? ;)
-
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.