Skip to content

Instantly share code, notes, and snippets.

@MarioLiebisch
Created July 18, 2016 08:47
Show Gist options
  • Save MarioLiebisch/fff9fb605295504eb29fc49c50d35321 to your computer and use it in GitHub Desktop.
Save MarioLiebisch/fff9fb605295504eb29fc49c50d35321 to your computer and use it in GitHub Desktop.
Drawing a parallax background using a fragment shader.
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(1024, 768), "Parallax Example",
sf::Style::Titlebar | sf::Style::Close | sf::Style::Fullscreen);
window.setVerticalSyncEnabled(true);
sf::Texture texture;
// This is a texture 1024x1024 with three backgrounds stacked one over the other from front to back
if (!texture.loadFromFile("resources/cave.png"))
return EXIT_FAILURE;
texture.setRepeated(true);
sf::VertexArray sprite(sf::TriangleFan);
sprite.append(sf::Vertex(sf::Vector2f(0,0), sf::Vector2f(0,0)));
sprite.append(sf::Vertex(sf::Vector2f(1024, 0), sf::Vector2f(1024, 0)));
sprite.append(sf::Vertex(sf::Vector2f(1024, 768), sf::Vector2f(1024, 1024)));
sprite.append(sf::Vertex(sf::Vector2f(0, 768), sf::Vector2f(0, 1024)));
sf::Shader parallaxShader;
parallaxShader.loadFromMemory(
"uniform sampler2D texture;"
"uniform float offset;"
// This shader is just for demonstration purposes. There's most likely a better way to do it. :)
"void main() {"
" vec2 p3 = gl_TexCoord[0].xy; p3.y = p3.y / 3.;"
" vec2 p2 = p3; p2.y = p2.y + .33; p2.x = p2.x + offset / 10;"
" vec2 p1 = p3; p1.y = p1.y + .67; p1.x = p1.x + offset / 100;"
" p3.x = p3.x + offset;"
" vec4 bg1 = texture2D(texture, p1);"
" vec4 bg2 = texture2D(texture, p2);"
" vec4 bg3 = texture2D(texture, p3);"
" bg1 = bg1 * (1 - bg2.a) + bg2 * bg2.a;"
" gl_FragColor = bg1 * (1 - bg3.a) + bg3 * bg3.a;"
"}"
, sf::Shader::Fragment);
float offset = 0.f;
sf::RenderStates state;
state.blendMode = sf::BlendAlpha;
state.shader = &parallaxShader;
state.texture = &texture;
sf::Clock clock;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
switch (event.type) {
case sf::Event::Closed:
window.close();
break;
}
}
// I set an arbitrary value as the offset, you'd calculate this based on camera position
parallaxShader.setUniform("offset", offset += clock.restart().asSeconds() / 2);
window.clear();
window.draw(sprite, state);
window.display();
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment