Monday, August 15, 2011

Sun Lens Flare

this time i added sun lens flare effect, if you don't know what i'm talking about, just read about it here

or if you are lazy :) here is a picture shown this effect:

anyway, to create this effect, what you really need is few things:
1. couple of flare images
2. light position in 2d (screen space)

1. this is simple, just google on it, and you'll get some nice textures... (you can also use photoshop)
2. take you sun light position and project it into screen space, check z to make sure the light isn't behind the camera.
after you have this 2d pos, you need to create 2d direction vector pointed to the center of the screen, and place the flares from 1 in a different color/sizes along this vector.
that's it.
one thing to note is that flares do not disappear immediately when occluded, they basically stay visible and fade away very nice and smoothly (also when they become visible), thats because these flares created from a very bright light sources.
to achieve this kind of effect, what we really need is a way to count how much the light is occluded.
from this info we can compute a scale factor between [0..1] and scale the lens color so they fade in and out smoothy.
few options to use:

1. the simplest and naive way is to trace few rays from the light to camera eye and see how many of them passed and then compute scale factor from 0..1
pros: simple to implement.
cons: not accurate, can hurt performance.

2. texture masking, you render the scene from light point of view to small render target, lets say 16x16 (cleared to white), for every pixel passed you write black, at the end this texture will tell you how much the sun is occluded (the black pixels), to get the result from it, you can lock it out and count for the black/white pixels - not good idea, a better way is to render this texture into 1x1 render target (float point rt, and we will have to use 16x16 vertices for each pixel), we need to enable alpha blending to count the pixels. note that 1 in the 16x16 rt, could be counter for 256 times if all the texture is white (sun isn't occluded), but we need a value between 0..1 to scale the lens color with, so what we output from the ps, is the sampled pixel from the 16x16 rt scaled by 1.0/256.0 (16x16 = 256)
pros: better accuracy.
cons: not easy to implement, need hw float point rt, can hurt performace for big scenes.

3. use hardware occlusion query, just rendered some simple query mesh (quad,box,sphere) and count how many pixels passed, from this you can compute scale factor between 0..1
note that its a little tricky to use, you need a way to know the maximum pixels for the query mesh so you could compute the [0..1] scale factor, second, they can hurt your performance if isn't used right.
pros: very accurate, performance is very good if done right.
cons: need hw occlusion query support, can be tricky to do right.

here is a scren shot to show you the effect in action:

no lens effect

with lens effect

in my implementation i use option 3...
that's it for now, cya until next time ;)