If nothing can be done, I can actually put all the effects in one shader file, but I guess it should be possible to re-draw objects to RenderImages several times but with different shaders.
Here is the minimal code (I hope):
#include <SFML/Graphics.hpp>
#include <iostream>
std::string pixelate = "uniform sampler2D texture;\
uniform vec2 mouse;\
\
void main()\
{\
float factor = 5 + 100 * length(mouse);\
vec2 pos = floor(gl_TexCoord[0].xy * factor + 0.5) / factor;\
\
gl_FragColor = texture2D(texture, pos) * gl_Color; \
}\
";
std::string colorize = "\
uniform sampler2D texture;\
uniform vec3 color;\
\
void main()\
{\
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy) * gl_Color;\
float gray = pixel.r * 0.39 + pixel.g * 0.50 + pixel.b * 0.11;\
\
gl_FragColor = vec4(gray * color, 1.0) * 0.6 + pixel * 0.4;\
gl_FragColor.a = pixel.a;\
}\
";
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Shader");
// Load a background image to display
sf::Shape Circle = sf::Shape::Circle(400, 300, 100, sf::Color::White);
sf::Shader shaders[2];
shaders[0].LoadFromMemory(pixelate.c_str());
shaders[1].LoadFromMemory(colorize.c_str());
shaders[0].SetTexture("texture", sf::Shader::CurrentTexture);
shaders[1].SetTexture("texture", sf::Shader::CurrentTexture);
shaders[1].SetParameter("color", 1.f, 1.f, 1.f);
sf::RenderImage rim, buffer;
rim.Create(800, 600);
buffer.Create(800, 600);
sf::RenderImage *front = &rim;
sf::RenderImage *back = &buffer;
// Start the game loop
while (window.IsOpened())
{
// Process events
sf::Event event;
while (window.GetEvent(event))
{
// Close window : exit
if (event.Type == sf::Event::Closed)
window.Close();
}
shaders[1].SetParameter("color", (1.0f / window.GetInput().GetMouseX()) * 800.0f, 1.0f, 1.0f);
shaders[0].SetParameter("mouse", (float)window.GetInput().GetMouseX() / static_cast<float>(window.GetWidth()), (float)window.GetInput().GetMouseY() / static_cast<float>(window.GetHeight()));
window.Clear();
back->Clear();
back->Draw(Circle);
back->Display();
for ( int i = 0; i < 2; i++)
{
front->Clear();
front->Draw(sf::Sprite(back->GetImage()), shaders[i]);
front->Display();
std::swap(front, back);
}
sf::Sprite test(back->GetImage());
window.Draw(test);
// Finally, display the rendered frame on screen
window.Display();
}
}
The last shader's parameter is not updated (?) Actually this looks like a different problem.