Please have a look at this code:
#include <iostream>
#include <conio.h>
#include <SFML/Graphics.hpp>
using namespace std;
using namespace sf;
float stepSizeMultiplier = 2.0f;
unsigned int additionalTextureSize = 200;
int main()
{
// Create the window
RenderWindow window(VideoMode(800, 600, 32), "SFML Shader Test", Style::Default);
Event eve;
// Create a Sprite with a texture
Texture texture;
texture.loadFromFile("Resources/Textures/stoneHouse.png");
texture.setSmooth(true);
Sprite sprite(texture);
sprite.setPosition(400.0f, 100.0f);
sprite.setScale(1.3f, 1.3f);
sprite.setRotation(7);
// Create the Render Textures
RenderTexture outlineTexture;
outlineTexture.create(sprite.getGlobalBounds().width + 2 * additionalTextureSize, sprite.getGlobalBounds().height + 2 * additionalTextureSize);
outlineTexture.setSmooth(true);
// Create the outline shader
Shader outlineShader;
outlineShader.loadFromFile("Resources/Shader/outlineShader.txt", Shader::Fragment);
outlineShader.setUniform("texture", Shader::CurrentTexture);
outlineShader.setUniform("edge_threshold", 10.0f / sprite.getGlobalBounds().width);
// Create the blur shader
Shader blurShader;
blurShader.loadFromFile("Resources/Shader/blurShader.txt", Shader::Fragment);
blurShader.setUniform("texture", Shader::CurrentTexture);
blurShader.setUniform("blur_radius", 2.0f / (sprite.getGlobalBounds().width + additionalTextureSize * 2));
// If ome of the shaders is not available
if (!outlineShader.isAvailable() || !blurShader.isAvailable())
cerr << endl << "Shaders are not available on this system!";
while (window.isOpen())
{
while (window.pollEvent(eve))
{
if (eve.type == Event::Closed)
window.close();
if (eve.type == Event::KeyReleased)
if (eve.key.code == Keyboard::Key::Escape)
window.close();
}
window.clear();
// Draw a rectangle to see where the renderTexture is
RectangleShape rectagle(static_cast<Vector2f>(window.getSize()));
rectagle.setFillColor(Color::Red);
window.draw(rectagle);
// Draw the outline renderTexture
outlineTexture.clear();
// Draw a transparent rectangle
RectangleShape rect(static_cast<Vector2f>(outlineTexture.getSize()));
rect.setFillColor(Color::Transparent);
outlineTexture.draw(rect, BlendMultiply);
Vector2f position = sprite.getPosition();
sprite.setPosition(additionalTextureSize, additionalTextureSize);
outlineTexture.draw(sprite, &outlineShader);
sprite.setPosition(position);
outlineTexture.display();
// Create an outline Sprite
Sprite outlineSprite;
outlineSprite.setTexture(outlineTexture.getTexture());
outlineSprite.setOrigin(additionalTextureSize, additionalTextureSize);
outlineSprite.setPosition(sprite.getPosition());
// draw the sprite without the shader
window.draw(sprite);
// draw the outline with the blur shader
window.draw(outlineSprite, &blurShader);
window.display();
}
cout << endl << endl << "Press any key to end the program...";
_getch();
return EXIT_SUCCESS;
}
Short explanation:
I am trying to draw a sprite with a blured edge filter/shader ontop of it.
The code kinda works like this. However, I am planning on implementing such an effect into my engine and I have the feeling that I am doing a lot of unnecessary work here.
Oh, and before I forget (for completeness sake), here are the two shaders:
Outline shader:
uniform sampler2D texture;
uniform float edge_threshold;
void main()
{
const float offset = 1.0 / 128.0;
vec2 offx = vec2(offset, 0.0);
vec2 offy = vec2(0.0, offset);
vec4 hEdge = texture2D(texture, gl_TexCoord[0].xy - offy) * -2.0 +
texture2D(texture, gl_TexCoord[0].xy + offy) * 2.0 +
texture2D(texture, gl_TexCoord[0].xy - offx - offy) * -1.0 +
texture2D(texture, gl_TexCoord[0].xy - offx + offy) * 1.0 +
texture2D(texture, gl_TexCoord[0].xy + offx - offy) * -1.0 +
texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1.0;
vec4 vEdge = texture2D(texture, gl_TexCoord[0].xy - offx) * 2.0 +
texture2D(texture, gl_TexCoord[0].xy + offx) * -2.0 +
texture2D(texture, gl_TexCoord[0].xy - offx - offy) * 1.0 +
texture2D(texture, gl_TexCoord[0].xy - offx + offy) * -1.0 +
texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1.0 +
texture2D(texture, gl_TexCoord[0].xy + offx + offy) * -1.0;
vec3 result = sqrt(hEdge.rgb * hEdge.rgb + vEdge.rgb * vEdge.rgb);
float edge = length(result);
vec4 pixel = gl_Color * texture2D(texture, gl_TexCoord[0].xy);
if (edge > (edge_threshold * 8.0))
//pixel.rgb = vec3(0.0);
pixel.rgb = vec3(0.0, 0.89, 0.19);
else
pixel = vec4(0.0);
gl_FragColor = pixel;
}
Blur Shader:
#version 130
uniform sampler2D texture;
uniform float blur_radius;
void main()
{
vec2 offx = vec2(blur_radius, 0.0);
vec2 offy = vec2(0.0, blur_radius);
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy) * 4.0 +
texture2D(texture, gl_TexCoord[0].xy - offx) * 2.0 +
texture2D(texture, gl_TexCoord[0].xy + offx) * 2.0 +
texture2D(texture, gl_TexCoord[0].xy - offy) * 2.0 +
texture2D(texture, gl_TexCoord[0].xy + offy) * 2.0 +
texture2D(texture, gl_TexCoord[0].xy - offx - offy) * 1.0 +
texture2D(texture, gl_TexCoord[0].xy - offx + offy) * 1.0 +
texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1.0 +
texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1.0;
gl_FragColor = gl_Color * (pixel / 16.0);
}
Your help is very much appreciated,
Kind Regards,
Adrian