Much of game making boils down to 'faking it' quite often
However the fastest way to do something like this programatically (and most fun way imo, cos shaders are awesome
) is to use a noise shader like this:
namespace
{
const std::string GreyFrag = R"(
#version 120
#define GREY
)";
const std::string ColourFrag = R"(
#version 120
)";
const std::string NoiseFrag = R"(
uniform float u_time;
float rand(vec2 pos)
{
return fract(sin(dot(pos, vec2(12.9898, 4.1414) + u_time)) * 43758.5453);
}
void main()
{
#if defined (GREY)
gl_FragColor.rgb = vec3(rand(floor((gl_FragCoord.xy))));
#else
// these are arbitrary numbers just to provide an offset.
// you could use uniform values here for a variable effect
gl_FragColor.r = rand(floor((gl_FragCoord.xy + 17.034765)));
gl_FragColor.g = 1.0 - rand(floor((gl_FragCoord.xy)));
gl_FragColor.b = rand(floor((gl_FragCoord.xy + 0.145)));
#endif
gl_FragColor.a = 1.0;
})";
}
int main()
{
sf::RenderWindow window(sf::VideoMode(400, 200), "SFML works!");
sf::CircleShape shape(100.f);
sf::Shader greyShader;
greyShader.loadFromMemory(GreyFrag + NoiseFrag, sf::Shader::Fragment);
sf::Shader colourShader;
colourShader.loadFromMemory(ColourFrag + NoiseFrag, sf::Shader::Fragment);
sf::Clock shaderClock;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
}
}
float shaderTime = shaderClock.getElapsedTime().asSeconds();
greyShader.setUniform("u_time", shaderTime);
colourShader.setUniform("u_time", shaderTime);
window.clear();
shape.setPosition(0.f, 0.f);
window.draw(shape, &greyShader);
shape.setPosition(200.f, 0.f);
window.draw(shape, &colourShader);
window.display();
}
return 0;
}