Monday, August 15, 2011

Sun Lens Flare



hi
this time i added sun lens flare effect, if you don't know what i'm talking about, just read about it here
http://en.wikipedia.org/wiki/Lens_flare

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 ;)

7 comments:

Mau78 said...

Hi Oren,

I'm following your blog from a long time but this is my first post. I'm developing an engine too and I've recently added the Fracture (We use Havok, and we've used some Havok utility funct).

I'm wondering if you've found some solution on creating the new texture verticies for broken pieces.
If you want contact me in pvt.

Best Regards

orenk2k said...

Hi

i'm using havok too, my old fractures used internal code that i wrote and its works very nice, the problems is the the fractures tend to be kind of perfect because of the plane cuts, anyway, few monthes ago i created new fractures model to get more natural fractures, the problem in havok utils is that you don't get enough info to generate the uv from the "cuts" so the solution i use is the same one used before, i'm generating the uv's after the "cuts" is done...
i think i will post on it next time or such, so stay tuned...
cya ;)

Mau78 said...

Hi Oren I work all day on this subject; for glass and concrete material (that usually uses tilable textures) I found a solution which look not bad. I retexture the new verticies with a "spherical" map.

Problem is for meshes that mapped with complex UV maps.
I'm thinking about a solution (maybe try to reassign the original mesh UV in someway???? I'll see)


So if I understand correctly now you're not using Havok utils for fracture the meshes right?

Regards

orenk2k said...

hi
well, before i didn't used havok helper functions for the cutting process (fractures gen), now i use them but not i'm not using havok destruction kit...
keep in mind the if you are going to map the uv from the original mesh uv, you need some kind of vertex fit or something like maya transfer attributes and it should run fast enough, even so, you will also have to find solution to map internal vertices that wasn't exist in the original mesh at all (assigned to internal fractures contained in the mesh)
cya

Mau78 said...

Hi Oren I'm not using Havok Destruction too :-)
I'm only using "Havok Fracture" utils...

"...you need some kind of vertex fit or something like maya transfer attributes and it should run fast enough, even so, you will also have to find solution to map internal vertices that wasn't exist in the original mesh at all..."

I was thinking the same...any link or reference to some papers about the topic??

Regards

orenk2k said...

hi
sorry no links, but i saw something on old gdmag issue, can't remember which one...

Mau78 said...

This is a very useful hint ^_^
I got gdmag subscription...I will check articles...

Thank you!