转自:Unity Shader中的模板测试(Stencil) - 知乎
模板测试 发生在片元着色器之后的逐片元操作阶段:
透明度测试——>模板测试——>深度测试——>透明度混合
_StencilComp("Stencil Comparison", Float) = 8 //只有深度值大于或等于8的像素才会被写入到模板缓冲区。
_Stencil("Stencil ID", Float) = 0 //模板测试开关 当模板值为0时,表示不进行模板测试操作。当模板值为1时,表示进行模板测试操作。
_StencilOp("Stencil Operation", Float) = 0 // 模板操作函数为0
/*
_StencilWriteMask是一个用于控制模板缓冲区写入操作的掩码。它是一个8位的整数,通常用于指定哪些模板缓冲区位将受到写操作的影响。
*/
_StencilWriteMask("Stencil Write Mask", Float) = 255
/*
_StencilReadMask是一个8位的整数,用于在比较参考值(referenceValue)和模板缓存的值(stencilBufferValue)时进行掩码操作。
在进行比较操作时,会将参考值与模板缓存的值进行按位与(&)运算,然后使用_StencilReadMask进行掩码过滤。
例如,如果_StencilReadMask的值为255(二进制位11111111),表示所有位都可以通过掩码,即比较操作不受任何限制。
如果_StencilReadMask的值为0(二进制位00000000),则表示没有任何位可以通过掩码,即比较操作将被禁用。
*/
_StencilReadMask("Stencil Read Mask", Float) = 255
_ColorMask("Color Mask", Float) = 15 //0b1111,每个位代表一个特定的颜色通道。在15这个值中,每个位都被设置为1,表示红、绿、蓝和alpha所有通道都被打开。
Stencil
{
Ref [_Stenail]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
用法
此命令会改变渲染状态。在PASS块中,为该通道设置渲染状态;在SubShader块中,为该块中所有PASS设置渲染状态。
使用 Ref、ReadMask、Comp 参数配置模板测试。
使用 Ref、WriteMask、Pass、Fail、ZFail 参数配置测试后的模板写入操作。
模板测试方程:(ref & readMask) comparisonFunction (stencilBufferValue & readMask)
(例:配置ref = 1,readmask = 255,comparisonFunction = less,stencilBufferValue = 2,result = (1&255)<(2&255) = true,通过测试,执行Pass配置的操作)
参数列表
请注意,所有参数都是可选的。
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 [_ZFail] //_ZFail作为参数传入时
}
参数详解
ref:0-255的整数,默认为0。作为参考值,与 stencil buffer 中的值进行比较。并在测试执行后根据 Pass、Fail 或 ZFail 指定的规则决定此值是否写入 buffer 中。
readMask:0-255的整数,默认为255。执行模板测试时使用此值作为遮罩。
writeMask:0-255的整数,默认为255。写入 stencil buffer 时使用此值作为遮罩。请注意,它指定操作中包含的位(值为 0 表示写入操作中不包含任何位,而不是模板缓冲区接收值 0)。例如,当前缓冲区的值是1,在Pass后执行的操作是 IncrSat ,但是 writeMask = 0,则完成后,缓冲区的值仍为 1。
comparisonOperation:定义模板测试执行的比较方法。与朝向无关。且会覆盖 comparationOperationBack 和 comparationOperationFront。
passOperation:当像素通过模板测试和深度测试时,GPU 对模板缓冲区执行的操作。与朝向无关。且会覆盖 passOperationBack 和 passOperationFront。
failOperation:当像素未能通过模板测试时,GPU 对模板缓冲区执行的操作。与朝向无关。且会覆盖 failOperation 和 failOperation。
zFailOperation:当像素通过模板测试,但是未能通过深度测试时,GPU 对模板缓冲区执行的操作。与朝向无关。且会覆盖 zFailOperation 和 zFailOperation。
带 Back 后缀的参数,表示定义的操作仅适用于背面像素。
带 Front 后缀的参数,表示定义的操作仅适用于正面像素。
值参考表
比较操作值
值 | Rendering.CompareFunction 枚举中的对应整数值 | 功能 |
Never | 1 | 从不渲染像素。 |
Less | 2 | 在参考值小于模板缓冲区中的当前值时渲染像素。 |
Equal | 3 | 在参考值等于模板缓冲区中的当前值时渲染像素。 |
LEqual | 4 | 在参考值小于或等于模板缓冲区中的当前值时渲染像素。 |
Greater | 5 | 在参考值大于模板缓冲区中的当前值时渲染像素。 |
NotEqual | 6 | 在参考值与模板缓冲区中的当前值不同时渲染像素。 |
GEqual | 7 | 在参考值大于或等于模板缓冲区中的当前值时渲染像素。 |
Always | 8 | 始终渲染像素。 |
模板操作值
值 | Rendering.StencilOp 枚举中的对应整数值 | 功能 |
Keep | 0 | 保持模板缓冲区的当前内容。 |
Zero | 1 | 将 0 写入模板缓冲区。 |
Replace | 2 | 将参考值写入缓冲区。 |
IncrSat | 3 | 递增缓冲区中的当前值。如果该值已经是 255,则保持为 255。 |
DecrSat | 4 | 递减缓冲区中的当前值。如果该值已经是 0,则保持为 0。 |
Invert | 5 | 将缓冲区中当前值的所有位求反。 |
IncrWrap | 6 | 递增缓冲区中的当前值。如果该值已经是 255,则变为 0。 |
DecrWrap | 7 | 递减缓冲区中的当前值。如果该值已经是 0,则变为 255。 |