|See what's going on with flipcode!|
Question submitted by (06 December 1999)
|Return to The Archives|
I have been looking at how lens flare is done in many of the demos
and games. For an example check the Image Of The Day 26/11/1999. I
notice that what seems to me to be a quick and dirty method is used.
Even when the light source is obscured by an object the lens flare is
still rendered. I have tried to think of a way to make this more
realistic and come up with the following:
The best way would be to use some form of ray to shoot between the camera (screen) and the light source. If the ray intersects anything before the light then the lens flare is not drawn. I have not tried this but I guess that the cost of doing ray intersections on all objects would be (way) too high. This led me to the z-buffer. When the image is complete the z-buffer should contain the distance to the nearest object along the 'ray'. A quick check between the z-buffer value and the calculated z distance to the light source should show whether the light is visible and hence determine if lens flare should be drawn. This should be a relatively simple check and I expect that this would make the lens flare more believable.
My question is, has this been tried? I have seen many articles that suggest that it is bad to query the video card/driver for any information due to graphics pipelines. Would the performance hit be more trouble than the visual gain is worth?
In Fly!, we used a set of rays cast in the direction of the sun. The
percentage of rays occluded would determine the percentage of opacity for
the flares. I believe we ended up using only nine rays when the product
was shipped, and the results were fine. We used ray intersections because
we already had a solid code-base that we could pull from to perform the
By using rays, we were also able to trace through cloud layers, get the opacity at that point in the cloud, and dim the lense flare by that amount. This way, as the sun would pass behind semi-opaque cloud layers, the flare would act appropriately. A very subtle effect, but worthwhile.
Checking the z-buffer for such a small screen-space area would probably work very well, provided you didn't need this extra functionality. The performance hit of reading back the z-buffer for such a small area should be minimal. However, I'm told that some hardware won't allow reading back from the z-buffer, since there might not be a bus for such information to travel over (in some console units, for example.)
As a side-note, if you ever watch a [live action] movie, you'll notice that the lense flare doesn't stop at the edge of the frame. In the real-world (i.e. the useless space that surrounds all computers :) as long as the light source can see the lense a flare can be visible, even if the light is not "in frame." The flare doesn't actually disappear until the housing of the physical camera casts a shadow onto the lense. Something you might want to consider if you want that extra bit of realism.
Also, lense flares are only noticable with lights that are in sharp contrast to the rest of the scene. A flashlight in a very dark room would cause a lense flare, but that same flashlight in a lit room would not. Many people seem to think that, since lense flares "look so cool" that they should have a strong impact on the scene. This causes over-use of a great realism enhancement (i.e. a bright lense flare from the flame of a candle.)
It is this graphics programmer's opinion that subtlty is paramount to realism.
Response provided by Paul Nettle
This article was originally an entry in flipCode's Fountain of Knowledge, an open Question and Answer column that no longer exists.