/gml-shadow-light-effect

A project demonstrating theatre-esque light & shadow effect using GLSL, For Gamemaker Studio.

Primary LanguageGLSL

Theatre-esque light & shadow shader effect

(Couldn't find a better word for this :/)

yes

Technical stuff

yes
This is the source image (overlaid on top of the checkerboard BG), We're going to use this to generate light, shadow and composite buffer.

yes
We feed the source buffer into the shader to render the light buffer.

We first fill the whole buffer with black, So that we can just apply an additive blending mode when constructing the composite buffer.
Then using the distance from the center of screen, We can generate a radial gradient.
We generate two versions of radial gradient : One with "hard" and small radius for foreground, Other one with "smooth" and large radius for background.
Notice how the opaque part / foreground gets more light than a background part, We're basically mixing between two gradients with input buffer's alpha like this :

// mix both so only foreground part (aka the parts with alpha) gets foreground lighting and same goes for background
gl_FragColor = mix(lightBG, lightFG, texture2D( gm_BaseTexture, v_vTexcoord ).a);

yes
Almost same thing happens with shadow buffer.
We're using the distance from the screen's center to apply a vignette effect..
Also, We're applying a blur effect to make the parts close to the screen's edge blurry.
But here's the twist : we're using a technique called "dithering" to compensate the artifact generated from using lesser texture samples.

yes
Blur effect shader can be quite expensive if you sample the texture too much. But if you don't sample the texture too much, It will get "chunky" like the picture above...

yes
That's why we're using the dithering to make the result smooth. Using a noise texture, We can offset the sampling uv coordinates with a random noise value.. Using that, We can get improved blur effect with lesser texture sampling; That means we can save those precious FPS!

yes
Using those buffers, We can finally construct the composite image by rendering a shadow buffer on background with multiplicative blend mode, And drawing a source buffer on top of it, Then rendering a light buffer with additive blending mode.
Following snippet of code renders a composite image :

// draw shadow buffer with multiplicative blend mode
draw_set_blend_mode_ext(bm_zero, bm_src_colour);
draw_surface(surfShadow, 0, 0);

// draw source buffer with normal blending
draw_set_blend_mode(bm_normal);
draw_surface(surfSrc, 0, 0);

// draw light buffer with additive blend mode
draw_set_blend_mode_ext(bm_one, bm_one);
draw_surface(surfLight, 0, 0);

// reset blend mode
draw_set_blend_mode(bm_normal);