About Me

Hi. I'm Josh Ols. Lead Graphics Developer for RUST LTD.


View Joshua Ols's profile on LinkedIn


Entries in RSRMs (7)


Realizations and Revisions


Having a learned a great deal more about shading since I wrote this post, the contents are now out of date. Please disregard them.


I came to a few realizations as of recently, that will affect the lighting direction I will pursue for my project.

Deferred shading:

After much debate on the merits of different approaches, I have decided to go with a more traditional form of deferred shading, using a g-buffer setup similar the one Starcraft 2 is using. So it will look something like this:

  1. (RGB) Light Accumulation, (A) unused
  2. (RGB) Normals, (A) Depth
  3. (RGB) Albedo,  (A) unused 
  4. (RGB) Specular Color, (A) Specular Power

This decision was motivated by the need for color accuracy, and compatibility across multiple PC configurations. Color accuracy requires that I have linear blending for lights, particle effects, etc. Unfortunately, sRGB blending behavior is inconsistent between DX9 & DX10 hardware, so I can't rely on it. So I am forced to do it myself using higher-precision fp16 targets to store linear colors.

Lighting Approach:

After having downloaded and played the demo of Brutal Legend, I was able to learn a lot more about their lighting scheme. 

Rim Lighting:

I had mistakenly believed that they were using the sky gradient maps to provide ambient lighting as well as reflections. As it turned out, they are using a form of rimlighting instead.

It was only recently that I began to see just how powerful a tool rimlighting can be. Originally, I thought it was only good for cartoony graphics, ala Super Mario Galaxy. However, I have observed that it is being used extensively in games like Final Fantasy 13, and Soul Calibur IV.

I will have to explore the possibilities offered by rim-lighting, since my initial observations have shown that it can be used to make a variety of material effects.


Their technique is called "Radially Symmetric Reflection Maps". I discovered that my earlier observations weren't entirely correct, as I saw it on normal-mapped surfaces in the demo. Apparently it only looked bad in my case because my test surface was completely flat, and pointing straight up. Also, the fact that the look-up texture will only be used for reflections means that I can just use the trick where I draw a dark line across the bottom to provide a "horizon" in the reflection.


Final thoughts:

So, that's where things are right now. I'm still trying to figure out a scheme for how to port my existing code-base to using GLSL shaders. Chances are good that I will use a fair number of macros and type-definitions to reuse my Cg shader code as best I can. My demo code is not about specific APIs, so I am trying to abstract things in a way that will hide the underlying details, whether they be DX9, DX10, or OpenGL.


Skylights & Global Illumination


I've recently found out just how wrong this article really was when I learned about Image-Based Lighting and Physically-based BRDFs. So if you want to see the correct implementation, please refer to my new RSRM blog post.



You really don't appreciate the difference it makes in lighting until you take a look at any of the idTech 4 games, and see just how bad Lambertian + Constant Ambient really looks. Problem is, proper global illumination is a tricky business. Seems like there is no one perfect solution that won't cost an arm and a leg to get quality results. So you can imagine how this has caused me much frustration in my own project.


Approaches I've considered:

  • Hemisphere Lighting
  • Irradiance volumes 
  • Spherical Harmonic Light Mapping (SHLM)
  • Screen-Aligned Irradiance Volumes
  • Skylights 
  • Dynamic Radiosity <several techniques>

My requirements:

  • Dynamic illumination
  • Influenced by surface normals
  • Cheap to calculate offline and at runtime
  • Low storage offline and at runtime
  • Works in most situations, both indoors and outdoors
  • Works over great distances

After much deliberation and experimentation, I settled on Skylights. While not ideal, they meet enough of my criteria to make them a good choice. Also, the fact that the game Brütal Legend uses them to great effect made me see how they could be viable in a real game. :)



This was where things got a little tricky. There didn't seem to be a whole lot of resources on the web about how to implement a system like this. There were a few on how to implement a dynamic skydome, but that was about it.

Having read several articles off the web, I derived a system that employed a 2D lookup texture which held gradients for altitudes, and time of day. From this I cobbled together something that employed bits from hemisphere lighting to look-up values in the texture. This provided enough for diffuse lighting, and glossy specular.

A proper metallic reflection took a bit longer, as it was clear that it would need a separate function that behaved very differently. This proved to be more difficult, and caused me to have limited success for several months. That was until I stumbled onto the article Dynamic Sky & Rain Effect. This helped me fill in most of the missing pieces to get some nice reflections, and a crude skybox (need to switch to skysphere).

Sky diffuse (sharp) Sky glossy (sharp) Sky reflection


Figure 1. 1, Sky diffuse lighting; 2, Sky glossy lighting; 3, Sky reflection; 4, skymap



Firstly, it seems that metallic reflections only look good with smooth geometry. As you can see from the third picture, they don't seem to like normal maps. This means that I can't have bumpy reflections, which is less than ideal, but not a deal-breaker.

Secondly, getting a nice horizon in metallic reflections required me to draw a dark line across the bottom of my gradient texture. While this worked for metallic reflections, it had the side effect of causing a black void in diffuse and glossy reflections. Since it would be too much of pain to produce two maps for every skylight, I'm guessing I will need to come up with some more complex function that darkens values below the horizon. That way, the burden of fixing this problem doesn't fall on an artist.


That's all I have to report right now. I'll keep everyone posted on future developments. ;)

Page 1 2