• entries
  • comments
  • views

HDRI + shadowing + cities

Sign in to follow this  


Today, two new videos for the price of one !


I have finally implemented automatic exposure by downsampling the scene recursively until i get a 1x1 pixel that contains the scene luminance. I have two implementations: a simple average, and Reinhard's operator. The first one is fast and looks pretty good. The second one is supposedly more accurate, but requires more pixel shader instructions, and at the moment its advantages are not clear compared to a simple average. Needs more experimentation.

Once the scene luminance is stored in a 1x1 texture, i interpolate this texture with the "current" luminance. This makes the luminosity adapt over a short period of time ( currently set at one second ), rather than being instantaneous. If you go in a dark area and quickly look at the sky, everything glows. It's magic !

Speaking of glows, i am now downsampling and blurring the scene multiple times ( previously, i was doing it only once, meaning the pixels range the bloom could affect was limited ). Doesn't cost too much performance. I'm also performing the blur in a standard, fixed point RGBA 8 bits texture, instead of using a FP16 buffer. It's faster, and i can make use of bilinear filtering to have an even better blur. The downside is that the values are clamped to [0-1], but it's possible to work around this "problem" by playing with the parameters.

On Shadows:

In one of my previous journal entries ( 6 months ago ? ) i was speaking of assigning a shadow map for each object. I dropped this technique in favor of cascaded shadow maps. It seems like cascaded shadow maps offer the best performance/quality trade off. At the moment, i'm using 2 levels of shadow maps ( each 2048^2 ), but i'm planning to add more once everything feels "right".

In order to get good transitions between the two shadow maps, i had to implement.. orthographic projections. Previously, i was using a perspective frustum with an apex set very far away ( to reduce the distortions due to perspective ) and a very big near clipping plane distance. Because there was two different shadow maps each with their own frustum, the perspective distortion prevented the shadows of one map from matching with the other one. Disturbing.

Now, with orthographic frustums, everything is good. I spent my whole week end on this implementation, mostly lost in debugging, since i forgot the fact that my matrices were setup in the DirectX way rather than the OpenGL way ( which i'm using for rendering ). Of course, checking the ortho projection matrix and comparing it to the one built in OpenGL, i did not find any difference.. except that it was expecting the ortho matrix the way it's built in DirectX. Ah Ah.

The two shadow maps are centered on the camera and are moving with it. It causes the shadows to flicker. I fixed that by transforming the shadow maps origin into object space, round this position to the shadow map texel size, and transform it back to world space. No more flickering. Except when the light itself moves, but there's nothing i can really do to help.

Shadow maps ( actually, the closest level only ) are antialiased - not really "soft" shadows, but the effect is cool. On NVidia cards, it's very nice, thanks to hardware PCF. On ATI cards it's less nice, even sampling the shadow map 8 times. The performance hit is... important.

I still have to improve shadows in the future. One thing i want to try is to store the shadow maps in an "atlas" texture, a single 2048^2 that will contain 4 1024^2 shadow maps. Four levels of shadow maps, even at half the resolution, might look better than what i currently have on two levels. It should also allow me to antialias all the levels. It should be lighter on memory and performance, since there's no need to render to 4 separate textures; only adjust some texture coordinates in a shader to write to or read from a specific quarter area, and it's done. Or, at least, i hope so..

Shadow maps are not updated every frame, but only every 4 or 8 frames ( respectively, for the two levels of shadow maps i currently have ). The largest shadow map is just enough to cover the whole city ( see video ).

On LOD ( level-of-detail ):

I spent a few days improving the current metrics. Nothing really important to say, it's very technical and mostly related to debugging and understanding why, sometimes, some silhouette edges are moved.

New videos:

Disclaimer: keep in mind this is a work in progress. Yes, it's not perfect. There are tons of little problems, parameters to adjust. Things will improve over time. And keep in mind it's yet another "tech" demo: even if it looks nice, it's far, extremely far from being more than a rendering prototype.

City video ( 45.8 MB, Divx5 ) : showing off the city and a few models. Stannum's buildings, Shawn's city dome ( a draft - yeah, textures are really deformed, it will be fixed. Same for the "metallic grid" on the roof ), CutterJohn's Intrepid, and 100 Shadix/Petrov interceptor's loaded ( to have any idea of the slowdown due to traffic ). Also shows HDRI and dynamic shadows.

Spuk's outpost : showing off the small station made by Spuk. Generic textures, no skybox/background, it's a bit plain, but it shows HDRI + dynamic shadows. Interior not shown due to backface culling problems in the model.

Mandatory screenshots:

Sign in to follow this  


Recommended Comments

Nice idea with clamping the shadow maps to pixel boundries in object space, i'll have to give that a go myself.

Everything looks as awesome as always.


Share this comment

Link to comment
Amazing work, as always. Do you have any problems with visual artifacts with that lattice pattern on the dome of your space city? I'd check the video but I try not to download too much on my uni. computer.

Plus are those yellow craft space taxis?

Share this comment

Link to comment
Hey Yann,

Very nice indeed :)
I'm at the stage at where i have a 1x1 texture that contains the luminace of the scene., do you mind explaining how do you interpolate this value with the value of the current luminance ?


Share this comment

Link to comment

After searchig the web couldnt find any good paper about "cascaded shadow maps" you are using in your engine. If its possible, could you please give us a link for a paper on this method.

Thank you in advance,

Share this comment

Link to comment
Original post by BrunoI'm at the stage at where i have a 1x1 texture that contains the luminace of the scene., do you mind explaining how do you interpolate this value with the value of the current luminance ?

Dead simple:

newLum = oldLum + (curLum - oldLum) * factor;

Factor is the speed at which the luminance varies, values around one second feel good. I read some papers that are more "physically" accurate and try to model the fact that eyes adapt more quickly to brightness than to darkness, but it's going a bit too far for a game IMO.

Original post by MaverickDQAfter searchig the web couldnt find any good paper about "cascaded shadow maps" you are using in your engine. If its possible, could you please give us a link for a paper on this method.

I don't know any paper about it, a similar technique is parallel-split shadow maps ( http://hax.fi/asko/PSSM.html ). As for cascaded shadow maps, they're quite simple to implement if you have basic shadow mapping. Instead of having only one shadow map, you:

- create N shadow maps
- for each frame, center each shadow map on the camera. Each shadow frustum has increasing sizes (so, shadow map #1 covers an area of 10mx10m, shadow map #2 an area of 100mx100m, shadow map #3 an area of 1000mx1000m, etc.. you'll have to figure out which dimensions work best for you).
- render the scene to each shadow map (so for N=3, you'll render the scene 3 times. Keep in mind that unlike perspective/light space shadow maps or similar techniques, you are not forced to re-render the shadow maps every frame, you can "cache" the shadow maps for a couple of frames).
- at render time, in a vertex shader, for each shadow map, project back the vertex onto each shadow map and output each result into a tex coord set.
- in a pixel shader, sample the N shadow maps and perform the depth comparison. Then, calculate the distance between the pixel and the camera in world space. Generate a blend factor for each shadow map transition depending on this distance. Blend all the shadows together according to those factors.

Share this comment

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now