Hi,
I'm trying to create a glow effect with shaders, and for that I blur an image and I draw a copy of that image above. If I clear the renderTextures with any color, everything works, but when I use renderTexture.clear( sf::Color::Transparent ), my shader reacts like if the background was black, so there is a black thing around my blur.
Generally, the transparent pixels are considered as black transparent ones, so in the beginning, I thought that my shader was not aware of the alpha of the pixels (which was true ^^), but now I have no idea of why it doesn't work with transparent renderTextures.
In a nutshell: why there is a black thing around my blurs when I clear my renderTextures with transparent colors, and how to make it works? I think the problem is not in my shader, but I'm not 100% sure
main.cpp:
#include <SFML/Graphics.hpp>
int main(){
// Main window, where I draw the render of the glowing and non-glowing objects together
sf::RenderWindow mainWindow( sf::VideoMode( 512, 512 ), "SFML 2" );
mainWindow.setFramerateLimit( 60 );
mainWindow.setVerticalSyncEnabled( true );
// Render for the non-glowing objects
sf::RenderTexture renderNormal; renderNormal.create( 512, 512 );
// Render for the glowing objects
sf::RenderTexture renderBlur; renderBlur.create( 512, 512 );
// Render of the blur on the x axis
sf::RenderTexture renderBlurX; renderBlurX.create( 512, 512 );
// Render of the blur on the y axis, after the blur on the x axis
sf::RenderTexture renderBlurY; renderBlurY.create( 512, 512 );
// Texture 512*256 with the text "to blur"
sf::Texture textureToBlur; textureToBlur.loadFromFile( "data/1.png" );
// Texture 512*256 with the text "to not"
sf::Texture textureToNot; textureToNot.loadFromFile( "data/2.png" );
// Sprite with the text "to blur":
sf::Sprite spriteBlurObject( textureToBlur );
// Sprite with the text "to not":
sf::Sprite spriteNormalObject( textureToNot );
// Same sprite as 'spriteBlurObject', but this one will be blured and put behind 'spriteBlurObject':
sf::Sprite spriteBlurObjectback( textureToBlur );
// Sprite where I render the non-glowing objects
sf::Sprite spriteRenderNormal( renderNormal.getTexture());
// Sprite where I render the glowing objects
sf::Sprite spriteRenderGlow( renderBlur.getTexture());
// Sprite for the blur on the x axis
sf::Sprite spriteRenderBlurX( renderBlurX.getTexture());
// Sprite for the blur on the y axis, after the blur on the x axis
sf::Sprite spriteRenderBlurY( renderBlurY.getTexture());
// The text 'to not' must not overlap with the text 'to glow'
spriteNormalObject.setPosition( 0, 256 );
// Shader which transform a texture, to create a blur on the x axis
sf::Shader shaderBlurX;
shaderBlurX.loadFromFile( "blur.frag", sf::Shader::Fragment );
shaderBlurX.setUniform( "texture", textureToBlur );
shaderBlurX.setUniform( "invertTextureSize", 1.0f/textureToBlur.getSize().x );
shaderBlurX.setUniform( "blurSize", 7 );
shaderBlurX.setUniform( "direction", sf::Vector2f( 1, 0 ));
// Same as 'shaderBlurX', but for the y axis
sf::Shader shaderBlurY;
shaderBlurY.loadFromFile( "blur.frag", sf::Shader::Fragment );
shaderBlurY.setUniform( "texture", renderBlurX.getTexture());
shaderBlurY.setUniform( "invertTextureSize", 1.0f/renderBlur.getTexture().getSize().y );
shaderBlurY.setUniform( "blurSize", 7 );
shaderBlurY.setUniform( "direction", sf::Vector2f( 0, 1 ));
// A simple shader to enhance alpha, it is not necessary
sf::Shader shaderAlpha;
shaderAlpha.loadFromFile( "prog/alpha.frag", sf::Shader::Fragment );
shaderAlpha.setUniform( "texture", renderBlurY.getTexture());
while( mainWindow.isOpen()){
sf::Event event;
while( mainWindow.pollEvent( event )){
switch( event.type ){
case sf::Event::Closed:
mainWindow.close();
break;
default:
break;
}
}
// Create the blur on the x axis
//renderBlurX.clear( sf::Color::Transparent ); // With this clear, there is a black thing around the blur
renderBlurX.clear( sf::Color::White ); // With this clear, everything works but there is no transparency
renderBlurX.draw( spriteBlurObjectback, &shaderBlurX );
renderBlurX.display();
// Create the blur on the y axis, after the blur on the x axis
renderBlurY.clear( sf::Color::Transparent );
renderBlurY.draw( spriteRenderBlurX, &shaderBlurY );
renderBlurY.display();
// Draw the glowing objects
renderBlur.clear( sf::Color::Transparent );
renderBlur.draw( spriteRenderBlurY, &shaderAlpha ); // Glowing (which is just a blur)/
renderBlur.draw( spriteBlurObject ); // Object himself
renderBlur.display();
// Draw the non-glowing objects
renderNormal.clear( sf::Color::Transparent );
renderNormal.draw( spriteNormalObject );
renderNormal.display();
// Draw the glowing and non-glowing objects
mainWindow.clear( sf::Color::White );
mainWindow.draw( spriteRenderNormal );
mainWindow.draw( spriteRenderGlow );
mainWindow.display();
}
}
blur.frag:
#version 330
uniform sampler2D texture; // Texture which will be modified
uniform float invertTextureSize; // Invert of the size of the texture, on the axis we working on
uniform int blurSize; // Size of the blur
uniform vec2 direction; // Direction of the blur (only (0;1) or (1;0))
void main(){
vec4 color = vec4( 0 );
vec4 tmpColor;
float sumColors = 0;
float sumAlphas = 0;
for( int i = -blurSize; i <= blurSize; ++i ){
tmpColor = texture2D( texture, vec2(
gl_TexCoord[0].s + ( direction.x*i*invertTextureSize ),
gl_TexCoord[0].t + ( direction.y*i*invertTextureSize )
));
color.rgb += tmpColor.rgb * tmpColor.a;
color.a += tmpColor.a;
sumColors += tmpColor.a;
sumAlphas += 1;
}
color.rgb /= sumColors;
color.a /= sumAlphas;
gl_FragColor = vec4( color.r, color.g, color.b, color.a );
}
alpha.frag:
#version 330
uniform sampler2D texture;
void main(){
vec4 color = texture2D( texture, gl_TexCoord[0].st );
color.w *= 2.5;
gl_FragColor = color;
}