If love it, make it free (c) ;)
Trying to steal Vray's thunder.
Geomerics talked about the production of the Seastack Bay built with Unreal Engine 4 and Geomerics’ Enlighten in collaboration with Ninja Theory. Take a look at an amazing breakdown of world creation with dynamic global illumination from an ARM company.
The Seastack Bay showcase was built in Unreal Engine 4 with Enlighten for the PC and PS4. This was a collaborative project between Geomerics, an ARM company, and Ninja Theory, the developer of Hellblade, who provided environment, audio and character assets.
Seastack Bay is a diverse 25km² world with a view distance of 6km. Vertical structures rise to over 100m, significantly increasing the surface area of the level. We wanted to animate the time of day and weather so all aspects of the global illumination had to be dynamic. Achieving smooth lighting updates on our target platforms without losing believability in the lighting was the main challenge. Below we’ll describe how we achieved this.
Figure 1: Seastack Bay showcase in Unreal Engine 4 with Enlighten
Here is a scene lit with dynamic direct and ambient light without the lighting being reflected between the surfaces. Notice the lack of depth caused by the uniform brightness levels at both the top and bottom of the gorge. There is also a disjointed relationship between the colour in the shadow and the colour of the warm sunlight.
Figure 3: Gorge with global illumination. We get colour from the bounced sunlight and a light-to-dark graduation between top and bottom
Here’s the same scene lit with the indirect bounced light generated by Enlighten at runtime. With global illumination, the light is bounced from the patches of direct sunlight onto the cliffs opposite and gradually becomes darker towards the bottom of the gorge as its energy is absorbed. With a multiple bounce solution such as Enlighten, it is possible to light the entire gorge naturally from just a small patch of sun and skylight; we can reposition these lights or change their properties and see instant results – either in the game or as a part of our lighting workflow.
Enlighten can be used as a toolbox for achieving both lighting quality and lighting performance. When discussing lighting performance and the resources we want to dedicate to the indirect lighting we tend to talk about the Enlighten “update” time. For a smooth user experience, we need to strike a balance between lighting quality and the Enlighten update time. It is worth remembering that Enlighten runs on the CPU independently of the main rendering and game update. It will never block the frame rate.
The addendum has complete performance stats of Seastack Bay, for now let’s take a look at how we used Enlighten’s features to achieve good visual results with an update time of 22.8ms on PC and 67.1ms on PS4.
Figure 4: Debug visualisation of contribute lightmap and probe lit geometry
The lighting mode is how Enlighten applies the lighting to the geometry of the scene – this is defined by the content creator. The debug visualisation in figure 4 shows all Enlighten contributing geometry in orange and smaller scene details which will be probe-lit in green. In the Enlighten UE4 integration, choosing which assets are lit by which mode is a simple mark-up process where we tag either the instance of the static mesh actor in the level, or more commonly set a sensible default directly on the asset.
Figure 5: Large cliff geometry contributing to the indirect lighting calculation with the lightmap pixel size visualised
We need to make sensible choices about what Enlighten lighting mode, such as contribute lightmap or probe, we should use across the level and what resolution we should choose for our indirect lighting. The full precomputation is only performed on the relevant parts of the level – the user chooses what is relevant to the indirect lighting by setting the Enlighten lighting mode. For the Seastack Bay Showcase, we wanted to balance performance and quality and so we included only the large scale level features (figure 5) in the full indirect lighting computation. We then used Enlighten’s per pixel probe lighting to relight the smaller details (figure 4) to achieve a performant result without losing quality.
Figure 6: Lighting quality visualisation. Green geometry is that closest to the player and at a higher quality level. Purple is geometry in the background and at the lowest quality level. Orange is in-between.
We can define the Enlighten Quality Levels to fit the scale and performance of our asset. For Seastack Bay, we optimised the output pixel size (indirect lighting resolution) to balance quality and performance for our asset scale. The checker pattern shows the resolution of the indirect lighting on the precomputed geometry. We used 4m per pixel for geometry close to the player, which is a medium quality level. If we want higher fidelity or more performance, we can simply switch the relevant static mesh instance in the level – notice the mountains using the purple ‘background’ setting and parts of the level far from the player using the orange ‘low’ level.
Setting Lighting Mode and Lighting Quality are two very important steps which allow us to ensure that the indirect lighting is smooth. Keep in mind when setting these how quickly you want to move the lights in the scene. If the light is static, the CPU cost of the indirect lighting will be minimal. If we want to move lights quickly that affect a large part of the scene, then we need to allocate enough CPU budget for it to update smoothly. If it is a slow-moving day/night cycle this would fit within a smaller budget. It is worth emphasising that with Enlighten, you only pay for lights that move in the scene.
In Seastack Bay, we had a combination of slow moving lights for the day / night cycle and faster changing lights such as the player’s flashlight or forest fire. If we exceeded the Enlighten budget, we would notice the indirect lighting stuttering behind the main rendering of the game. To resolve this, we would need to reassess the quality and lighting mode settings, or increase the CPU budget.
Precomputed Light Transport
The next step is to run an offline computation of the large scale level architecture. For the Seastack Bay showcase which is 25km², this process took 40 minutes distributed over 10 nodes for all the contributing scene geometry.
Figure 7: The Enlighten precompute process distributed via Incredibuild
Figure 8: Enlighten lighting with white albedo material
In figure 8, we see the large scale features in the level that are important for blocking and transmitting the bounced lighting. It corresponds to the orange geometry in figure 5. If we change the shape or position of these meshes, we need to run the precompute again to see the correct lighting result.
Figure 8a: Detailed objects added
Here we’re adding the Enlighten lighting to the detailed green objects seen in figure 4. They are too small to significantly contribute to the precompute, but they will receive Enlighten indirect lighting and integrate seamlessly. We can place, delete or iterate on any parameter of these non-precomputed objects and see the final lighting result instantly. Enlighten integrates with existing shadowing techniques such as DFAO or SSAO. We are free to use these techniques to enhance the shadowing.
The Enlighten precompute process generates three outputs. Dynamic lightmaps are described above; we will talk next about spherical harmonic light probes and dynamic reflection capture cubemaps. Combined, these give us the ability to change any parameter of lights, transform all dynamic light types and tweak material colours.
Light probes are included in the light transport precompute. This technique is used to light dynamic geometry such as characters, vehicles or anything else that moves. It can also be used as an optimisation for static geometry.
Figure 9: Light probes – notice the increased density of probe samples close to the hut.
The user indicates areas of interest where moving objects will be present and the software will adaptively place probe sample points to ensure optimal performance.
Figure 10: Enlighten’s spherical harmonic probes
Cubemaps are important for achieving a correct material response with physically-based shading models. These are placed by the user in the level using the existing workflow in UE4 and Enlighten will update them in real-time using the precomputed data.
Figure 11: Reflection captures for updating the reflection of the lighting in real-time.
To keep the reflections looking consistent, we need to update them with the changing lighting conditions. Enlighten will capture the bounced lighting information from the precomputed geometry in real-time and reapply this to the scene’s materials according to their settings.
This allows us to produce dramatic lighting changes both on and off-screen while maintaining believable material reflections. The cubemap resolution in Seastack Bay of 32×32 pixels gave us optimal performance and worked well visually as most of the materials had a medium-high roughness value.
Figure 12: Seastack Bay showcase
We have shown how global illumination benefits a large exterior scene and have demonstrated how, by using Unreal Engine 4 with Enlighten, we can attain precise control over the quality and performance of the scene.
With the dynamic global illumination of the Seastack Bay showcase as an example, we have given an overview of the inputs required from the user, the precompute process and the outputs generated by Enlighten to be used by the runtime.
To learn more about light probe or dynamic reflection technology, visit Geomerics’ blog page.
Addendum: Seastack Bay performance statistics
- The integrator chooses the rate at which specific Enlighten outputs are updated – this can be less frequent for distant geometry. Our demo team generally updates Enlighten output data once per render frame, but this is a completely asynchronous task that can also be spread across multiple frames without impacting visual quality.
- The cost of an update depends on how much the lighting is changing.
- These stats are captured running on a single thread.
- 82 reflection captures with a resolution of 32×32 pixels for each face (16K total)
- 125K total probes, roughly one per 1m³.
- 300K total lightmap pixels, with a lightmap resolution of up to 4 pixels per m2
i7-4720HQ 2.6 GHz
40 minutes distributed (on 10 machines)
3 hours undistributed (on a single laptop)