未添加 _Stencil 属性时 Unity 着色器警告

问题描述 投票:0回答:1

我正在为 Unity 2019.3.13f1 编写一个自定义着色器,它只是一个简单的 UI 渐变。该着色器不(需要)对模板缓冲区执行任何操作,因此我将模板设置为始终静态传递:

Stencil
{
    Ref 0
    Comp Equal
    Pass Keep
}

但是这样做会引发警告

材质 SomeGradient 没有 _Stencil 属性

所以我添加了一个 _Stencil 属性(尽管它永远不会被使用,而且我也不希望其他人能够从编辑器更改模板缓冲区)

[HideInInspector] _Stencil("Stencil ID", Float) = 0

Stencil
{
    Ref [_Stencil]
}

这会消除警告,但会引发新警告:

材质 SomeGradient 没有 _StencilOp 属性

现在重复前面的步骤,它将继续这样做,直到我最终得到一堆我不想公开的属性,并且也不想更改,只是为了摆脱一些警告

[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]
}

这使我的着色器代码显着膨胀,而无需添加任何功能(在没有属性的情况下静态设置它)。查看 Unity 的

UI-Default
着色器,他们还显式添加了这些属性(以及
_ColorMask
,否则也会引发警告)。

引发警告的代码来自

\2019.3.13f1\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\UI\Core\StencilMaterial.cs
方法
Material Add
,该方法似乎是在将材质添加到图像组件的材质属性时由 Unity 在内部调用的。

 /// <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
}

完全删除

Stencil{}
通行证仍然会引发警告。

我查看了 Stencil 的 documentation,但我似乎找不到他们想要显式添加此属性的原因,在文档示例中他们也没有显式添加属性。那么有一个我错过的充分理由吗?


我还发现令人困惑的是,当您创建一个新的无光照着色器(创建>着色器>无光照着色器)时,它不会抛出这些警告,尽管也没有显式添加模板属性

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
    Tags { "RenderType"="Opaque" }
    LOD 100

    Pass
    {
     //Rest of shader code
    }
}

为什么这似乎是一个例外?

unity-game-engine shader hlsl stencil-buffer
1个回答
0
投票

Stencil 不是着色器中使用的属性,而是 Unity 对绘制状态进行编程的指示。

在着色器中拥有这些属性会影响 DepthStencil 状态的创建方式。

对于 UI 着色器,Stencil 用于各种功能,例如屏蔽滚动矩形之外的 UI 等。没有这个会导致奇怪的行为。例如。 UI 元素在带有遮罩的滚动矩形外部可见。

为了使所有 UI 元素能够很好地协同工作,我发现最好的方法是从默认 UI 着色器派生任何 UI 着色器。

© www.soinside.com 2019 - 2024. All rights reserved.