Lighting is one of the most important visual elements of your game. Our partners at Arm have provided some handy tips to help you optimize your mobile game lighting.
When it comes to rendering a mobile game, lighting can be one of the biggest performance considerations. It is also one of the most important for completing a visual style. However, artistic goals and performance often find themselves at odds with each other.
Fortunately, there are ways to bridge the gap and work within the constraints of mobile hardware. Here, our partners at Arm, the world’s largest mobile chip design company, share some of their tips for lightning from their best practice guide.
Within Unity’s Built-in Render Pipeline you can choose between two render paths, Forward Rendering and Deferred Shading. In Forward Rendering, real-time lights are very expensive, but to clamp this cost you can choose how many lights should be rendered per pixel. Deferred Shading requires GPU support, but on enabled hardware it can render a large number of real-time lights and offer a high level of lighting fidelity.
While Deferred Shading is very attractive for light-intensive games for PC or console, it is not very performant on mobile GPUs. This is due to the lower bandwidth of mass market devices. When you’re making a mobile title, it’s important that it runs smoothly on as many devices as possible. To optimize your mobile lighting projects, we suggest you use the Universal Render Pipeline.
Unity’s Universal Render Pipeline, a prebuilt Scriptable Render Pipeline, is tuned for performance. Universal Render Pipeline by default is Forward Rendering and has a slew of features to help your app be as performant as it can be (you can read more about it here).
Regardless of platform, one of the biggest performance upgrades for rendering is to bake lighting into lightmaps and Light Probes. When you use real-time lights, features such as direct lighting and shadows need to be calculated uniquely for every frame that is rendered. Depending on the number of lights on screen, this can get computationally expensive. Performance budget will drastically limit how much content you can have on screen. To work around these limitations, many of the calculations can be precomputed offline in a process called “lightmap baking.”
Lightmap baking stores lighting and shadow information in textures, or “lightmaps.” This technique can capture computationally intensive lighting characteristics, such as bounced light and soft shadows, which can heighten realism. However, lightmaps have some limitations that are important to understand. Fully baked lighting cannot update in relation to dynamic elements of your Scene. Therefore, any dynamic objects will not be added to the lightmap. But not to worry: your dynamic objects have a pre-calculated solution as well, “Light Probes.”
Light Probes have a lot of the same benefits as lightmaps, in that they store lighting data that can be calculated offline. Much of the computational costs are incurred at edit time, rather than runtime. While a lightmap encodes lighting received at a given texel for surfaces in your Scene, a Light Probe stores the light that passes through empty space in your Scene. This data can then be used to light moving (dynamic) objects, which helps integrate them visually with lightmapped objects throughout your Scene.
A texel, texture element, is an individual pixel in a texture map. These texels are therefore the units that make up a lightmap and encode lighting information. Your control over texels can influence the quality of your lighting, computation time for the bake, disk storage costs, and the video RAM (VRAM) cost of your lightmaps.
When you are setting up your light bakes, you need to define the resolution of your lightmaps and specify the number of texels per unit. In this case, a unit is a definition of area in Unity’s default units (most frequently a meter). You can find the Lightmap Resolution property in Unity’s Lighting window. To view how texels are laid out in your Scene, either you can, in Scene view, click the first drop-down menu, which sets the Draw Mode, and check “Show Lightmap Resolution,” or you can click Lightmap Indices in the same menu.
Baked objects will now be covered in a checkerboard overlay. This is how your texels are distributed when you bake the lights. Below you can see an example of two different settings on the same cube. The left cube has a setting of 5 and the right of 2.5. The higher the variable, the more computation that will need to be done. The lower the resolution, the less lightmap space that is required and the fewer lightmaps needed. But keep in mind that the lower the resolution, the lower the quality will be as well. Experiment to find what will work best for your project.
Even with offline baking for most elements, you will probably want to include some real-time effects in your game, such as a character shadow. Real-time shadows are usually generated using a technique known as a “shadow map.” The cost of Scene geometry being rendered to the shadow map is proportional to the number of vertices drawn to it. So it’s important to limit the shadow-casting geometry, as well as the number of real-time shadow-casting lights.
To achieve a real-time effect you can place a small 3D mesh under the character and apply a blurry texture to it. This is a simple yet effective way to get a shadow without the potentially prohibitive cost of true shadow mapping.
Whether you are setting up lighting and baking it, helping to optimize your project, or just curious about game lighting, everyone has skills to contribute to making a game look amazing. Games are a unique showcase of interdisciplinary expertise. Share what you have learned about lighting with your team – it might just brighten up their day.