LWRP 4.0.0-preview is out
Upgrading to this version requires Unity 2018.3.0b3.
This version changes the light attenuation computation to be physically based. This change means that you don’t have to increase the range of your light to control the attenuation. Instead, you should control the attenuation with the light intensity. Baked GI has changed to match the realtime attenuation. When you upgrade to LWRP 4.0.0-preview, it is likely that you have to upgrade your light settings as well.
We are pushing work to have LWRP out of preview as soon as possible. Therefore for this version, we focused most of our time in API design to implement much feedback we received over the past months and evolve both our C# and shader API to be more easy to use, extensible and flexible.
This version introduces API breaking changes. Breaking changes are the reason we bumped the major version number. If you didn’t fork LWRP or authored custom shaders without using ShaderGraph, upgrading your shaders to this version requires some work. We apologize for the nuisance, but this is required so we can evolve. Once out of preview, there won’t be any more breaking changes.
Please check the changelog to help you upgrade shaders to version 4.0.0-preview and reach out in this thread with upgrading issues so we can help you.
If you authored custom shaders, please make sure you update the shader variants in your shader to match the new ones.
// -------------------------------------
// Lightweight Render Pipeline keywords
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile _ _SHADOWS_SOFT
#pragma multi_compile _ _MIXED_LIGHTING_SUBTRACTIVE
These multi_compile keywords are stripped from the build depending on:
-
Settings in the LWRP asset that is assigned when you build your project, f.ex, if you disable Additional Lights in the asset, LWRP strips all related variants from the build.
-
LWRP strips invalid variant combinations. f.ex _MAIN_LIGHT_SHADOWS_CASCADE defined but not _MAIN_LIGHT_SHADOWS are invalid and therefore stripped
-
Unused passes. If you select in the asset you don’t support shadows then all shadow caster passes are stripped from the build. Same with meta pass that is only used for baking lightmaps.
I’ve updated the LWRP Physically Based shader example to 4.0.0-preview. You can use that as well to help you upgrade your shaders.
State of the Docs
Lack of documentation was one of the significant feedbacks we received, and we are putting much effort into writing them. We will layout them in phases soon. Meanwhile, use this post as a reference.
The LWRP Forward Renderer
LWRP cull lights per-object, and they are all shaded in a single pass. Compared to Built-in forward renderer, LWRP shades multiple lights with less overdraw and less draw calls.
LWRP (on the left) renders GI and all realtime lights in the same pass. Light attenuation is physically based. Built-in render pipeline (on the right) renders GI and a directional light in a base pass. Each additional light is rendered with an additional pass additively. Attenuation is not physically based and is affected by both light intensity and range. The image difference is purely because of the light attenuation difference.
Below are a couple of shots from Angry Bots 2 comparing Built-in render pipeline and LWRP. This shot was taken in package 3.3.0-preview when light attenuation was the same so they are pretty close to each other. This scene has a shadow-casting directional light + 2 point light and 2 shadow-casting spot lights.
Compared to Built-in, LWRP renders that specific frame with about half as many draw calls.
If you are unsure of what Batches and SetPass calls mean in that image, check this guide.
This is how LWRP shades a scene. It chooses the brightest directional light as the Main Light. This light is shaded outside the light loop in the shader and it has a dedicated set of shader variables/shading path in order to shade it as fast as possible. This makes possible to scale rendering up for multiple lights without adding shading overhead to games supporting a single directional light.
Shading of additional lights happens in a loop. We want to avoid branching on light-type, and we cannot classify them in a forward renderer. We perform a generic shading function that works for directional, point and spot light types.
There’s a current issue with Graphics Emulation that prevents LWRP to store a large amount of lighting data efficiently. This issue limits the number of lights LWRP can shade. There is currently a limit of 1 main light + 4 additional lights per-object. Also, if you have more than 16 lights visible by the camera, LWRP omits some of them. Once we fix the Graphics Emulation issue, these limits will only impact GLES2.0 and GLES3.0
We have also updated the LWRP asset to make it more clear and easily configurable. It’s very important to check the settings in the LWRP asset because it controls quality and passes in your rendering. Configure the asset to support only the least features your game requires for better performance.
What about other rendering approaches?
It’s on our roadmap to support a mobile-friendly deferred renderer based on this approach. Currently, if you want to use a different shading strategy than standard forward rendering you can override the LWRP render pipeline to do so.
We provide ScriptableRenderPass class that you can use to create custom-render passes and inject that in LWRP. There are two ways of injecting custom render passes in LWRP. You can inject them at specific points in the default renderer. Take a look at the LWRP default renderer to see some injection points. Boat Attack uses that to render special water effects. Alternatively, you can completely override the LWRP renderer by implementing your own IRendererSetup. A renderer setup is a script that can be attached to a camera and it executes all ScriptableRenderPasses registered in it. You can use this to implement a Forward+ renderer with compute in LWRP for instance.
VR and Lightweight Render Pipeline
There are currently some issues with MSAA and PostProcessing in VR. There’s also a current issue with Daydream devices. Although they support multi-view, Google blacklisted multi-view on these devices due to driver issues. There was no other strategy to fall back in SRP because Multi View is deprecated. The effect is that they render black.
We added single pass double wide as the fallback to SRP in 2019.1, and we might backport it to 2018.3.
Built-in Shaders
All unlit shaders from built-in render pipeline work with LWRP. Because the lighting strategy is different, the built-in lit shaders don’t work with LWRP. We provide a new set of lit shader with LWRP. These shaders are distributed along with the LWRP package. When LWRP package is installed you can see them by going in Unity to your project window under the folder Packages/Lightweight RP/Shaders or you can check them in Github. LWRP provides Lit, SimpleLit, and Unlit shaders that cover most of the Unity built-in render pipeline shaders.
We provide a Material Upgrader utility that upgrades Built-in shader to LWRP. It’s in the Unity toolbar at Edit → Render Pipeline → Upgrade project materials to Lightweight RP materials.
Custom Shaders
If you are writing custom shaders we recommend using our new Core RP shader library. This is a modern library written in hlsl. LWRP further extends the Core SRP shader library with additional functions specific for it. You get the Core RP and LWRP shader libraries installed on your computer when you install these packages. They can be located in Packages/Core RP Library/ShaderLibrary and Packages/Lightweight RP/ShaderLibrary. Alternatively you can also check their source in Github: CoreRP, LWRP
The most important things when writing custom shaders are:
-
Make sure you add the multi_compile pragmas as in this shader example. If you want to remove some of them because of shader compiler variants you can disable settings in the pipeline asset instead and the keywords will be stripped.
-
Include “Packages/com.unity.render-pipelines.lightweight/Core.hlsl” in all your shaders. This will include shader variables and most utility functions you need. Think of it as legacy UnityCG.cginc.
-
If you are doing lit shaders include “Packages.com.unity.render-pipelines.lightweight/Lighting.hlsl”. This will include, GI, Lighting, IBL and shadow functions.
-
Material shader properties are not defined in Core shader library or LWRP shader library. This means _Color, _MainTex, _MainTex_ST, and all variables in the Properties section of a shader must be defined by the shader itself. If you define all those properties in a CBUFFER names UnityPerMaterial, SRP can cache the material properties between frames and reduce significantly the cost of each draw call. Each of LWRP shaders define theirs constants in a *Input.hlsl. You can check LitInput.hlsl for an example.
-
Invest some time learning the new shader library. Docs are not done yet but all the source code is there. You can check LWRP shaders for reference.
All built-in shader variables described in this page except Lighting variables work with LWRP.
Don’t reference LWRP lighting shader variables in your shader. Instead we provide two functions to initialize a Light struct that has all lighting information you need for shading a light. These are GetMainLight, and GetAdditionalLight and they are defined in Lighting.hlsl
Light struct is defined as follow:
struct Light
{
half3 direction;
half3 color;
half distanceAttenuation;
half shadowAttenuation;
};
If you have any feedback on the shader API we would be glad to know. This is the chance to help shape the API to better suit your usage. We want to provide an easy to use and flexible API.
Performance
We are benchmarking LWRP and Built-in on several mobile devices and a few test projects. The process very slow given the amount of architecture fragmentation for platforms we support. Optimizing for a GLES2 capable device is completely different work than doing for a Vulkan one, and yet more different than PC and consoles.
We just found out that there was a performance regression on some android devices between 2.X and 3.X. We are yet about to re-run our tests in 4.X version.
We want to make sure to fix this performance regression before sharing a detailed data with benchmarking. Overall, compared to built-in you should expect at this point:
-
PC, Consoles, Mobile (Vulkan and Metal), and VR
-
Slightly better performance with a single directional light.
-
Considerable better performance with multiple lights. We are investigating some issues with performance on some devices next week.
-
Mobile (GLES3+)
-
About same performance with a single directional light.
-
Some devices have better and some worse performance. We are investigating this issue as well and figuring out perf regressions.
-
Mobile (GLES2)
-
About same performance with a single directional light
-
Worse performance issues depending on the scene with multiple lights. GLES2 enforce support in their specs for dynamic indexing in pixel shaders. Most mobile GPU manufacturers support it though. We are working with them to figure out which GPUs we can patch our shaders to support dynamic indexing. This is more likely to only land in 19.1. So, if you are in GLES2 and LWRP it’s ideal to fallback to either single directional light or shading additional lights per-vertex.
The matrix of different architectures and different games rendering styles makes it really hard to cover all performance cases. It’s extremely important to have your help in this. If you are using LWRP and have worse performance compared to built-in render pipeline, please open a bug report with your test scene, LWRP version and the device you tested. We will figure out what is happening and improve it.
When comparing performance between LWRP and Built-in renderer please make sure:
-
Built-in is set to forward renderer as it is the only renderer we support for now
-
Make sure the Quality Settings in Built-in match LWRP. Quality Settings in LWRP are configured in the LWRP asset.
-
If you using a Android 7.0 or above capable device make sure to check Sustained Performance mode in Player Settings.
-
If you are on a mobile device that does not support Sustained Performance mode make sure you give some minutes for the device to cool down between profiling sessions. This happens because mobile GPUs have passive cooling system. When they overheat the CPU and GPU clocks down to cool down and this impacts severely performance.
Current Limitations
-
Currently only one directional light is supported. We’ll add support to shade additional directional lights in the light loop. This is coming soon.
-
Light culling layer for the main directional light is not yet implemented. Main light is not culled per-object and there’s currently no efficient way to implement this in a single pass renderer for all platforms. We are working on changes to engine to allow support for efficiently doing this. This is most likely coming only in 19.1.
-
Due to issues with Graphics Emulation we are limiting shading to 1 main light + 4 additional lights per-object. Also, there’s a limit to at most 16 visible lights globally. This limit will be removed once we fix the Graphics Emulation issue. This way we can store light data in StructuredBuffers for platforms that support it. We are investigating a workaround for the issue for 18.3. Otherwise it will only be fixed in 19.1
-
There’s currently no built-in support for postfx AO. A user has added support to MSVO in LWRP
-
Motion Vectors and Camera Normals are not supported yet. This makes some post effects not supported in LWRP.
-
Speed Tree shaders are not yet ported to LWRP.
-
Particles shaders are not yet fully ported to LWRP.
-
LPPV, Mixed Lighting Mode, Occlusion Probes are not supported. This is most likely only coming in 19.2
-
Point light shadows are not supported. This is most likely only coming in 19.2
-
Camera Relative rendering is not supported. This is most likely only coming in 19.3
-
Box Projection and Reflection Probe blending is not supported. This is most likely coming in 19.3.
-
Detail maps and parallax is not supported in the built-in LWRP shaders yet.
-
Realtime GI is not supported.
That’s it. Please let us know of any issues you have.