Last active
December 7, 2018 23:57
-
-
Save Oxore/ce70426a973e30824ab6839dff75f283 to your computer and use it in GitHub Desktop.
CSFML multi-pass blur shader example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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