Screen-Space Global Illumination Filter v1.5

Adds a bounce of light. No occlusion but that might change in the future.

Leave a comment here and credit me if you use it in your game.


I would put a blend file up for download but i am too lazy, instead i will link to this video that explains how to add 2d filters to your game.

Here is the filter itself:


NOTE: Much of this code was taken from Martinsh’s deferred shading filter, and later improved upon by TheLumcoin and myself.


-fixed gamma correction
-slight performance improvements (replaced some float divides for multiplication by a precomputed constant)
-Changed distance falloff to a nicer looking ( and maybe more performant ) formula
-pushed samples into a loop.
-various other improvements.
-cleaned up the code.
-added distance falloff.
-Fixed color detection.
-Improved angular falloff a bit.
-Implemented hemispherical emission.
-Fixed angular falloff.
-First Release.

Currently implementing hemispherical emission:

Also, i completely fixed the angle falloff (you can see it on the image), it is now exactly the way it should be. I’ll update the script once i’m done implementing the hemispherical emission.

EDIT: for some reason it works well when i take just one sample but it breaks when i iterate through the whole image. Also, any ideas on how to feather the edge of the hemispherical emission? This is how i am doing it at the moment:

float hemiEmit = clamp(round(dot(lightDir,emissionNormal) + 0.5), 0, 1);

yeah i know, not very fancy

EDIT2:I felt like posting another image:

this should theoretically allow screen space geometry based lighting in the BGE!

EDIT3: Here is the reason for hemispherical emission: better edge definition

You can clearly see the edge between the back wall and the floor
(The weird artifact on the edges is what i mean by “it breaks”, it also makes some darker pixels appear all over the screen every once in a while)

OK. Progress was made.

The image above only uses 16 samples per pixel. Amazing huh? also, light is only being bounced in the direction that the face from wich the light bounces is facing, wich is how it works in real life (this is that hemispherical emission thing i was talking about earlier).

However, every sample is empirically written on the script, because looping through doesn’t seem to work and returns a glitchy and awful image.

    final += lightSample(vec2(0.2,0.2),canCoord);
    final += lightSample(vec2(0.4,0.2),canCoord);
    final += lightSample(vec2(0.6,0.2),canCoord);
    final += lightSample(vec2(0.8,0.2),canCoord);
    final += lightSample(vec2(0.2,0.4),canCoord);
    final += lightSample(vec2(0.4,0.4),canCoord);
    final += lightSample(vec2(0.6,0.4),canCoord);
    final += lightSample(vec2(0.8,0.4),canCoord);
    final += lightSample(vec2(0.2,0.6),canCoord);
    final += lightSample(vec2(0.4,0.6),canCoord);
    final += lightSample(vec2(0.6,0.6),canCoord);
    final += lightSample(vec2(0.8,0.6),canCoord);
    final += lightSample(vec2(0.2,0.8),canCoord);
    final += lightSample(vec2(0.4,0.8),canCoord);
    final += lightSample(vec2(0.6,0.8),canCoord);
    final += lightSample(vec2(0.8,0.8),canCoord);

Yeah. not ideal, but it is the only way i can get it to work properly so it’ll have to do, at least until i manage to fix it.

And because i have implemented a hemispherical direction to the samples, emissive planes can now be simulated by setting a material to be emissive wich is something i’ve wanted for a very long time.

This image is also using 16 samples per pixel.

Latest Script available at thread start.

Martins has already done a SSGI shader (doesn’t look very good to me). Maybe his resources can help you.

I tried to take a look at it but sadly the file he linked to is no longer available however, i could totally use the article he linked to.
Thanks for the reference!

EDIT: I just looked at the article and it absolutely NOT what i’m trying to do with mine, the article shows a color bleeding filter, while mine is a more physically correct VPL-ish aproach (wich looks a lot more accurate at the expense of a lot more performance)

Tested the new version: pic ->
But, when moving the cam its flickering.

I guessed that would happen, it’s just a matter of increasing the amount of samples, but that would make it run super slow on any computer… i’ll see if i can modify this to use rendertotexture and do operations on a downsampled version of the rendered image wich should allow to use more samples with a way smaller hit to performance… Thanks for the screenshot and for the feedback!

EDIT: If i use rendertotexture i might even be able to do a clustering protocol to further optimize the sampling process…

Nice, thanks for the shader, though I haven’t gotten it to work correctly yet, need more testing

btw why is this not a nested loop?

indirect += lightSample(vec2(0.2,0.2),canCoord);
indirect += lightSample......

I’m not sure but maybe something like this?

for (int i = 1; i < 5; i++){
    for (int j = 1; j < 5; j++){
        indirect += lightSample(vec2(j*0.2,i*0.2),canCoord);

looks awesome so far! great work! :smiley:

Sometimes you need to unrool the loops to obtain the max performance…

Ive made a comparison: pic ->
left bf bge 2.78a, right upbge master build.
If anyone wants to test the file, link:

Thank you! I watched some of your tutorials haha.

It just doesn’t work properly but i don’t know why. Here is an image that explains what i mean:

@lordloki76, SebastianMestre
thanks, now I see, I’ve only read branching is costly for gpu parallelism, didn’t even know that loop can become an issue, good to know

filter not working

Thank you, it has been fixed.

I’ve been toying with this for the last few hours and figured i should add something to it, so here is an update.

It includes some optimization, clean ups to the code and distance based falloff.


EDIT: i also went crazy and decided that the default amount of samples should be 81, instead of 16.

EDIT2: link to the filter on post #1

Hey I checked out your filter and it looks great for scenes where the camera and most of the geometry is static. As soon as the camera moves the flickering starts to happen, which is why I won’t be able to use this filter in my game project.

I know increasing the samples should help with fixing it, but that will drain too much performance for it to be really useful. I hope you’re still working on this, maybe you can find a way to optimize it :smiley:

average the samples across frames* (this will prevent flickering I think)

1 Like

I can think of a few ways to improve this (temporal interpolation would be one of them) but i don’t know enough about blender to implement those improvements.

I stopped active development of this a while back, but that doesn’t mean i won’t update it if i come up with some substantial improvements

Samples = [list of samples] 
If "ColorSampleList"  not in own:
    own['ColorSampleList'] = [Samples] 
    for i in range(len(own['ColorSampleList'])):
         own['colorSampleList'] [i] = (own['colorSampleList'] [i] + Samples[i]) /2


This averages over 1 frame

You can do

own[‘colorSampleList’] [i] = ( (own[‘colorSampleList’] [i]*31) + Samples[i]) /32

To average over 32 frames