Version: 2020.3
ShaderLab 命令:Offset
ShaderLab 命令:UsePass

ShaderLab 命令:模板

配置与 GPU 上的模板缓冲区相关的设置。

模板缓冲区为帧缓冲区中的每个像素存储一个 8 位整数值。为给定像素执行片元着色器之前,GPU 可以将模板缓冲区中的当前值与给定参考值进行比较。这称为模板测试。如果模板测试通过,则 GPU 会执行深度测试。如果模板测试失败,则 GPU 会跳过对该像素的其余处理。这意味着可以使用模板缓冲区作为遮罩来告知 GPU 要绘制的像素以及要丢弃的像素。

通常会将模板缓冲区用于特殊效果,例如门户或镜子。此外,在渲染硬阴影或者构造型实体几何 (CSG) 时,有时会使用模板缓冲区。

渲染管线兼容性

功能名称 内置渲染管线 通用渲染管线 (URP) 高清渲染管线 (HDRP) 自定义 SRP
模板

用法

此命令会更改渲染状态。在 Pass 代码块中使用它可为该通道设置渲染状态,或者在 SubShader 代码块中使用它可为该子着色器中的所有通道设置渲染状态。

可以使用 Stencil 命令执行两种不同的操作:配置模板测试,以及配置 GPU 写入模板缓冲区的内容。可以在同一个命令中执行这两种操作,但最常见的用例是创建一个 Shader 对象,该对象会遮罩其他 Shader 对象无法绘制到的屏幕区域。为此,需要将第一个 Shader 对象配置为始终通过模板测试并写入模板缓冲区,并将其他对象配置为执行模板测试而不写入模板缓冲区。

使用 RefReadMaskComp 参数可配置模板测试。使用 RefWriteMaskPassFailZFail 参数可配置模板写入操作。

模板测试方程为:

(ref & readMask) comparisonFunction (stencilBufferValue & readMask)
签名 示例语法 功能
Stencil
{
    Ref <ref>
    ReadMask <readMask>
    WriteMask <writeMask>
    Comp <comparisonOperation>
    Pass <passOperation>
    Fail <failOperation>
    ZFail <zFailOperation>
    CompBack <comparisonOperationBack>
    PassBack <passOperationBack>
    FailBack <failOperationBack>
    ZFailBack <zFailOperationBack>
    CompFront <comparisonOperationFront>
    PassFront <passOperationFront>
    FailFront <failOperationFront>
    ZFailFront <zFailOperationFront>
}

请注意,所有参数都是可选的。
Stencil
{
    Ref 2
    Comp equal
    Pass keep
    ZFail decrWrap
}
根据给定参数配置模板缓冲区。

有效参数值

参数 功能
ref 整数。范围为 0 到 255。默认值为 0。 参考值。

GPU 使用在 compareOperation 中定义的操作将模板缓冲区的当前内容与此值进行比较。

此值使用 readMask 或 writeMask 进行遮罩,具体取决于进行的是读取操作还是写入操作。

如果 Pass、Fail 或 ZFail 的值为 Replace,则 GPU 也可以将此值写入模板缓冲区。
readMask 整数。范围为 0 到 255。默认值为 255。 GPU 在执行模板测试时使用此值作为遮罩。

有关模板测试方程,请参阅上文。
writeMask 整数。范围为 0 到 255。默认值为 255。 GPU 在写入模板缓冲区时使用此值作为遮罩。

请注意,与其他遮罩一样,它指定操作中包含的位。例如,值为 0 表示写入操作中不包含任何位,而不是模板缓冲区接收值 0。
comparisonOperation 比较操作。请参阅比较操作值以了解有效值。默认值为 Always。 GPU 为所有像素的模板测试执行的操作。

这会定义适用于所有像素的操作,而与朝向无关。如果定义了此值以及 comparationOperationBack 和 comparationOperationFront,则此值会覆盖它们。
passOperation 模板操作。请参阅模板操作值以了解有效值。默认值为 Keep。 当像素通过模板测试和深度测试时,GPU 对模板缓冲区执行的操作。

这会定义适用于所有像素的操作,而与朝向无关。如果定义了此值以及 passOperationBack 和 passOperationFront,则此值会覆盖它们。
failOperation 模板操作。请参阅模板操作值以了解有效值。默认值为 Keep。 当像素未能通过模板测试时,GPU 对模板缓冲区执行的操作。

这会定义适用于所有像素的操作,而与朝向无关。如果定义了此值以及 failOperationBack 和 failOperationFront,则此值会覆盖它们。
zFailOperation 模板操作。请参阅模板操作值以了解有效值。默认值为 Keep。 当像素通过模板测试,但是未能通过深度测试时,GPU 对模板缓冲区执行的操作。

这会定义适用于所有像素的操作,而与朝向无关。如果定义了此值以及 zFailOperation 和 zFailOperation,则此值会覆盖它们。
comparisonOperationBack 比较操作。请参阅比较操作值以了解有效值。默认值为 Always。 GPU 为模板测试执行的操作。

这会定义仅适用于背面像素的操作。如果定义了 comparisonOperation,则该值会覆盖此值。
passOperationBack 模板操作。请参阅模板操作值以了解有效值。默认值为 Keep。 当像素通过模板测试和深度测试时,GPU 对模板缓冲区执行的操作。

这会定义仅适用于背面像素的操作。如果定义了 passOperation,则该值会覆盖此值。
failOperationBack 模板操作。请参阅模板操作值以了解有效值。默认值为 Keep。 当像素未能通过模板测试时,GPU 对模板缓冲区执行的操作。

这会定义仅适用于背面像素的操作。如果定义了 failOperation,则该值会覆盖此值。
zFailOperationBack 模板操作。请参阅模板操作值以了解有效值。默认值为 Keep。 当像素通过模板测试,但未能通过深度测试时,GPU 对模板缓冲区执行的操作。

这会定义仅适用于背面像素的操作。如果定义了 zFailOperation,则该值会覆盖此值。
comparisonOperationFront 比较操作。请参阅比较操作值以了解有效值。默认值为 Always。 GPU 为模板测试执行的操作。

这会定义仅适用于正面像素的操作。如果定义了 comparisonOperation,则该值会覆盖此值。
passOperationFront 模板操作。请参阅模板操作值以了解有效值。默认值为 Keep。 当像素通过模板测试和深度测试时,GPU 对模板缓冲区执行的操作。

这会定义仅适用于正面像素的操作。如果定义了 passOperation,则该值会覆盖此值。
failOperationFront 模板操作。请参阅模板操作值以了解有效值。默认值为 Keep。 当像素未能通过模板测试时,GPU 对模板缓冲区执行的操作。

这会定义仅适用于正面像素的操作。如果定义了 failOperation,则该值会覆盖此值。
zFailOperationFront 模板操作。请参阅模板操作值以了解有效值。默认值为 Keep。 当像素通过模板测试,但未能通过深度测试时,GPU 对模板缓冲区执行的操作。

这会定义仅适用于正面像素的操作。如果定义了 zFailOperation,则该值会覆盖此值。

比较操作值

在 C# 中,这些值通过 Rendering.CompareFunction 枚举进行表示。

Rendering.CompareFunction 枚举中的对应整数值 功能
Never 1 从不渲染像素。
Less 2 在参考值小于模板缓冲区中的当前值时渲染像素。
Equal 3 在参考值等于模板缓冲区中的当前值时渲染像素。
LEqual 4 在参考值小于或等于模板缓冲区中的当前值时渲染像素。
Greater 5 在参考值大于模板缓冲区中的当前值时渲染像素。
NotEqual 6 在参考值与模板缓冲区中的当前值不同时渲染像素。
GEqual 7 在参考值大于或等于模板缓冲区中的当前值时渲染像素。
Always 8 始终渲染像素。

模板操作值

在 C# 中,这些值通过 Rendering.Rendering.StencilOp 枚举进行表示。

Rendering.StencilOp 枚举中的对应整数值 功能
Keep 0 保持模板缓冲区的当前内容。
Zero 1 将 0 写入模板缓冲区。
Replace 2 将参考值写入缓冲区。
IncrSat 3 递增缓冲区中的当前值。如果该值已经是 255,则保持为 255。
DecrSat 4 递减缓冲区中的当前值。如果该值已经是 0,则保持为 0。
Invert 5 将缓冲区中当前值的所有位求反。
IncrWrap 7 递增缓冲区中的当前值。如果该值已经是 255,则变为 0。
DecrWrap 8 递减缓冲区中的当前值。如果该值已经是 0,则变为 255。

示例

Shader "Examples/CommandExample"
{
    SubShader
    {
         // 此处是定义子着色器的代码的其余部分。

        Pass
        {    
             // 此通道中的所有像素都会通过模板测试并将值 2 写入模板缓冲区
             // 如果要防止后续着色器绘制到渲染目标的此区域或将它们限制为仅渲染到此区域,则通常会执行此操作
             Stencil
             {
                 Ref 2
                 Comp Always
                 Pass Replace
             }            

             // 此处是定义通道的代码的其余部分。
        }
    }
}

此示例代码演示在 SubShader 代码块中使用此命令的语法。

Shader "Examples/CommandExample"
{
    SubShader
    {
             // 仅当模板缓冲区的当前值小于 2 时,此子着色器中的所有像素才通过模板测试
             // 如果希望仅绘制到渲染目标中未"遮罩"的区域,则通常会执行此操作
             Stencil
             {
                 Ref 2
                 Comp Less
             }  

         // 此处是定义子着色器的代码的其余部分。

        Pass
        {    
              // 此处是定义通道的代码的其余部分。
        }
    }
}
ShaderLab 命令:Offset
ShaderLab 命令:UsePass