Skip to content

Instantly share code, notes, and snippets.

@Oxore
Last active December 7, 2018 23:57
Show Gist options
  • Save Oxore/ce70426a973e30824ab6839dff75f283 to your computer and use it in GitHub Desktop.
Save Oxore/ce70426a973e30824ab6839dff75f283 to your computer and use it in GitHub Desktop.
CSFML multi-pass blur shader example
/*
* Compile with:
* gcc -oblur blur.c -lcsfml-graphics
*
* XXX #1:
* How to use shaders in CSFML:
* - https://en.sfml-dev.org/forums/index.php?topic=9767.0
*
* XXX #2:
* Gaussian Blur with link inside a thread to a book about SFML:
* - https://en.sfml-dev.org/forums/index.php?topic=20155.0
*
* XXX #3:
* "The texture coordinates are inverted because the texture produced by
* sf::RenderTexture is inverted (because of FBO).":
* - https://en.sfml-dev.org/forums/index.php?topic=11178.0
*
* */
#include <SFML/Graphics/RenderWindow.h>
#include <SFML/Graphics/RenderTexture.h>
#include <SFML/Graphics/VertexArray.h>
#include <SFML/Graphics/Shader.h>
#include <SFML/Graphics/Sprite.h>
#include <SFML/Graphics/Texture.h>
#include <stdlib.h>
#define UIBGCOLOR (sfColor){26, 26, 26, 255}
char *fragshader = " \
uniform sampler2D source; \
uniform vec2 offsetFactor; \
\
void main() \
{ \
vec2 textureCoordinates = gl_TexCoord[0].xy; \
vec4 color = vec4(0.0); \
color += texture2D(source, textureCoordinates - 4.0 * offsetFactor) * 0.0162162162; \
color += texture2D(source, textureCoordinates - 3.0 * offsetFactor) * 0.0540540541; \
color += texture2D(source, textureCoordinates - 2.0 * offsetFactor) * 0.1216216216; \
color += texture2D(source, textureCoordinates - offsetFactor) * 0.1945945946; \
color += texture2D(source, textureCoordinates) * 0.2270270270; \
color += texture2D(source, textureCoordinates + offsetFactor) * 0.1945945946; \
color += texture2D(source, textureCoordinates + 2.0 * offsetFactor) * 0.1216216216; \
color += texture2D(source, textureCoordinates + 3.0 * offsetFactor) * 0.0540540541; \
color += texture2D(source, textureCoordinates + 4.0 * offsetFactor) * 0.0162162162; \
gl_FragColor = color; \
} \
";
sfRenderWindow *window;
sfVertexArray *vertices;
sfRenderStates states;
sfRenderTexture *render_tex;
sfShader *shader;
sfTexture *texture;
sfSprite *sprite;
static void handleWindowEvents()
{
sfEvent event;
while (sfRenderWindow_pollEvent(window, &event))
if (event.type == sfEvtClosed)
sfRenderWindow_close(window);
}
void main_loop()
{
sfRenderWindow_clear(window, UIBGCOLOR);
sfShader_setTextureParameter(shader, "source", texture);
sfShader_setVector2Parameter(shader, "offsetFactor", (sfVector2f){0.f, 1.f/300.f});
sfRenderTexture_drawVertexArray(render_tex, vertices, &states);
sfRenderTexture_display(render_tex);
const sfTexture *tex1 = sfRenderTexture_getTexture(render_tex);
sfShader_setTextureParameter(shader, "source", tex1);
sfShader_setVector2Parameter(shader, "offsetFactor", (sfVector2f){1.f/300.f, 0.f});
sfRenderTexture_drawVertexArray(render_tex, vertices, &states);
sfRenderTexture_display(render_tex);
const sfTexture *tex2 = sfRenderTexture_getTexture(render_tex);
sfSprite_setTexture(sprite, tex2, sfTrue);
sfRenderWindow_drawSprite(window, sprite, NULL);
sfRenderWindow_display(window);
}
int main()
{
sfVideoMode mode = (sfVideoMode){300, 300, 32};
window = sfRenderWindow_create(mode, "CSFML Blur Shader",
sfResize | sfClose, NULL);
if (!window)
exit(EXIT_FAILURE);
sfRenderWindow_setFramerateLimit(window, 60);
// XXX #3: .texCoords `y` coord is inverted relatively to .position `y` coord
sfVertex vert0 = {
.position = (sfVector2f){0, 0},
.texCoords = (sfVector2f){0, 1}
};
sfVertex vert1 = {
.position = (sfVector2f){300, 0},
.texCoords = (sfVector2f){1, 1}
};
sfVertex vert2 = {
.position = (sfVector2f){0, 300},
.texCoords = (sfVector2f){0, 0}
};
sfVertex vert3 = {
.position = (sfVector2f){300, 300},
.texCoords = (sfVector2f){1, 0}
};
vertices = sfVertexArray_create();
sfVertexArray_append(vertices, vert0);
sfVertexArray_append(vertices, vert1);
sfVertexArray_append(vertices, vert2);
sfVertexArray_append(vertices, vert3);
sfVertexArray_setPrimitiveType(vertices, sfTrianglesStrip);
shader = sfShader_createFromMemory(NULL, NULL, fragshader);
states = (sfRenderStates){
.shader = shader,
.blendMode = sfBlendAlpha,
.transform = sfTransform_Identity,
.texture = NULL,
};
render_tex = sfRenderTexture_create(300, 300, sfFalse);
sfIntRect area = (sfIntRect){0, 0, 300, 300};
texture = sfTexture_createFromFile("./image.png", &area);
sprite = sfSprite_create();
// XXX #3: needs to be flipped upside down
sfSprite_setScale(sprite, (sfVector2f){1.f, -1.f});
sfSprite_setOrigin(sprite, (sfVector2f){0.f, 300.f});
while (sfRenderWindow_isOpen(window)) {
handleWindowEvents();
main_loop();
}
sfRenderTexture_destroy(render_tex);
sfTexture_destroy(texture);
sfSprite_destroy(sprite);
sfRenderWindow_destroy(window);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment