Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - StackDanny

Pages: [1]
1
Graphics / Re: Implementing VAO in SFML/OpenGL with shaders
« on: February 06, 2019, 02:01:48 pm »
Hello,

As far as I understand it binding the data with glew fills the layouted variables? So do I have to just update the version to allow layout variables?

2
Graphics / Implementing VAO in SFML/OpenGL with shaders
« on: January 21, 2019, 02:16:36 pm »
Hello, I am following a OpenGL tutorial series on YouTube and they use SDL for the window. I, however, would like to use SFML as I am very familiar with it. Well, except for all the OpenGL stuff. So I am trying to load my data to the gpu as a VAO. As far as I understand, These data points can be accessed in the shaders with
layout(location = 0)
I have never worked with this layout keyword and the in and out keywords, but I hope I understand them so far. The problem is that my program only provides me a white screen (no triangle). My system has occasionally crashed from time to time while I try to debug this Code (there seems to be a serious problem). I've read the SFML examples but their OpenGL example doesn't involve shaders. I've also searched on forums but they all seem to discuss problems beyond this "hello world" introduction-like program. It's really demotivating  :-\ after hours and hours not beeing able to get this simple program to run. I'd be so relieved if someone could explain my error(s). Thank you! :)

simple.vert
#version 330 core

layout(location = 0) in vec3 a_position;

void main(){
   gl_Position = vec4(a_position, 1.0f);
}

simple.frag
#version 330 core

out vec4 fragColor;

void main(){
        fragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

main.cpp
#define GLEW_STATIC
#include <GL/glew.h>

#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <iostream>


struct Vertex {
        float x;
        float y;
        float z;
};

struct VertexBuffer {

        VertexBuffer(Vertex* data, uint32_t numVertices) {
                glGenVertexArrays(1, &vao);
                this->bind();

                glGenBuffers(1, &bufferId);
                glBindBuffer(GL_ARRAY_BUFFER, bufferId);
                glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(Vertex), data, GL_STATIC_DRAW);

                glEnableVertexAttribArray(0);
                glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), data);
                this->unbind();
        }

        virtual ~VertexBuffer() {
                glDeleteBuffers(1, &bufferId);
        }

        void bind() {
                glBindVertexArray(vao);
        }

        void unbind() {
                glBindVertexArray(0);
        }
private:
        GLuint bufferId;
        GLuint vao;
};
int main(){
        sf::ContextSettings settings;
        settings.antialiasingLevel = 4;
        settings.depthBits = 24;
        settings.majorVersion = 3;
        settings.minorVersion = 3;

        sf::RenderWindow window;
        window.create(sf::VideoMode(1280, 720), "GLSFML", sf::Style::Default, settings);
        window.setVerticalSyncEnabled(true);

        glewInit();


        sf::Shader shader;
        shader.loadFromFile("resources/simple.vert", "resources/simple.frag");
        sf::Shader::bind(&shader);


        Vertex vertices[] = {
                Vertex{-0.5f, -0.5f, 0.0f},
                Vertex{0.0f, 0.5f, 0.0f},
                Vertex{0.5f, -0.5f, 0.0f}
        };
        uint32_t numVertices = 3;

        VertexBuffer vb(vertices, numVertices);

        try {
                while (window.isOpen()) {
                        sf::Event event;
                        while (window.pollEvent(event)) {
                                if (event.type == sf::Event::Closed) {
                                        window.close();
                                }
                        }

                        window.setActive(true);
                        glClearColor(0.5, 0.5, 0.0, 1.0);
                        glClear(GL_COLOR_BUFFER_BIT);

                        vb.bind();
                        glDrawArrays(GL_TRIANGLES, 0, numVertices);
                        vb.unbind();

                        window.setActive(false);

                        window.display();
                }
        }
        catch (std::exception& any) {
                std::cerr << any.what() << '\n';
                std::cin.get();
        }

        return EXIT_SUCCESS;
}
 

Edit: I just found this example file: https://gist.github.com/gamepopper/1931ca297f3decdee90e785f12762192 which might be what I need here.

3
Thanks to Fallahn, who showed me correct approach to this problem. Before tackling that, I would like to show you my results:

Luminescence (threshold = 0.24f):

Blur (4 Layers):

Assembled:


Yay! The solution is to set all transparent pixels to solid black vec4(0.0, 0.0, 0.0, 1.0) and than after they've been blurred, just add them ontop the scene:
vec4 tex_color = texture2D(texture, gl_TexCoord[0].xy);
vec4 add_color = texture2D(add_texture, gl_TexCoord[0].xy);
gl_FragColor = tex_color + add_color;
This way, if add_color is black ("transparent"), we add tex_color + vec4(0.0, 0.0, 0.0, 1.0) which results in no change!
This is great, because now you can ignore the alpha channel completely.
To understand why I find this so great, you can read this little rant here (feel free to skip it):
Without haying to worry about alpha you can ignore any sf::BlendMode like the confusing sf::BlendMode::OneMinusSrcAlpha which caused me headaches for 2 solid days. Try calculating any reasonable "true" alpha value when you know they are all premultiplied. Of course you also have to multiply all rgb values with the pixel's alpha to reverse the prumultiplication… the formulas escalate quite quickly from here. Also subtract 1 from alpha because it's OneMinusSrcAlpha... and don't forget to check for cases where the sum of all alphas (yes, you need to sum that) is 0 (or in OneMinusSrcAlpha matter, something else), because otherwise you get division by 0 (or in OneMinusSrcAlpha matter a division by 0 when all surrounding pixels are solid). Also sometimes weird alpha values might work, but only for a single pass of blur, but in my case I have multiple passes.. etc.
Here's the final code:

luminescence.frag
#version 120

uniform sampler2D texture;
uniform float threshold;

void main(void){
    vec3 current_color = texture2D(texture, gl_TexCoord[0].xy).rgb;
    vec4 pixel =  vec4(0.0, 0.0, 0.0, 1.0);
    float brightness = dot(current_color.rgb, vec3(0.2126, 0.7152, 0.0722));
    if (brightness >= threshold){
        pixel = texture2D(texture, gl_TexCoord[0].xy);
    }
    gl_FragColor = pixel;
}
boxblur.frag
#version 120

uniform sampler2D texture;
uniform float texture_inverse;
uniform int blur_radius;
uniform vec2 blur_direction;

void main(void){
    vec4 sum = texture2D(texture, gl_TexCoord[0].xy);

    for (int i = 0; i < blur_radius; ++i){
        sum += texture2D(texture, gl_TexCoord[0].xy + (i * texture_inverse) * blur_direction);
        sum += texture2D(texture, gl_TexCoord[0].xy - (i * texture_inverse) * blur_direction);
    }
    gl_FragColor = sum / (blur_radius * 2 + 1);
}
multiply.frag
#version 120

uniform sampler2D texture;
uniform float multiply;

void main(void){
    gl_FragColor = texture2D(texture, gl_TexCoord[0].xy) * multiply;
}
assemble.frag
#version 120

uniform sampler2D texture;
uniform sampler2D add_texture;
uniform float add_weight;

void main(void){
    vec4 tex_color = texture2D(texture, gl_TexCoord[0].xy);
    vec4 add_color = texture2D(add_texture, gl_TexCoord[0].xy) * add_weight;
    gl_FragColor = tex_color + add_color;
}

main.cpp
#include <SFML/Graphics.hpp>
#include <iostream>
#include <array>

void run() {
    const sf::Vector2f SIZE(1280, 720);

    sf::Texture background_tex;
    background_tex.loadFromFile("resources/background.jpg");
    sf::Sprite background(background_tex);

    sf::Shader luminescence_shader;
    luminescence_shader.loadFromFile("resources/luminescence.frag", sf::Shader::Fragment);
    luminescence_shader.setUniform("texture", sf::Shader::CurrentTexture);
    luminescence_shader.setUniform("threshold", 0.24f);

    sf::Shader blur_shader;
    blur_shader.loadFromFile("resources/boxblur.frag", sf::Shader::Fragment);
    blur_shader.setUniform("texture", sf::Shader::CurrentTexture);
    blur_shader.setUniform("texture_inverse", 1.0f / SIZE.x);

    sf::Shader assemble_shader;
    assemble_shader.loadFromFile("resources/assemble.frag", sf::Shader::Fragment);
    assemble_shader.setUniform("texture", sf::Shader::CurrentTexture);

    sf::Shader multiply_shader;
    multiply_shader.loadFromFile("resources/multiply.frag", sf::Shader::Fragment);
    multiply_shader.setUniform("texture", sf::Shader::CurrentTexture);


    sf::RenderStates shader_states;
    //no blendmode! we make our own - assemble.frag

    sf::ContextSettings context_settings;
    context_settings.antialiasingLevel = 12;

    //draws background
    sf::RenderTexture scene_render;
    scene_render.create(SIZE.x, SIZE.y, context_settings);

    sf::RenderTexture luminescence_render;
    luminescence_render.create(SIZE.x, SIZE.y, context_settings);

    //draws luminescence and blur
    sf::RenderTexture assemble_render;
    assemble_render.create(SIZE.x, SIZE.y, context_settings);



    //addding multiple boxblurs with different radii looks really nice! in this case 4 layers
    std::array<sf::RenderTexture, 4> blur_renders;
    for (int i = 0; i < blur_renders.size(); ++i) {
        blur_renders[i].create(SIZE.x, SIZE.y, context_settings);
    }
    const int BLUR_RADIUS_VALUES[] = { 250, 180, 125, 55 };
    float blur_weight = blur_renders.empty() ? 0.0 : 1.0 / blur_renders.size();

    sf::RenderWindow window(sf::VideoMode(SIZE.x, SIZE.y), "glsl fun", sf::Style::Default, context_settings);

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }

        //first draw the scene
        scene_render.clear();
        scene_render.draw(background);
        scene_render.display();


        //apply luminescence
        shader_states.shader = &luminescence_shader;
        luminescence_render.clear();
        luminescence_render.draw(sf::Sprite(scene_render.getTexture()), shader_states);
        luminescence_render.display();

        //apply two pass gaussian blur n times to simulate gaussian blur.
        shader_states.shader = &blur_shader;
        for (int i = 0; i < blur_renders.size(); ++i) {
            blur_shader.setUniform("blur_radius", BLUR_RADIUS_VALUES[i]);

            blur_renders[i].clear();
            blur_renders[i].draw(sf::Sprite(luminescence_render.getTexture()));
            blur_renders[i].display();

            //vertical blur
            blur_shader.setUniform("blur_direction", sf::Glsl::Vec2(1.0, 0.0));
            blur_renders[i].draw(sf::Sprite(blur_renders[i].getTexture()), shader_states);
            blur_renders[i].display();

            //horizontal blur
            blur_shader.setUniform("blur_direction", sf::Glsl::Vec2(0.0, 1.0));
            blur_renders[i].draw(sf::Sprite(blur_renders[i].getTexture()), shader_states);
            blur_renders[i].display();
        }

        //load blur_renders[0] into assemble_render so we can add the other blurs ontop of it
        shader_states.shader = &multiply_shader;
        multiply_shader.setUniform("multiply", blur_weight);
        assemble_render.clear();
        assemble_render.draw(sf::Sprite(blur_renders[0].getTexture()), shader_states);
        assemble_render.display();

        //adding the rest ontop creating a final blur
        shader_states.shader = &assemble_shader;
        assemble_shader.setUniform("add_weight", blur_weight);
        for (int i = 1; i < blur_renders.size(); ++i) {
            assemble_shader.setUniform("add_texture", blur_renders[i].getTexture());
            assemble_render.draw(sf::Sprite(assemble_render.getTexture()), shader_states);
            assemble_render.display();
        }

        //final result; scene + blur
        assemble_shader.setUniform("add_weight", 1.0f);
        assemble_shader.setUniform("add_texture", assemble_render.getTexture());
        assemble_render.draw(sf::Sprite(scene_render.getTexture()), shader_states);
        assemble_render.display();

        window.clear();
        window.draw(sf::Sprite(assemble_render.getTexture()));
        window.display();
    }
}

int main() {
    try {
        run();
    }
    catch (std::exception e) {
        std::cerr << "caught exception - - - " << e.what() << '\n';
        return 1;
    }
    return 0;
}

4
Wow that works!. I will post the working Code here (and on StackoverFlow) for people that have the same/similiar problem.  Thank you so much!

5
If I draw a black texture above my scene, I see the black texture. If I set the luminescence Pixels to Black and blur it, I also blur the black Pixels. So I am not sure if it's really additvely. The Question is, If I can set up sf::RenderWindow in a way, that drawing is done additevely and not alpha channel based. Or I can also just ignore the alpha values in the blur shader, which I am trying to do. So 2 possible ways.

6
I am sure that the boxblur is right choice (either that or gaussian blur ; basically the same thing), the theory behind this seems correct; https://learnopengl.com/Advanced-Lighting/Bloom scroll down to paragraph "Gaussian blur" - they use the same idea!

7
Hi, I don't know how I can ensure that. However, I can simulate such an effect by keeping the sf::BlendMode but removing
pixel.rgb *= pixel.a;
from boxblur.frag. This way I get a White Edge effect. But this only Looks fine if the luminescence mask is mostly White. But that's rarely the case. I lowered the threshold to 0.3f and it Looks like this: (https://imgur.com/a/eZF18MY)
I just want the edge to be the same color as at the luminescence mask for a given point. It just seems unbelievable tricky to achieve this, something that seemed like an easy task at first glance.

8
Hey I want to create a glow effect for my application, I already posted everything relevant to my question on StackOverflow here: https://stackoverflow.com/questions/54204592/making-a-glow-effect-problems-with-alpha-values-c-sfml-glsl
But it seems pretty dead there. So I would like to propose it on this forum aswell.

To reduce code size to the minimum, let's say I want to create a glow effect on an image. Starting with this one:



To produce an effect that looks like this:



It's a three step way.
- save all bright pixels from the scene (= luminescence)
- apply a blur effect on those pixels (= blur)
- draw original picture and the blur texture ontop (= assemble)

Step 1 and 3 are no Problem. The blur part just doesn't want to work correctly.
Before I explain further, here's my luminescence result:

Here I have set the threshold to be 0.67f - looks pretty good. But now when I try to blur this, I get some unlucky results:

This black edge comes from the fact, that any transparent color is black
vec4(0.0, 0.0, 0.0, 0.0)
I've read about this on this sfml forum, and the suggestion was to use SFML's sf::BlendMode for this and multiply the .rgb value of the final pixel color in the fragment shader with its alpha value. So I did and now this my result:

It's better, but definetely not good. The blur shader now also avarages out the surrounding pixels of the luminescence mask. After assembling it's just a blurry picture:

.. I tried "fixing" this in the shader files by checking if the pixel's alpha is zero. This way I don't value them when avaraging out. But since sf::BlendMode is activated, I don't know how alpha behaves now - So I deactivated the blendmode but I still have weird results. (at the very of this question I provided the code and a result from this attempt)

none of my attempts to fix this work. I really could use some help here. Maybe I'm doing something fundamentally wrong in the shaders.. here's the full code - If you want to compile it, make a folder "resources" with the 2 Fragment shaders and the background.jpg (: https://pixnio.com/architecture/city-downtown/urban-water-architecture-buildings-city-lights-evening)  (in 1280x720). You can use of course any other picture. I just used this one because it's free to use and dark enough to get some exciting glow effect.

luminescence.frag

#version 120

uniform sampler2D texture;
uniform float threshold;

void main(void){
    vec3 current_color = texture2D(texture, gl_TexCoord[0].xy).rgb;
    vec4 pixel =  vec4(current_color.rgb, 0.0);
    float brightness = dot(current_color.rgb, vec3(0.2126, 0.7152, 0.0722));
    if (brightness >= threshold){
        pixel = texture2D(texture, gl_TexCoord[0].xy);
    }
    gl_FragColor = pixel;
}

boxblur.frag
#version 120

uniform sampler2D texture;
uniform float texture_inverse;
uniform int blur_radius;
uniform vec2 blur_direction;

void main(void){
    vec4 sum = texture2D(texture, gl_TexCoord[0].xy);

    for (int i = 0; i < blur_radius; ++i){
        sum += texture2D(texture, gl_TexCoord[0].xy + (i * texture_inverse) * blur_direction);
        sum += texture2D(texture, gl_TexCoord[0].xy - (i * texture_inverse) * blur_direction);
    }
    vec4 pixel = vec4(sum / (blur_radius * 2 + 1));
    pixel.rgb *= pixel.a; //to negate the sf::BlendMode effect
    gl_FragColor = pixel;
}
main.cpp
#include <SFML/Graphics.hpp>
#include <iostream>
#include <exception>

void run() {
    const sf::Vector2f SIZE(1280, 720);

    sf::Texture background_tex;
    background_tex.loadFromFile("resources/background.jpg");
    sf::Sprite background(background_tex);



    sf::Shader luminescence;
    luminescence.loadFromFile("resources/luminescence.frag", sf::Shader::Fragment);
    luminescence.setUniform("texture", sf::Shader::CurrentTexture);
    luminescence.setUniform("threshold", 0.67f);

    sf::Shader blur;
    blur.loadFromFile("resources/boxblur.frag", sf::Shader::Fragment);
    blur.setUniform("texture", sf::Shader::CurrentTexture);
    blur.setUniform("texture_inverse", 1.0f / SIZE.x);




    sf::RenderStates shader_states;
    //this line sets the blendmode!
    shader_states.blendMode = sf::BlendMode(sf::BlendMode::One, sf::BlendMode::OneMinusSrcAlpha);



    sf::ContextSettings context_settings;
    context_settings.antialiasingLevel = 12;

    //draws background
    sf::RenderTexture scene_render;
    scene_render.create(SIZE.x, SIZE.y, context_settings);

    //draws luminescence and blur
    sf::RenderTexture shader_render;
    shader_render.create(SIZE.x, SIZE.y, context_settings);



    sf::RenderWindow window(sf::VideoMode(SIZE.x, SIZE.y), "glsl fun", sf::Style::Default, context_settings);

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }

        scene_render.clear();
        scene_render.draw(background);
        scene_render.display();


        //apply luminescence
        shader_states.shader = &luminescence;
        shader_render.clear(sf::Color::Transparent);
        shader_render.draw(sf::Sprite(scene_render.getTexture()), shader_states);
        shader_render.display();

        //apply two pass gaussian blur 3 times to simulate gaussian blur.
        shader_states.shader = &blur;
        float blur_radius = 30.0f;
        for (int i = 0; i < 3; ++i) {
            blur.setUniform("blur_radius", static_cast<int>(blur_radius));

            //vertical blur
            blur.setUniform("blur_direction", sf::Glsl::Vec2(1.0, 0.0));
            shader_render.draw(sf::Sprite(shader_render.getTexture()), shader_states);
            shader_render.display();

            //horizontal blur
            blur.setUniform("blur_direction", sf::Glsl::Vec2(0.0, 1.0));
            shader_render.draw(sf::Sprite(shader_render.getTexture()), shader_states);
            shader_render.display();

            //decrease blur_radius to simulate a gaussian blur
            blur_radius *= 0.45f;
        }

        //assembly
        window.clear();
        window.draw(sf::Sprite(scene_render.getTexture()));
        window.draw(sf::Sprite(shader_render.getTexture()));
        window.display();
    }
}

int main() {
    try {
        run();
    }
    catch (std::exception e) {
        std::cerr << "caught exception - - - " << e.what() << '\n';
        return 1;
    }
    return 0;
}

Ok and this is the attempt to modify boxblur.frag to exclude zero alpha values: (I removed
shader_states.blendMode = sf::BlendMode(sf::BlendMode::One, sf::BlendMode::OneMinusSrcAlpha);
on line 29 in main.cpp for this of course):
#version 120

uniform sampler2D texture;
uniform float texture_inverse;
uniform int blur_radius;
uniform vec2 blur_direction;

void main(void){
    float div = 0.0;
    vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
    vec4 temp_color = texture2D(texture, gl_TexCoord[0].xy);
    if (temp_color.a > 0.0){
        sum += temp_color;
        div += 1.0;
    }


    for (int i = 0; i < blur_radius; ++i){
        temp_color = texture2D(texture, gl_TexCoord[0].xy + (i * texture_inverse) * blur_direction);
        if (temp_color.a > 0.0){
            sum += temp_color;
            div += 1.0;
        }
        temp_color = texture2D(texture, gl_TexCoord[0].xy - (i * texture_inverse) * blur_direction);
        if (temp_color.a > 0.0){
            sum += temp_color;
            div += 1.0;
        }
    }
    vec4 pixel;
    if (div == 0.0){
        pixel = vec4(texture2D(texture, gl_TexCoord[0].xy).rgb, 0.0);
    }
    else{
        pixel = vec4(sum / div);
    }
    gl_FragColor = pixel;
}

And this results in:

[I am using Visual Studio 2017 Community] - Thanks for any help!

Pages: [1]