Block Shaders: Surface Shaders for SRPs and more (Public Demo Now Available!)

Greetings from the Shader team!

We heard your feedback regarding the need for SRP compatible surface shaders, as well as a better way to integrate with Unity’s Shader system, and have been hard at work to provide a meaningful solution which we are now happy to announce in the form of Block Shaders.

Block Shaders introduce a streamlined and modular text-based shader authoring workflow, and allow to override and extend the functionality of existing shaders, without the complexity of modifying the original shader source - in a similar fashion to BiRP Surface Shaders. In addition, Block Shaders also aim to help unify shader authoring across the render pipeline.

We are at an alpha stage of development and need to hear from you! To that end, we prepared a public prototype for you to experiment with and provide your valuable input as early as possible. In order to access the demo please refer to the demo’s Quickstart Guide.

Manifesting as a new shader asset type and syntax, Block Shaders can override and extend the functionality of shader “templates”, which will be provided by the Render Pipeline’s or created freely by users. For example, a Block Shader can override and extend a lit template’s vertex or surface descriptions:

BlockShader “MyShader” implements “LitTemplate” {

   Blocks {

        Block VertexBlock
        {
            Interface
            {
                inout float3 PositionOS;
                inout float3 NormalOS;
                [Property] in float _Deformation;
            }
            void apply(inout Interface self)
            {
                // HLSL goes here...
                self.PositionOS += self.NormalOS * _Deformation;
            }
        }

        Block SurfaceBlock
        {
            Interface
            {
                in float4 UV;
                out float3 Albedo;
                out float Metalness;
                out float Roughness;
                out float Alpha;
            }
            void apply(inout Interface self)
            {
                 self.Albedo = float(1.0, 0.0, 0.0); // set albedo to red
                 self.Metalness = 0.0; // set metalness to non-metallic
                 self.Roughness = 0.5; // set roughness to semi-rough
                 self.Alpha = 1;
            }
        }
   }

   Implementation Vertex
   {
      VertexBlock;
   }

   Implementation Surface
   {
      SurfaceBlock;
   }

}

Users are free to declare their own custom Blocks, and define their Block’s interfaces in order to freely pass data between Blocks. In the following example, an interpolator is passed between a Vertex and Surface Block in order to implement custom fog:

        Block VertexBlock
        {
            Interface
            {
                inout float3 PositionOS;
                out float FogIntensity;

            }
            void apply(inout Interface self)
            {
                float3 positionWS = TransformObjectToWorld(self.PositionOS);
                float4 positionCS = TransformWorldToHClip(positionWS);
                float2 pos = positionCS.xy / positionCS.w; 
                self.FogIntensity = min(1, dot(pos, pos) * 0.5); 
            }
        }

        Block SurfaceBlock
        {
            Interface
            {
                in float FogIntensity;
                out float3 Color;
            }
            void apply(inout Interface self)
            {
                self.Color = lerp(self.Color, float3(1.0,1.0,1.0), self.FogIntensity); 
            }
        }

Block Shaders can be created from available Block Templates which define the shader’s passes and stages. Templates are constructed using a collection of linked Blocks - shader functions with a set interface (akin to shader graph nodes) to be reused and shared as assets and libraries across shaders, projects and teams.

Templates also expose public Blocks called “Customization Points” along the shader’s flow of execution, which define the template’s public interface to be implemented and extended by Block Shaders, using any number of user defined Blocks.

By authoring Blocks, as well as utilizing existing Block libraries, users can override and extend shaders in a reusable and modular fashion:


For illustration purposes only

The Universal and High Definition Render Pipelines will both provide a library of Block Templates, corresponding to their existing shader libraries, to be overridden and extended by user authored Block Shaders. In addition to the familiar vertex or surface descriptions, templates could provide any number of customizations points, for use cases such as custom lighting functions or image-based lighting override:

        Block DirectionalLightingBlock
        {
            Interface
            {
               in float3 Normal;
               inout float3 Color;
            }
            void apply(inout Interface self)
            {
               self.Color *= saturate(dot(self.Normal, _MainLightPosition.xyz)) * _MainLightColor.rgb;
            }
        }

        Block ImageBasedLightingBlock
        {
            Interface
            {
                inout float3 ReflectionWS;
                [Property] UnityTextureCube _CubeMap;
                out float3 IBL;
            }
            void apply(inout Interface self)
            {
                self.IBL = texCUBE(self._CubeMap, self.ReflectionWS).rgb;
            }
        }

In order to unify the shader authoring across pipelines, we are evaluating if URP and HDRP will provide templates under cross-pipeline Template Groups, which define a shared minimal interface. Users could then author Block Shaders that target a specific template group, in order to maintain compatibility with both pipelines, with HDRP potentially implementing more complex shading and utilizing more optional customization points compared to the URP equivalent.

Due to the generic nature of Block Shaders, they also allow streamlining the creation of any type of shader, depending on the templates created by both Unity and the community. For example, a developer or asset store creator could choose to create a volumetric ray marching template - and allow technical artists to customize their own cloud or smoke shaders in a simplified manner.

This new workflow is made possible by Shader Foundry API, a new intermediate layer and API which provides a C# representation of Block Shaders and Templates, and allows for better integration with Unity’s shader system. The Shader Foundry API will allow developers to programmatically create and configure Block Shader Templates, in order to integrate and maintain shaders and tools across pipelines and engine versions.

We hope to land Shader Foundry and Block Shaders as early as possible, including official URP and HDRP template support. We will continue to improve and extend Block Shaders, and provide support for additional features such as compute or raytracing shaders, so please share your feedback and any feature or functionality you would like to see - either directly in this thread or via the Block Shaders Survey.

You can follow our progress in the Shaders forum as well as in our public roadmap, and look forward to an announcement of when the Foundry is available in the public betas. We can’t wait to see what amazing shaders and block libraries you create using Block Shaders!

51 Likes

This looks DEFINITIVELY EXCITING!
Will this be a core feature only available on future Unity versions or will this be compatible with current Unity 2021 LTS ?

Long awaited, very much necessary! Maybe a silly question, but there’s no compatibility / interoperability with built-in RP? Just wanting to know if we’ll be still 2+ years either stuck at legacy built-in or tied to Better Shaders (the Asset Store package)…

2 Likes

@atomicjoe
I’m afraid we do not have any plans to backport Block Shaders and Shader Foundry at the moment.

@Edy
Since you can use “Surface Shaders” with BiRP, this seems like a lower priority for us at the moment. With that in mind, would Block Shaders support for BiRP be something you interested in? If so, please fill the survey and let us know. We will definitely consider this when planning our roadmap for rolling out Block Shaders…

1 Like

At the very least, you can have Shadergraph shaders target BiRP alongside the others now.
It does seem strange to me adding support for BiRP wouldn’t be as simple as having a third compilation target that maps the outputs to BiRP syntax, given they already do that with ShaderGraph…

But anyways, excited to see this is finally here and to try this out!

2 Likes

Ok so let me recap: Block Shaders is not compatible with current or older Unity versions, is not compatible with BiRP and it’s not compatible with Surface Shaders.

What we asked for was to port Surface Shaders to SRP for retro and inter-compatibility with ALL render pipelines and 10+ years of shaders and what we got is yet another layer of incompatibility over Unity.

Nice.

11 Likes

Yet another disappointment in the long list of Unity disappointments.
I’m out.

3 Likes

We could very well explore providing BiRP compatibility with Block Shaders if there is enough interest so we are definitely not ruling that out.

The demo we provided includes “Simple Lit” templates that allow you to override the Vertex and Surface descriptions of a shader, similarly to BiRP Surface Shaders - so we recommend you check that out.

Being much more generic, Block Shaders will allow the Render Pipelines to expose any public interface they see fit for their provided shader templates. Users could also freely define their own templates and their available interface. This would allow to potentially match, or even exceed the functionality provided by the existing BiRP Surface Shaders.

We are also exploring the concept of “Template Groups” in order to allow unifying the shader authoring experience across pipeline. In practice, this could allow you to author Block Shaders that target certain template groups in order to achieve cross pipeline compatibility for your authored shaders!

3 Likes

The main issue with re-using old surface shaders was the barrier to entry of copying their functionality to the newer pipelines. This system should in theory make it very easy to translate old surface shaders to the new pipelines, especially once some templates are made for it.

1 Like

First of all, let me be clear that this is not against you or your team in particular but about Unity’s direction in general and there is nothing personal in it:

You’ll have to excuse my lack of confidence in any potentiality after all these years of lackluster SRP performance and compatibility compared to BiRP.
With this you had the opportunity to bridge the gap between BiRP and SRP, incentivize adoption of the SRPs by BiRP users and leverage more than a decade of shaders by simply supporting Surface Shaders on the SRPs, but instead of that you opted for yet another new layer of incompatibility over the SRPs, doubling down on all what the community criticized the SRPs for.
You keep pushing the SRPs and try to bury BiRP and yet the community refuses to let BiRP die. You should ask yourselves WHY, instead of doubling down on something the users don’t really want.
The problem here is the mindset.

11 Likes

+1 to what @atomicjoe is saying. Big problem for adapting SRP is the fact that we can’t easily port shaders, now you make a tool that could solve it and completely neglect this fact. It’s just annoying to see Unity trying to act like BiRP is not a thing again and again. That’s not exactly how you make people change their toolset you know.

It’s like if Blender 2.8 decided to just straight up remove old shortcuts instead of providing compatability options. You don’t exactly need a survey to understand why this would not work well

That said, I have a question regarding syntax

Implementation VertexDescription
{
    FogBlock()->(VertexFogIntensity: FogInterpolator);
}

Why use → operator instead of just FogBlock(VertexFogIntensity: FogInterpolator);
And what can Implementation thing have inside it anyway, except call to a block?

Also. How template is selected, or whatever is used to generate a shader? Would it be possible to select template from block shader itself, thus, assets like GPUInstancer could provide custom templates that would work with their own rendering systems

2 Likes

If this was really simple to do, it would’ve been done ages ago.

It may be simple enough to make a translation tool that converts a subset of surface shaders to the new system. We’ll evaluate this in due time.

The Implementation section can have a list of block invocations.
As to the syntax, it goes like this:

BlockName(input0: inVar0, ...)->(output0: outVar0, ...); // Full version
BlockName(inout0: var0, ...); // When overridden inputs and outputs are symmetric
BlockName; // No overrides

A template is specified in the block shader.

7 Likes

Definitely. Oh, damn it, definitely! My understanding was that all this was intended to finally provide RP interoperability between all RPs supported by Unity.

What we desperately need since the very arrival of SRPs is some way to have our shaders and materials so they just work no matter the actual RP being used in the project (BiRP, URP, HDRP, future/other RP…). Of course they may look different depending on the RP used. Of course some features will be available in some RPs and not in others. But they will just work instead of showing a pink material.

You guys even gave a talk in Unite Copenhagen 2019 entirely dedicated to create BiRP-URP compatible shaders and effects! It’s a very unexpected surprise that now BiRP is a “lower priority”, given that it’s the only RP that is truly universal still today! Many of us have been stuck here since forever, as upgrading to any non-BiRP pipeline has always been an one-way destructive path for our projects.

Sure, I’ll fill the survey if that helps. Thank you for your understanding!

9 Likes

If you can actually have a tool that could convert surface shaders to block shaders it could as well be a proof that new system at least has no regressions compared to previous. So I think that would be a good idea

And syntax now makes perfect sense to me, thanks. So far idea looks better than surface shaders. Those were weird and built around edge cases so I like this new approach more

1 Like

I’m not technical enough to understand the way it all works but I have a question, Jason made this tool that lets you write shaders for all the render pipelines, ( BIRP included ) why does unity not allow for this?

7 Likes

Same for Amplify shaders, they can work on all pipelines, what is needed is more unity between pipelines and not just between URP and HDRP

4 Likes

Please, please do. Compatibility between all RPs supported by Unity has been desperately needed for too many years.

Young people might not remember this, but years ago one of the mottos in Unity was “author once, build many”. The introduction of SRPs blew all that up, leaving many of us stuck at BiRP or Better Shaders.

10 Likes

That’s not what we need. We need full Surface Shaders compatibility.
Sorry if that’s not what you wanted to hear, but that’s just the way it is.
If that’s not easy to do with the current state of SRPs, then maybe that is what should be fixed, instead of putting band-aids over a bleeding wound.

7 Likes

I can kinda get why people want BIRP support, it would help with the transition for sure. I imagine on Unity’s end since BIRP will DEFFINITELY be depreciated at some point it doesn’t seem worth the effort. Cause as soon as URP/HDRP is more dominantly used, they’ll move on completely. They just need to make a more convincing argument to do so.

And the side effect of adding support for this is people may stick with BIRP for longer than they’d like.

But I think the reason they should is cause when that depreciation happens, hopefully the transition will be much smoother. I’ve already long left BIRP behind personally, but there’s still the issue of assets and such that might not be SRP compatible. So, I would maybe see benefits on the asset store side in the end if people could more easily update their assets.

But I’m certain this will complicate matters, sure it CAN be done, but people already complain about Unity being slow as it is. And maybe some dude who knows BIRP in an out can make a tool for it, but how many people at Unity now are at that level that are available for that job?

At least for me personally, the need is low priority compared to the desire to see things move forward as an SRP user.

5 Likes

Don’t you think being able to transition without redoing all of your shaders from scratch would be nice argument?

This kind of thinking doesn’t apply to majority that still use BiRP. Mostly because it’s not only not compatible but actually better than glorified mobile renderer which is URP and simepler than parameter hell that is HDRP. But I’m getting off track now so gonna shut up :roll_eyes:

6 Likes