Pages

22/02/2013

Pseudo Lens Flare

Lens flare is a photographic artefact, caused by various
interactions between a lens and the light passing through it. Although it is an
artefact, there are a number of motives for simulating lens flare for use in
computer graphics:

it increases
the perceived brightness and the apparent dynamic range of an image

lens
flare is ubiquitous in photography, hence its absence in a computer generated
images can be conspicuous

it can
play an important stylistic or dramatic role, or work as part of the gameplay
mechanics for video games (think of glare blinding the player)

it
looks reeeeeally cool

For real time lens flares, sprite-based techniques have
traditionally been the most common approach. Although sprites produce easily
controllable and largely realistic results, they have to be placed explicitly
and require occlusion data to be displayed correctly.
Here I'll describe a simple and relatively cheap screen
space process which produces a "pseudo" lens flare from an input
colour buffer. It is not physically based, so errs somewhat from photorealism,
but can be used as an addition to (or enhancement of) traditional sprite-based
effects.

Algorithm

The approach consists of 4 stages:

Downsample/threshold.

Generate
lens flare features.

Blur.

Upscale/blend
with original image.

1. Downsample/Threshold

Downsampling is key to reducing the cost of
subsequent stages. Additionally, we want to select a subset of the brightest
pixels in the source image to participate in the lens flare. Using a scale/bias
provides a flexible way to achieve this:

Adjusting the scale/bias is the main way to
tweak the effect; the best settings will be dependant on the dynamic range of
the input as well as how subtle you want the result to look. Because of the
approximate nature of this technique, subtle is probably better.

2. Feature Generation

Lens flare features tend to pivot around the
image centre. To mimic this, we can just flip the result of the previous stage
horizontally/vertically. This is easily done at the feature generation stage by
flipping the texture coordinates:

vec2 texcoord = -vTexcoords + vec2(1.0);

Doing this isn't strictly necessary; the rest of
the feature generation works perfectly well with or without it. However, the
result of flipping the texture coordinates helps to visually separate the lens
flare effect from the source image.

GHOSTS

"Ghosts" are the repetitious blobs which mirror
bright spots in the input, pivoting around the image centre. The approach I've
take to generate these is to get a
vector from the current pixel to the centre of the screen, then take a number
of samples along this vector.

The weight function is about as simple as it gets - a linear falloff. The reason we perform the weighting inside the sampling loop is so that bright spots in the centre of the input image can 'cast' ghosts to the edges, but bright spots at the edges can't cast ghosts to the centre.

A final improvement can be made by modulating the ghost colour radially according to a 1D texture:

This is applied after the ghost sampling loop so as to affect the final ghost colour:

CHROMATIC DISTORTION
Some lens flares exhibit chromatic distortion, caused by the varying refraction of different wavelengths of light. We can simulate this by creating a texture lookup function which fetches the red, green and blue channels separately at slightly different offsets along the sampling vector:

Although this is simple it does cost 3x as many texture fetches, although they should all be cache-friendly unless you set uDistortion to some huge value.

That's it for feature generation. Here's the result:

3. Blur

Without applying a blur, the lens flare features (in particular, the ghosts) tend to retain the appearance of the source image. By applying a blur to the lens flare features we attenuate high frequencies and in doing so reduce the coherence with the input image, which helps to sell the effect.

4. Upscale/Blend

So now we have our lens flare features, nicely blurred. How do we combine this with the original source image? There are a couple of important considerations to make regarding the overall rendering pipeline:

Any post process motion blur or depth of field effect must be applied prior to combining the lens flare, so that the lens flare features don't participate in those effects. Technically the lens flare features would exhibit some motion blur, however it's incompatible with post process motion techniques. As a compromise, you could implement the lens flare using an accumulation buffer.

The lens flare should be applied before any tonemapping operation. This makes physical sense, as tonemapping simulates the reaction of the film/CMOS to the incoming light, of which the lens flare is a constituent part.

With this in mind, there are a couple of things we can do at this stage to improve the result:

LENS DIRT

The first is to modulate the lens flare features by a full-resolution "dirt" texture (as used heavily in Battlefield 3):

The key to this is the lens dirt texture itself. If the contrast is low, the shapes of the lens flare features tend to dominate the result. As the contrast increases, the lens flare features are subdued, giving a different aesthetic appearance, as well as hiding a few of the imperfections.

DIFFRACTION STARBURST

As a further enhancement, we can use a starburst texture in addition to the lens dirt:

As a static texture, the starburst doesn't look very good. We can, however, provide a transformation matrix to the shader which allows us to spin/warp it per frame and produce the dynamic effect we want:

13 comments:

Great work, Keep it up Mr Chapman. My rendering engine is coming along but im reaching the point where ill need a good bit of help and advice. If i could send you another mail about somethings that would be great, Ill also send a copy of my code over. Your camera movement and materials are awesome. :)

I wasn't quite able to reproduce the full effect, but I was able to convert it to a "glare" effect in minecraft. Only around 70 lines and is very light on my GPU. Here is a screenshot.http://imgur.com/ua2XuZlOne good part about it is that its not only limited to the sun/moon, It appears on bright objects (usually would take messing with lightmaps). Thanks for making this.