Global illumination – Improving outdoor lighting

I came across some nice articles on this site which have inspired me to try to improve the lighting in my game.

Recently I implemented a “primitive” form of global illumination for the game (I say “primitive”, because while there are surely more advanced techniques out there, it is still far from being simple).

I basically measure reflected sunlight (one bounce) off of objects and add the effects of this to my ambient lighting term. Most of the work happens offline:

  • For every point in a world grid, render the scene in all 6 directions with sunlight only, and place these in a cube map
  • Integrate the cube map with spherical harmonic basis functions
  • Store the spherical harmonic constants in a texture where each texel corresponds to a point in the world grid (currently 1024×1024). I’m assuming a 2.5D world here (so there is just one layer).

For debugging purposes, I can show the generated cube map, the cube map applied to a sphere, and the spherical harmonic constants applied to a sphere (which should approximate the low frequency color variations in the cube map). In the below image, you can see the sphere gets lit by green light reflected off the mossy cliff, and below a bit from the blue water:


Cube map and results of applying it to a sphere (rendered roughly from where the sphere is located)

Cube map and results of applying it to a sphere (rendered roughly from where the sphere is located)


At runtime, using the textures that contain the SH constants, I add this term to the ambient light based of the normal of the pixel being rendered. I also scale this by the inverse of the current cloudiness (since it is supposed to represent reflected sunlight).

My plan (not yet fully-implemented), was to render these offline cube maps at 8 different times during the day. Then we would use a blend of the two adjacent (in time of day) snapshots. I got this idea from the GDC 2014 presentation “Assassin’s Creed 4: Black Flag – Road to next-gen graphics“.

Of course, 9 RGB spherical harmonic terms requires 27 bytes to store. If I only use the first 4 SH terms (taking a reduction in quality), then that’s still 12 bytes. At 1024 x 1024, that’s 12MB. Multiplied by 8 times of day, that’s 96MB just for the textures to store the reflected sunlight approximation. As for performance, it adds 6 texture samples to my ambient lighting equation. Offline performance is slow too – I only calculate 20×20 regions on demand right now for testing, but based on the time that takes, it would take about 7 hours to render for the entire map.

I could minimize memory usage by only placing probes in important areas and constructing the textures at runtime based on the nearest probes. But that would be a lot more work.

I suppose this would be worth it if it produced clearly superior results. But the resulting effect is quite subtle:



The lower half of the image has the global illumination effect applied. The bright sunlight reflecting off the right-hand cliff gives some extra illumination to the shadowed cliff on the left.


Overall, the effect is quite subtle for my mostly-outdoor world. It is worth all the effort? It also does nothing to help the case when it’s cloudy and there is no direct sunlight (since this is supposed to represent reflected sunlight). As a result, things are very dull and muddled in that scenario:




Now back to some of the interesting and inspiring articles I found.

There is one about outdoor lighting that appears to produce nice results. And there is one about multi-resolution ambient occlusion.

The latter article has some really nice images, and describes techniques which are actually similar to stuff I already have (which helps validate my hacks).

Although I don’t currently use the medium frequency occlusion (standard SSAO) because it’s quite expensive, I do have things that are similar to the high and low frequency occlusion.

For many of my objects, I have ambient occlusion terms baked into the geometry (this is the high frequency occlusion). It’s most noticeable in my plants, and improves the look greatly:




You’ll also note the dark area below the plant and near the base of the brick wall. This would be similar to what the article describes as low frequency occlusion. Basically, large objects cause things to be darker below them. Currently, my implementation is specific to terrain – certain objects (tree and walls) add to a ambient occlusion term baked into the terrain. The article describes a more general approach I could use.

So I’ll be looking at some of these techniques to improve my lighting. The first thing I’ll do though is to adjust the albedos of my textures. I think a lot of them are out of whack with each other, making things look not very realistic.

Hopefully I’ll get to a point where I can produce clearly better results, and provide some before-and-after screenshots.



6 comments on “Global illumination – Improving outdoor lighting

  1. […] my last post I talked a bit about some cheapish global illumination I was trying out. I noted how it was a very […]

  2. […] A couple of posts ago I mentioned I would try my hand at implementing some more general purpose low frequency ambient occlusion. The article here suggests a blurry overhead shadowmap to darken areas under trees and such. With this as inspiration, I came up with a technique I’m fairly pleased with. […]

  3. […] It’s important to note that this is not directional though. The cylinder in the middle is a mix of green and magenta even though from this angle it would be greenish in the real world. For a directional solution we could use spherical harmonics. I describe my experience with that here. […]

  4. Hi, I’m new into 3D graphics and i’m wondering about one little thing.
    To generate an HDR cubemap, do I need to create separate depth and normal buffers (cubemaps)? Thanks in advance.

  5. I spent *AGES* implementing AO for my voxel engine, and can’t help but notice that your AO here only affects objects below others. AO is meant to approximate the blocking/reflecting of light between two objects, meaning it should also shade the bottom of the wall (and similar in the plant, though I don’t know if it’s worth figuring that out).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

Just another WordPress site

Just another WordPress.com site

Harebrained Schemes

Developer's blog for IceFall Games

kosmonaut's blog

3d GFX and more


Turn up the rez!

bitsquid: development blog

Developer's blog for IceFall Games

Game Development by Sean

Developer's blog for IceFall Games

Lost Garden

Developer's blog for IceFall Games


Developer's blog for IceFall Games

Casey Muratori's Blog

Developer's blog for IceFall Games


Developer's blog for IceFall Games

Rendering Evolution

Developer's blog for IceFall Games

Simon schreibt.

Developer's blog for IceFall Games

Dev & Techno-phage

Do Computers Dream of Electric Developper?

- Woolfe -

Developer's blog for IceFall Games

Fabio Ferrara

Game Developer

Clone of Duty: Stonehenge

First Person Shooter coming soon to the XBOX 360

Low Tide Productions

Games and other artsy stuff...


Just another WordPress.com site

Sipty's Writing

Take a look inside the mind of a game developer.

%d bloggers like this: