Search Unity

Lighting tips & tricks in the ADAM films

Are you curious about how Oats Studios created such high-fidelity sets, characters and costumes in real time for ADAM: The Mirror and ADAM: Episode 3? Read our in-depth, behind-the-scenes blog posts on lighting, Alembic support, clothing simulation, Timeline, shaders, real-time rendering and more.

My name is Jean-Philippe Leroux, and I am a senior technical artist specialized in lighting on the Made with Unity team. I have nearly 15 years of experience in lighting and spent 13 of those at Ubisoft Montreal where I dedicated many years to the lighting development of the Watch_Dogs brand. My role in the production of the ADAM shorts was as a technical advisor, supporting Oats Studios’ lighting artists who were intent on achieving some very impressive effects in real time.

Project background

The ADAM: The Mirror and ADAM: Episode 3 shorts were my first projects for Made with Unity. The production had already started when I began consulting with Oats Studio in July 2017. I enjoyed a smooth collaboration with the Oats team, including Youngbin Eun, Nathaniel Holroyd and Abhishek Joshi (lighting artists), Jim Spoto (Unity lead) and Chris Harvey (VFX supervisor). I worked remotely with them via Perforce until October and I also spent a week with them at their studio, the coolest “man cave” I’ve ever seen.

Setting the stage in ADAM: Lighting basics

Unity supports a large number of platforms, which also means there is a wide choice of lighting workflows. For a high-fidelity cinematic project like ADAM, some of Oats’ basic choices were quite obvious.

To start, Oats set Color Space to Linear. This is always the first thing I set up in a new project, as it’s actually essential for proper lighting calculations. The only reason you would not use this color space would be if your target platforms are lower-tier devices that can’t support it.

They set their Rendering Path to Deferred. Not only did this allow Oats to use some cool rendering techniques like screen-space reflections, it greatly simplified their lighting workflow by letting them use any number of lights, which is especially important for set lighting, since much of it has huge geometry.

For Tonemapping, Oats chose ACES from Unity’s Post-Processing Stack. ACES is the standard developed by the television and film industries as the common ground for all image sources. It provides an important natural-looking contrast that modern television thrives on, and it also correctly preserves the whites from clipping.

Since a big part of the ADAM films is “humanizing” the characters, proper tonemapping is a crucial step in the look development (the art of conveying emotion to a character through lighting, shaders, etc.). Additionally, tonemapping will actually define how you light and expose your shots. (Good news, the next Post-Processing Stack release will let you create your own tonemapping curve.)

A scene in ADAM: Episode 3 with and without tonemapping

The importance of Global Illumination (GI)

Without a doubt, Precomputed Realtime GI was a key choice for this project. It allowed Oats the proper light bounce since all their shots used dynamic lights for the characters and the sun position was also tweaked shot by shot. Together, the sun and dynamic lights gave them the indirect lighting input they were after.

(First, a bit of background. If you’re not that familiar with real-time GI and are considering using it for one of your own projects, I highly recommend that you invest a few hours going through this great tutorial: Introduction to Precomputed Realtime GI. This is a must-read for every artist or developer as it will help you produce really high quality lighting effects and save you many hours of iterations.)

Back to ADAM . . . One caveat of Unity’s real-time GI solution is that only directional light shadows are supported. All other light-source shadows are not considered in the calculation, so they pass through every object and wall. Because of that limitation, for example, we had to find a way to contain the GI created by the bright lights inside The Mirror’s room.
Oats employed a very simple trick to achieve this. They used emissive planes culled from the camera view that was contributing to the GI, without leaking light outside the room.

The disposition of camera-culled emissive planes in the room

Solving the dynamic GI issue with emissive planes in The Mirror’s room

A Perforce problem slows the team down temporarily

During development, a problem arose when Oats started pushing updated versions of the GI to their Perforce server: everyone on the team was losing the GI and receiving error messages. It turns out the default Perforce configuration caused an unexpected issue. While LightingData.asset are binary files, by default they were being treated as text files by the Perforce server, which corrupted them when they were integrated into the depot. To put production back on track, Oats corrected the configured filetype assigned to .asset and rebuilt the GI, making sure the files were submitted as binaries since they already existed in the depot as text files.

Handling new sun positions

Another issue Oats noticed was seeing pops every time the sun position changed. Oats designed their lighting per-camera shot, like they would on a normal film production. This meant that modifying the position of the sun, shot by shot, would require a full update of the Realtime GI solution. Unfortunately, even with Realtime GI CPU usage set to Unlimited, the update was not ready in time when the first frame of a new shot was drawn, making a noticeable pop at every sun position change. To compensate, Oats improvised a temporary solution: In a higher Timeline Director, we added, shot by shot, a two-frame buffer that wasn’t output by the Frame Recorder. Good news: Unity 2017.2 now handles this automatically using the DynamicGI.IsConverged command in the Frame Recorder.

Here you can see where we added two frames between cuts

Working with alembic caches

“Now that Unity’s added alembic support – it’s a super key bridge for us. We need it to be able to cache large geometry datasets.” – Chris Harvey, VFX Supervisor, Oats Studios
Alembic caches, which Oats used for their cloth and facial simulations, are effectively meshes. In ADAM, they sit at the origin of the world and they evaluate the GI probes as such. To ensure everything was handled properly, Oats simply set the “anchor override” renderer probe to the character’s pelvis. By doing so, the probes are properly evaluated based on the character’s position in the set, not by the pivot point of the cache. You can learn more about Alembic support in ADAM by reading Sean Low’s blog post.

Setting the Anchor Override

Employing Dynamic Decals

In the third ADAM episode, keep your eyes peeled for some cool graffiti, pebbles, dirt and other details. To add these, Oats pulled many goodies from the Dynamic Decals asset package. However, it didn’t initially work well when they introduced the real-time GI, because the decals didn’t get properly illuminated, appearing really dark in the shadows.
In deferred rendering, these effects are written to the buffer via the reflection pass before the GI is resolved. The problem occurred because we used the Skybox for the Environment light. If you use gradient or color, don’t worry – you won’t encounter this issue. Oats’ solution was to write its own ambient override for the Dynamic Decals and tweak the values until they matched as closely as possible, using a Lambert sphere and a custom DecalAmbient shader sphere.

Oats’ custom Decal Ambient Override vs a Lambert sphere

Getting the shadows right

As you probably know, shadows are hugely important when we talk about the quality of light. And, to be honest, it’s an area that hasn’t seen enough functional breakthroughs in the last decade. Nevertheless, ADAM’s lighting quality comes from a good understanding and mastering of the currently available techniques.
First, a little background: All lights should cast shadows and those should be fully opaque, but many developers use shadow transparency thinking it will fill the shadowed area, when in fact it breaks the lighting continuity because lighting is still directional and the back faces will remain dark. See below how once Oats used GI to fill shadowed areas, the need for shadow transparency was alleviated, giving excellent results.

Note the difference between shadow strengths of 0.8 and 1

Oats also really boosted the shadow quality using a simple modification to the spotlight shadow filtering. They pushed PCF filtering to 7×7 resolution by overriding the internal deferred shading. If you want to try this trick, note that it only works for spot: point light shadows don’t benefit from it.
Another Unity 2017.1 feature that Oats took advantage of was custom shadow resolution per light, which you can find on the Inspector debug tab. The resolution must be a power of two and is capped at 8k.
If you’re going to try this, be careful when using high-resolution shadow maps. Higher resolutions do not equal better quality. The higher you go, the crisper your shadow will be – but that is not what you normally want to achieve because it basically means going in the opposite direction of the high quality provided by area lights. Always remember that light quality equals soft shadow and wide specular. Here you can see the difference between shadow resolution and filtering at different settings in ADAM.

Getting shadow bias right

Setting the shadow bias properly was key for Oats. They wanted their shadows to be connected but without causing acne. In Unity, spotlight shadow bias is enmeshed with the clip plane value. To ensure a perfect connection, they needed to push it as close as possible to the subject. A good starting point for character lighting is around two units. Check out the effect below.

Setting cascades

Similarly, the cascade distribution settings of the directional lights had to be authored shot by shot, which Oats did using a Timeline custom track. As well, they tapped the SE Screen-Space Shadows package for some amazing shadow-quality enhancements. By pairing it with the Cascade Shadow Map (CSM), they got perfect contact shadows that the best bias settings in the world could not achieve.

A scene from ADAM with and without Screen-Space Shadows

Using Timeline for shot-by-shot lighting

Once the lighting lookdev was approved for a sequence, Oats broke it apart in Timeline, enabling them to easily do shot-by-shot adjustments. They basically duplicated the lookdev lighting rig for each shot and activated it via Timeline.
Since using the basic Switch Active track will overpopulate Timeline, Oats created a custom Switch Active Asset clip that allowed them to activate two groups of light per clip, all on the same track. That kept it clean and simple.

Oats’ custom Switch Active Asset setup

Organizing their lighting per shot let Oats do small adjustments without the risk of impacting any other shots. If you’re going to try this, I strongly recommend using a clean naming convention that follows your shot numbers and group ordering. This will make you more efficient and will greatly help others working with you, as Oats found.

Shot-by-shot breakdown of a lighting sequence in Timeline

You can learn more about Timeline in ADAM by reading Sean Low’s blog post.

Getting perfect control over punctual lights

Early in production, Oats expressed the need for better control over punctual lights. Specifically, they wanted more control over the falloff and the spread of the lights. John Parsaie, a Made with Unity software engineer, created an asset for them that takes advantage of the Cookie slot. As a bonus, this gave Oats curve control over both parameters and a smoothness clamp. The cool thing was that all the lights were still contributing to GI and reflections.

A custom script gave Oats better control over attenuation and falloff

Adding flickering lights

To achieve the dynamic, realistic look for ADAM’s fires and flares, Oats created a comprehensive script that provided light position, intensity, and hue modulation. This script really added to the fidelity of these combined visual effects. They attached it to an empty object and it propagates to all lights and FX children.

The result was also visible in the Scene view, which is always great when developing looks. We ran into a small glitch with this one though — it initially prevented the baking of cube maps and GI to complete. Once we realized that the script was causing the problem, we simply used another command to disable all the flickering in the scene at bake time.

Where there’s smoke, there’s fire

Burning up the night sky: The opening of The Mirror

When ADAM: The Mirror begins, a series of very impressive oil fires provide a lot of drama and tension in the scene. Will the prisoners succumb to the “heat” as they proceed through a deadly night-time landscape? Many people want to know how Oats accomplished this impressive effect. According to Stephen Cooney at Oats, they combined a number of cool industry tricks and did a lot of layering:We used animated texture atlases for most of the fire elements. We generated some in Houdini and we also used some stock Unity texture atlases. Fire was treated as “heat” in the texture and then remapped in the shader to any intensity and graded with a power curve.

We combined this with a tiling detail fire texture to add extra grit. After the final “heat” was calculated this was remapped between two colors (one for cool, one for hot). We used optical flow maps to smoothly blend between frames. This was useful for the large plume fire atlas that had only a few frames.The smaller fire comprised very long (but smaller resolution) texture atlases, while the plume component was a very low frame-count but high-resolution explosion (flow maps made this easy). We did the large plumes as a combination of the small ground-fire elements with the large plume puffs tacked on.

An explosion texture used for plume (red for heat, green for lighting) and its flowmap

We achieved a major part of the look by managing the visualization order manually. Also, since the fire was treated as “heat” and then remapped to actual values (with the detail texture on top), it made it much easier to get visually appealing levels of brightness. These play well with Unity’s Post-Processing System without the need to revisit the texture.Oats’ particle lighting system, which enables particles to look lit (useful for smoke), helped us tie the various particle systems together. Because the light could be animated, the smoke’s brightness would follow and the ground would take the same brightness.We also used this for the flare in order to “light” the smoke. Basically, it allowed our emissive particle systems to have a way to connect to the custom diffuse systems.

A dystopian campfire: ADAM prisoners listening to Needalus explain who they are

Final reflections

This project was a great introduction for me into the Made with Unity world as I collaborated with an accomplished team of lighting and graphics experts who were creating lifelike CG shorts in our off-the-shelf game engine. I think that over the course of the project, Oats proved that Unity has what it takes to deliver outstanding film-quality effects, while keeping iterations and costs down.
And we learned a lot too, seeing them constantly pushing VFX and storytelling boundaries and all the imagination and hard work that requires. I’ll let Abhishek Joshi, Oats’ CG supervisor have the last word:Lighting in real time in Unity was a huge leap for us creatively. Coming from offline raytraced renders, the speed and interactivity allowed us complete creative freedom and iteration speed unheard of with a non-real-time workflow. This is the future of creating animated content.

Learn more about Unity

Find out how Unity 2017 and its features like Timeline, Cinemachine, Post-Processing Stack, and real-time rendering at 30 FPS help teams like Oats Studios change the future of filmmaking.

As Unity is promoting itself as an awesome movie creation tool, It would be nice if they would actually include all these features and tools so they are accessible to all artists. If not, these articles just prove that you need resources of a large studio like Oats and do a lot of custom development to actually create something good looking – and this obviously is not accessible to many artists.
Yes, some of the stuff becomes open sourced, but it is usually half-finished (made for specific project) and not maintained – not working on later Unity versions.
Currently you need to buy a ton of third party scripts and effects and have a technical specialist to set it all up and provide constant tech support for artists, to achieve good looking picture. That’s the reason most artists I know still think that UE is far far superior – just because they can just open the engine and get good looking picture without much hustle. It seems like Unity is completely neglecting the visual side of the engine which is sad, because it is a great engine with huge potential.
To mention a few things missing – better shadows (point light shadow filtering, soft shadows), volumetric lighting, screen space shadows, more and better post processing effects, editor decals, more built in shaders – particle shading, shadows on alpha blended objects, artist friendly shader editor (Amplify Shader is good example), automatic light probe generation options, etc…

I agree with this. Although I wouldn’t go as far to say you need such tools to achieve a high-level standard for graphics, it also showcases how there’s so much need for custom visual tools in unity in order to get things right. While that is not an issue, I would rather see a focus on solutions that can be accessed or created by the community. These features are nice, but don’t give us too much info to work with. We have seen some good talks on lighting and GI – Why not use this project as a case of “here, based on what we’ve shown previously, X and Y work flawlessly for this kind of environment, while Z might have a better impact for outdoor scenes”. I love that you guys give some exposure to assets that have a nice impact on the quality, but I’d rather see it at the end of the post as a “Assets that also helped us achive our visual goal:” instead of showing it in the middle of the post.

Please do not take this as a negative comment. I look forward to see what the unity team is working on right now and I appreciate we have a lot of resources on our hands.

Thanks for your feedback, Gatis.
You’re right, a large team of experienced artists and technicians will always be able to achieve results that may be out of reach of other artists. However, keep in mind that Oats used Unity 2017.1 as the basis for their production. Because they had some big goals, they put in place the structure and other technology they needed to accomplish them (such as custom scripts), as mentioned in the article. Regarding third-party scripts, Oats only bought one lighting-related asset SE Screen-Space Shadows ($20) (https://www.assetstore.unity3d.com/en/#!/content/77836). Achieving the same lighting quality is already within the reach of any user.

And we are listening to users like you to help us with our roadmap(https://unity3d.com/unity/roadmap). That’s because Unity is dedicated to democratizing development (it’s one of our three pillars), so every release we provide more tools and capabilities to allow game, film and other creators to simplify their development and achieve their goals. Stay tuned for updates coming shortly in Unity 2018 such as workflow improvements for artists, more artist-friendly features, and a richer set of default settings to look good out-of-the-box.

+1 here, hope someday there will an option to enable (even if it is extensive) shadow calculation for bounced light propagation.
Btw, surprised that Oats didn’t use NGSS asset for fixing ugly point/spotlights state from “out of the shelf” Unity…

interesting post, but in order to be any helpful you have to go much more in depth:
what are: emissive planes culled from the camera view that was contributing to the GI?
and “Oats’ custom Decal Ambient Override vs a Lambert sphere” looks totally wrong.

Thanks, Laurent – that is exactly what it is. When you use a Mixed lighting solution for your GI, planes using a standard shader with an emission and color value > 1 will act nearly identical to Unity baked area lights. Those area lights do not work with real-time GI (Oats’ chosen solution), but emissive materials work just fine. Those planes have to be defined as static, meaning you can’t move, rotate or scale them, but you can animate their color and intensity.

Hi Iarsbertram. Please read Laurent’s comment below for more info on the use of emissive plane. As with the custom Decal Ambient Override, you can indeed easily spot the difference on both grey spheres as it was intended. The idea was to show you the real solution that was crafted and achieved by Oats. What I wanted readers to understand was that a solution does not have to be perfect, but credible in the context that it will be used. For any production, time is a very precious resource, so we have to spend it wisely. Crafting a “perfect” solution for certain projects will not give you any perceivable quality boost to the production.