How do I implement a simple 2D torch effect on screen with GLSL with SFML

Started by
1 comment, last by haegarr 9 years, 10 months ago

Hello there gamedev community smile.png

At the moment i'm creating a basic 2D game with the help of SFML and good old C++. Now if you look at the image attached below, the left part is what I have so far, but the right side is something i would like to implement, now I know the image on the right is just a simple radial fill rectangle with the middle part transparent and the edges not transparent.

I'm trying to achieve a basic darkness around the edges of the screen and brightness at the centre (like a torch effect in a dungeon crawler). I feel like the openGL shader would be the best option for this, but I have to admit my skills with C++ and SFML are good enough to create this game, but my openGL shader knowledge is basically non-existent, I just wanted to ask first off, is a shader the best option for this? Second, if yes, could you provide some shader code or some information on where I can learn openGL shaders, Third, if no, could you provide why a shader would not be the best idea and how I should achieve this effect.

The effect is something similar to this, but of course my game is only in 2D not 3D and the torch would flicker.vYljM.jpg

Advertisement

If I understand it right, you basically want a circular overlay on your screen, as in the bottom-right screenshot?

The simplest way, without needing any shaders, is to draw your circle (or whatever mask) in a image, draw a screen-filling quad on top of the rest, and apply multiply-blending. White pixels on this image will keep the background color unchanged, darker colors will darken the background pixels.

In case you want to animate a bit (a toch flickers), you can gently try to shit this screen filling quad a bit the to the left/right/up/down, and/or multiply the quad texture color with another color that pulsates (with a sinus or something). So far, still no shaders are needed really. Nevertheless, it might be a good lesson to achieve this same effect with a shader, as you get a bit more control on things like color multiplication, shifting, or eventually mixing 2 different textures to achieve an animation.

If it is done image based (i.e. the geometry is ignored) and with a undisturbed shape, then it is like the Vignette effect.

I've once implemented Vignette as a post-processing effect based on GLSL 1.20 as follows below. The implementation assumes that the scene is rendered into a texture (offscreen render target), and that the effect is applied by mapping the texture onto a fullscreen quad to the framebuffer, as usual.


#version 120

// post-processing head structure
uniform struct Post {
  sampler2DRect _0;
} post;

// post-processing effect #1: Vignette
uniform struct Vignette {
  vec4 _0; // .xy: center of effect in pixels; .zw: normalization factor
  vec3 _1; // .x: interior radius; .y: exterior radius; .z: dimming [0,1]
};
Vignette post_1 = Vignette(vec4(960,600,600,600),vec3(1.5,2.0,0.5));

// varying inputs
varying vec2 v0; // tex-coord of fullscreen rectangle

// program
void main(){
  // getting the original color
  vec4 col=texture2DRect(post._0,v0);
  // calculating the relative distance from the window center
  vec2 pos=(gl_FragCoord.xy-post_1._0.xy)/post_1._0.zw;
  float temp=length(pos);
  // calculating the shade
  temp=1.0-smoothstep(post_1._1.x,post_1._1.y,temp);
  // mixing the original and the shaded color, preserving alpha
  col.rgb=mix(col.rgb,col.rgb*temp,post_1._1.z);
  // outputting color
  gl_FragColor=col;
}

If you look at the given initialization of post_1, you'll see the center of the effect set to (960,600) which means the center of the screen if its size is 1920 by 1200 pixels. You'll further see the scaling set to 600 by 600 which generates a circle effect (different scale values for x and y will generate an elliptic effect). The interior radius (1.5 in the example) and the exterior radius (2.0 in the example) work as follows: All inside the interior radius is copied unchanged to the output; all outside the exterior radius is dimmed by the dim factor (0.5 in the example); in-between the inner and the outer radius a smooth transition is generated.

This topic is closed to new replies.

Advertisement