Search code examples
c++visual-studio-2010glslshadersfml

SFML 2.0 GLSL Volumetric Light Scattering Shader


Using the GLSL shader source code provided by Kenny Mitchell in GPU Gems 3, I've attempted to create some 2D god rays using SFML 2.0. Currently, whenever I compile and debug the project, the mask texture and sprite ("image.png" and "sprite", respectively) disappear completely. The project I have currently set up is very crude, consisting of only one main.cpp file and the shader files, though I have a feeling that I would require more than I have currently. Any help would be much appreciated! Source code will be provided below.

main.cpp:

#include <SFML\Graphics.hpp>
#include <SFML\System.hpp>
#include <SFML\Window.hpp>
#include <iostream>

void main()
{
    sf::RenderWindow _window(sf::VideoMode(800, 480, 32), "Lighting Test");
    _window.setFramerateLimit(60);

    sf::Shader lightingShader;
    sf::RenderStates renderState;

    sf::Texture texture;
    texture.loadFromFile("image.png");

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

    sf::Texture backgroundTexture;
    backgroundTexture.loadFromFile("light.png");

    sf::Sprite background;
    background.setTexture(backgroundTexture);

    while (_window.isOpen())
    {
        int x = sf::Mouse::getPosition(_window).x;
        int y = sf::Mouse::getPosition(_window).y;

        lightingShader.loadFromFile("lightingShader.vert", "lightingShader.frag");
        lightingShader.setParameter("exposure", 0.25f);
        lightingShader.setParameter("decay", 0.97f);
        lightingShader.setParameter("density", 0.97f);
        lightingShader.setParameter("weight", 0.5f);
        lightingShader.setParameter("lightPositionOnScreen", sf::Vector2f(0.5f, 0.5f));
        lightingShader.setParameter("myTexture", sf::Shader::CurrentTexture);
        renderState.shader = &lightingShader;

        _window.clear(sf::Color::Black);
        sprite.setPosition(x, y);
        //sprite.setColor(sf::Color::Black);
        //background.setPosition(400, 240);
        _window.draw(background);
        _window.draw(sprite, renderState);
        _window.display();
    }
}

lightingShader.vert:

void main() 
{

    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = ftransform();
}

lightingShader.frag:

uniform float exposure;
uniform float decay;
uniform float density;
uniform float weight;
uniform vec2 lightPositionOnScreen;
uniform sampler2D myTexture;
const int NUM_SAMPLES = 100 ;
void main()
{   
    vec2 deltaTextCoord = vec2( gl_TexCoord[0].st - lightPositionOnScreen.xy );
    vec2 textCoord = gl_TexCoord[0].st;
    deltaTextCoord *= 1.0 /  float(NUM_SAMPLES) * density;
    float illuminationDecay = 1.0;


    for(int i=0; i < NUM_SAMPLES ; i++)
    {
            textCoord -= deltaTextCoord;
            vec4 sample = texture2D(myTexture, textCoord);

            sample *= illuminationDecay * weight;

            gl_FragColor += sample;

            illuminationDecay *= decay;
    }


    gl_FragColor *= exposure;
}

Solution

  • I've finally solved the problem on my own. Turns out the vertex shader I created was unnecessary, and all I had to do was replace:

    lightingShader.loadFromFile("lightingShader.vert", "lightingShader.frag");

    With:

    lightingShader.loadFromFile("lightingShader.frag", sf::Shader::Type::Fragment);.