Reputation: 5173
I'm writing a custom shader for Unity 2019.3.13f1 that is just a simple UI gradient. This shader does not (need to) do anything with the stencil buffer, so I set the Stencil to always pass statically:
Stencil
{
Ref 0
Comp Equal
Pass Keep
}
However doing this will throw the warning
Material SomeGradient doesn't have _Stencil property
So I add a _Stencil property (despite it never going to be used, and I don't want others to be able to change the stencil buffer from the editor either)
[HideInInspector] _Stencil("Stencil ID", Float) = 0
Stencil
{
Ref [_Stencil]
}
This gets rid of the warning, but will throw a new warning:
Material SomeGradient doesn't have _StencilOp property
Now repeating the previous step it will keep doing this untill I eventually end up with a bunch of properties I don't want exposed, and never want to change either, just to get rid of some warnings
[HideInInspector] _Stencil("Stencil ID", Float) = 0
[HideInInspector] _StencilOp("Stencil Operation", Float) = 0
[HideInInspector] _StencilComp("Stencil Comparison", Float) = 8
[HideInInspector] _StencilReadMask("Stencil Read Mask", Float) = 255
[HideInInspector] _StencilWriteMask("Stencil Write Mask", Float) = 255
Stencil{
Ref [_Stencil]
Pass[_StencilOp]
Comp[_StencilComp]
ReadMask[_StencilReadMask]
WriteMask[_StencilWriteMask]
}
This bloats my shader code significantly, without adding anything to functionality (over statically setting it without properties). Looking at Unity's UI-Default
shader they have also added these properties properties explicitly (along with _ColorMask
which also throws a warning elsewise).
The code throwing the warning comes from the \2019.3.13f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\UI\Core\StencilMaterial.cs
method Material Add
, which seems to get called internally by Unity when adding a Material to the Material property of an Image component.
/// <summary>
/// Add a new material using the specified base and stencil ID.
/// </summary>
public static Material Add(Material baseMat, int stencilID, StencilOp operation, CompareFunction compareFunction)
{
if ((stencilID <= 0 && colorWriteMask == ColorWriteMask.All) || baseMat == null)
return baseMat;
if (!baseMat.HasProperty("_Stencil"))
{
Debug.LogWarning("Material " + baseMat.name + " doesn't have _Stencil property", baseMat);
return baseMat;
}
if (!baseMat.HasProperty("_StencilOp"))
{
Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilOp property", baseMat);
return baseMat;
}
if (!baseMat.HasProperty("_StencilComp"))
{
Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilComp property", baseMat);
return baseMat;
}
if (!baseMat.HasProperty("_StencilReadMask"))
{
Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilReadMask property", baseMat);
return baseMat;
}
if (!baseMat.HasProperty("_StencilWriteMask"))
{
Debug.LogWarning("Material " + baseMat.name + " doesn't have _StencilWriteMask property", baseMat);
return baseMat;
}
if (!baseMat.HasProperty("_ColorMask"))
{
Debug.LogWarning("Material " + baseMat.name + " doesn't have _ColorMask property", baseMat);
return baseMat;
}
//Rest of code
}
Removing the Stencil{}
pass in its entirety will also still throw the warning.
I looked at the documentation for Stencil, but I can't seem to find a reason why they want this explicitly added, in the docs examples they don't add the properties explicitly either. So is there a good reason for it that I missed?
What I also find baffling is that when you create a new Unlit shader (Create>Shader>Unlit Shader) it doesn't throw these warnings, despite not having the stencil properties added explicitly either
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
//Rest of shader code
}
}
Why does this seem to be an exception to the rule?
Upvotes: 5
Views: 11563
Reputation: 1
Stencil is not a property used in shader but an indication to Unity on programming the Draw state.
Having these properties in the shader effects how DepthStencil state is created.
For a UI shader, Stencil is used for various features like masking UI which goes outside a scroll rect etc. Not having this would result in weird behaviour. Eg. UI elements visible outside a scroll rect with a mask.
For all the UI elements to work well together, I found the best way is to derive any shader for UI from the default UI shader.
Upvotes: 0