Is it possible to pass SubShader tag as a parameter?

Hi,

I'm trying to control rendering order explicitly. One of the ways to do that is to control "Queue" Tag in my shader. Unfortunately that means I have to create a shader for each rendering "layer".

I would like to create a shader which takes "Queue" Tag as a parameter - that would allow me to create a single shader and then just to pass an parameter value to control rendering order.

Is it possible to do that (and how)? Or is there a better technique?

Thanks, Paulius

I have this same issue and put it in the too hard basket for a while. Now after looking through the documentation for the Material class I noticed that a material uses the shader renderqueue position by default, however you can override that via Material.renderQueue (i.e. NOT shader.renderQueue). Once you do this the Material maintains its new position in the renderQueue. So you can control this in code and it only requires ONE version of your shader.

[EDIT] Changing my answer to YES. Shader.renderQueue is readonly, but Material.renderQueue is writable. (Everything else here is still correct, just not complete.)


Unfortunately I think the answer is no. The Tag syntax only supports strings. Also, Shader.renderQueue is read-only:

http://unity3d.com/support/documentation/ScriptReference/Shader-renderQueue.html

Which implies you can't change it dynamically.

Also, since renderQueue is a property of the shader, not the material, you couldn't use the same shader on different materials with different queue settings.


But I did find a way to manage static render order from the Unity scene editor.

Create the shader for the effect you want, with a named pass that you will reuse below. Note that pass name should be uppercase.

Shader "MyShader"
{
    Properties { ... }
    SubShader
    {
        Tags {"Queue"="Transparent"}
        Pass
        {
            Name "MAIN"
            ... (implement your effect)
        }
    } 
}

Now create a shader per desired layer, named and tagged by layer number (here's layer 1):

Shader "MyShader/1"
{
    Properties { ... (need to duplicate from main shader) }
    SubShader
    {
        Tags {"Queue"="Transparent+1"}
        UsePass "MyShader/MAIN"
    } 
}

Create your material(s) per layer, selecting shader MyShader > 1, 2, 3, etc. You can change the shader selection from the scene editor to change the layer order. Since your implementation is all in one shader ("MyShader") and reused in the layer shaders, you only have to modify one shader in order to change the implementation.

Unfortunately if you add or remove passes or change the properties you need to update all the layer shaders as well, so this isn't perfect, but it helps.