We know that the introduction of the Scriptable Render Pipelines brought a lot of complexity to writing shaders in Unity. We are working on improving that experience. As you are likely aware, the features we write today take almost a year to release in a shipped Unity Editor, so please keep that broad timeline in mind. We will share frequent updates on these plans and give you access to our work in alphas and betas for early feedback whenever possible.
Requirements
We’ve read these threads, your tweets, and your blog comments, and we’ve talked with some of you directly. We know the following features are critical:
- You need to hand-write shaders and have that code work across pipelines and upgrade seamlessly to new versions of Unity.
- You need a straightforward way to do that without a ton of boilerplate code.
- You need these shaders, and ones created in Shader Graph, to be modular, composable, and work with custom Render Pipelines.
- You need to create your own templates/targets for any render pipeline and let TA’s and artists extend those in Shader Graph or via code.
The following system is designed to meet those requirements.
Design
We are adding the concept of composable Shader Blocks to our existing Shader Lab language. A Shader Block is an isolated piece of shader functionality that declares a public interface in the form of inputs and outputs.
Render pipelines will provide Shader Templates, each exposing a set of Customization Points (name TBD). Shader Blocks can be plugged into these Customisation Points, and their inputs/outputs will be automatically matched together to pass data between them. You will also be able to manually control this data flow. A completed template outputs a subshader. The final shader is then composed from one or more subshaders.
Underlying this system will be an internal, intermediate representation of the Shaders that we’re calling the Shader Foundry. All Shader Block code, as well as Shader Graph files, will produce this unified representation, allowing both to use the same set of templates to output Shaders for each required pipeline.
Of course this is all very high-level, but over the next few months we’ll show you examples of the code and how to use it so we can refine our APIs based on your input.
Benefits
The biggest benefit of this system is that it supports every feature of the render pipelines. No more waiting for Shader Graph to add a node or workflow - URP and HDRP will expose their features directly. It also provides stability across upgrades so the shader code you write in it will work for years. Additional benefits:
-
Customizability - the provided customization points will give a lot of power to control the final result, and if they are insufficient you can create your own template either from the ground up or based on an existing template to limit or expand the end user’s ability to control the shader.
-
Reusability - Shader Blocks are interchangeable, mix-and-match pieces. Unity’s internal functionality will be written as blocks that you can incorporate into your own shaders. The Asset Store will use the same system as well.
-
Specialization - We will include the concept of pipeline specific blocks and branches so functionality can be adjusted based on which pipeline is in use, along with other performance, platform, and feature support branches.
-
The limitations of the system are driven by the render pipelines. For example, HDRP will not support custom lighting due to the complexity of its lighting system, while URP will support providing your own lighting function because URP’s lighting system is not as deeply integrated with the other parts of the rendering pipeline and is designed to be highly flexible. As part of our goal to provide a unified authoring environment across pipelines, we are finding ways to reference common concepts (like motion vectors) in a pipeline-agnostic way.
Surface Shaders?
A big question on many minds is, “Will this provide a feature-for-feature replacement for the BuiltIn Render Pipeline’s Surface Shaders?”. Our goal is to provide as much parity and support as possible within the constraints of a modern, performant graphics pipeline. Some of the features and syntax that Unity added to Surface Shaders are kind of bonkers! And you all did amazing, beautiful things with them! But that kind of deep access to every facet of the renderer’s internals just isn’t realistic in a modern rendering architecture. We’ll provide a lot more detail on this in the future, including a feature-by-feature comparison. For the Surface Shader features we can’t support, we’ll gather your input on what you used them for and do our best to provide alternative solutions.
Timeline
So when can you get your hands on this? It won’t all come right away. Over the next year, we will release the Shader Foundry layer - including a public, supported C# API for constructing shader code in the Foundry. We will also update our Shader Graph Targets to take advantage of the new system. Along with that, we will start releasing previews of the new ShaderLab features that will become the preferred way to write shaders for Unity. If you prefer, you will still be able to write directly in the low level languages you use today. Since this all has a lot of nuance and we need to get it right, we’ll be reviewing the work in progress with a lot of people both internally and externally before we finalize and release it.
Summary
This is a high-level plan, and we understand if you have questions or are just skeptical! Our best answer will be to execute and deliver a fantastic solution. Please let us know where you’d like additional clarity, or if there are use cases we haven’t captured here. We welcome your feedback and we look forward to the incredible experiences you’ll build with it!