⏲ Approximate time: 4+ hours | ⚙ Level: Beginner
Improving the Lighting in your worlds
Welcome to the World Lighting tutorial!
The goal here is to improve the lighting in your worlds and make them more visually appealing. In addition to that, we will also show you how to make them more performant from a lighting point of view to meet the framerate requirements for virtual reality.
We will also be showing performance measurements in our tutorial, for context these were taken on a Ryzen 7 5800x with an RTX 3080.
There are no Prerequisites or Files required for this tutorial.
Preface
Assessing our world
The first thing we have to do before messing with any lighting is to assess our world and determine what kind of lighting it will need.
For lighting in general we have roughly the following styles to choose from.
- Realtime Lighting: Where scene lighting is calculated for every frame that is rendered. This is best for dynamic worlds that are always changing, but this is also the most expensive render.
- Baked Lighting: Where lighting is precalculated into textures beforehand. This is best for static worlds that don't change, and is also the cheapest to render.
- Mixed Lighting: Is a combination of both Realtime and Baked lighting. Useful for getting the best of both worlds.
The reason this is important, is that different worlds will need different styles of lighting depending on how interactive they are. Very interactive worlds will need a different lighting style than ones are mostly static with little interaction. Each of these lighting styles have their own advantages and drawbacks, so it's important to go with one that best suits our world and will lead to the best performance.
In our instance, we have a shopping world where you go around the shop picking up some items that the player can get. Beyond that there won't be alot of other interactions. There also won't be any day or night cycles, so the lighting of the world will stay consistent the entire time.
With that said, that means that our enviorment will be primarly static. So the style of lighting that we will choose for this world based on our prior description will be Baked Lighting (Where lighting is baked to textures as the enviorment and it's lighting will not change).
So with the lighting style in mind, we will also look around our world to figure out how we can light it artistically.
We'll take into consideration the way we have our shop is modeled, where there are large windows in the front of the store that can let in a lot of natural light from the outside. We can use that to our advantage to light the store in broad daylight.
To summarize, these are the main points for our world to keep in mind...
- Completely Static Environment.
- A few small interactable items.
- Large open windows for natural lighting.
Now before we can move on, we will first go over some lighting limitations we may run into before we begin to light the world.
Lighting Limitations
Now our world currently has existing lighting. However, there are a lot of issues with it...
Currently, there are over several shadow casting point lights in the scene. These lights are all in real-time, and in-action is causing a lot of performance slowdown. Since it's also real-time, it means the lights are recalculated for every frame that is rendered.
By using the Unity Profiler tool we can see how many milliseconds are spent in the rendering of the scene.
The rendering phase on the CPU is taking roughly 14 ms
(Roughly 60 fps). However, the framerate target for virtual reality is 90 fps (10 ms - 11 ms)
. We are 30 fps under the target.
The reason this is important especially in virtual reality, is that framerates below the target are known to induce negative side effects like motion sickness or disorientation. We want to ensure a very comfortable experience for the user, so the performance has to hit the target for virtual reality.
As a quick test, we can disable all of the lights in the scene and see how the performance of the world improves.
The rendering phase on the CPU now takes only 4 ms
(Roughly 250 fps) with no lights in the scene.
One limitation of Forward Rendering here is important to note. Notice in the image how the seats and column displays are receiving point lighting, but the floor and walls are not. As a result they look disconnected from the environment. When moving around in the scene, lights can pop in and out of existence as Unity tries to decide which lights on the object have per pixel priority.
Forward Rendering has a limitation to where it can only render a certain amount of per-pixel lights per object. In the Massive Loop client this value is set to 4 Lights. When the number of lights interacting with an object goes beyond this limit, they are then rendered with a less precise but faster method.
Per-pixel lighting means that light is shaded per pixel, and each light is shaded in a single pass. When you have 4 Lights shading an object, that means there are 4 Lighting passes for an object. This can grow in complexity when there are many objects in the scene interacting with lights that require multiple passes. This is why when there are a large number of lights and objects in a scene, the performance can decrease dramatically as we saw previously.
If real-time lighting was a design choice for our world, a solution to solve the light popping issue can be to split up the walls and floors into multiple objects so they can receive per-pixel lighting. To save performance as well also we can have zones within our world where we disable lights that the player does not see.
However, in this case, since our environment will primarily be static, and we are choosing to stick with baked lighting there is no need to have any realtime lights because the world and it's lighting won't change.
With the design points of our world set and the lighting limitations acknowledged, we can now start lighting our world...
Lighting Our World
1. Setting our Enviormental Lighting
We have removed all lights in our scene, and as shown in the image, the world is only lit with ambient lighting.
Yet, there is an issue with it because the ambient lighting is incredibly flat and bright.
There is no visual depth information in the scene. Meaning we can't distinguish the direction of lights, and objects have constant flat shading making them blend together.
Referencing our inital goals for the world, we want to light the scene in broad daylight and emulate natural lighting. In real-world outdoor lighting the biggest contributions are the sky, and the sun. Since we will add the sun in a bit we will start with the sky.
So to start lets make sure the scene is lit from the sky rather than an arbitrary flat constant color.
We can fix this by adjusting our environmental lighting settings in the Lighting window.
For ambient lighting, Unity provides 3 modes...
- Color - The ambient lighting term of the scene is a single constant color.
- Gradient - The ambient lighting term of the scene is made up of 3 different colors. A ground color (which comes from below), an equator color (which comes from the sides), and a sky color (which comes from above).
- Skybox - The ambient lighting term is dictated by the skybox of the scene.
Currently, the ambient source of the scene is set to Color
. To match the design goals of lighting the scene in broad daylight we want to change it to the skybox.
This means now that the ambient term of the scene will be dictated by the Skybox, which is physically correct, and matches our design goal.
For our sky, we are using the default Unity sky shader.
Other shaders can also be used as a Skybox, whether they are completely dynamic or static.
Upon making this change, we can see an immediate improvement to our scene...
The ambient shading of the scene now matches that of the sky.
In addition to that, because the sky is not a constant color, we have variance in how the ambient term of the scene is shaded.
There are different colors and values depending on the angle of objects. Giving us more visual depth cues compared to the Color
ambient lighting, where everything blended together.
With our environmental lighting now set correctly, we will move on to adding sunlight.