I want to create a glow effect for my game. In order to keep this minimalistic let's say I want to glow an Image. :)
Starting with this one:
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:
(threshold = 0.67f)
An now when I 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). It's not an unkown Problem within SFML/GLSL, 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 (in 1280x720).
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;
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;
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;
}
This is the boxblur.frag where I tried to exclude zero alpha values: (I removed shader_states.blendMode = sf::BlendMode(sf::BlendMode::One, sf::BlendMode::OneMinusSrcAlpha);on line 29 in main.cpp 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;
}
[I am using Visual Studio 2017 Community] - Thanks for any help!






