Creating a condition inside stencil block

I use the following code right now to pass a value into a stencil shader and it works nicely:

Properties{
    [IntRange] _StencilMask("Stencil Mask", Range(0, 255)) = 0
}
SubShader{
    Stencil {
        Ref[_StencilMask]
        Comp always
        Pass replace
    }
}

Now I need to expand my use case. I want to react to the eye (as found in unity_StereoEyeIndex) that is currently being rendered (URP with Single Pass Rendering). I want to set a different stencil value per eye. How would I do that? Is there some sort of “if” condition I can use in the stencil block so that I could declare two properties? I also tried passing a float array but I get an error when writing

Ref[_StencilMasks[unity_StereoEyeIndex]]

Any help would be highly appreciated!

You’d probably have to use two passes, and collapse the vertices of one eye so it doesn’t get rendered.

// pseudo code
Pass {
    Stencil {
        Ref[_StencilRefLeft]
        // etc
    }
    
    // vertex shader
        if (unity_StereoEyeIndex != 0) // not left eye
            o.pos = float4(0,0,0,1);
        return o;
    }
    // etc
}
Pass {
    Stencil {
        Ref[_StencilRefRight]
        // etc
    }
   
    // vertex shader
        if (unity_StereoEyeIndex != 1) // not right eye
            o.pos = float4(0,0,0,1);
        return o;
    }
    // etc
1 Like

That is a good hint already! In LWRP there is no multi-pass support though. That will probably make this not work. I could assign two materials to the object which would cause unity to iterate twice over the shader. That might do the trick at a bit higher cost. What does o.pos = float4(0,0,0,1); do exactly? Will it tell the shader not to set the stencil there?

That tells the

That collapses the vertices of the object to infinity small so it’ll never be rendered for that eye.

1 Like