文章目录
模板缓存(stencil buffer)
模板缓存通常作为用来作为每个像素的掩码来觉得是否丢弃该像素的数据。
模板缓冲区通常是每像素8位整数。该值可以被写入、递增或递减。随后的绘制调用可以根据该值进行测试,以确定在运行像素着色器之前是否应该丢弃像素。
语法
-
Ref
Ref referenceValue:要比较的值和/或者要写入缓冲区的值。 -
ReadMask
ReadMask readMask:8bit 的掩码范围是0-255的整形。用于将参考值与缓冲区的内容进行比较 (referenceValue & readMask) comparisonFunction (stencilBufferValue & readMask)。默认255。 -
WriteMask
WriteMask writeMask:作为0-255整数的8位掩码,在写入缓冲区时使用。注意,与其他写掩码一样,它指定哪些模板缓冲区位将受到写的影响(即WriteMask 0表示没有位受到影响,也不会写入0)。默认值:255。 -
Comp
Comp comparisonFunction:用于将参考值与缓冲区的当前内容进行比较的函数。默认值:always。 -
Pass
Pass stencilOperation:如果模板测试(和深度测试)通过,该如何处理缓冲区的内容。默认值:keep。 -
Fail
== Fail stencilOperation==:如果模板测试失败,该如何处理缓冲区的内容。默认值:keep。 -
ZFail
ZFail stencilOperation:如果模板测试通过,但深度测试失败,该如何处理缓冲区的内容。默认值:keep。
Comp、Pass、Fail和ZFail将应用于几何图形的front-face。如果Cull Front指定了,则是几何图形的back-face。您还可以通过定义CompFront、PassFront、FailFront、ZFailFront(用于前面的几何图形)和CompBack、PassBack、FailBack、ZFailBack(用于后面的几何图形)来显式指定双面模具状态。
例子
第一个示例着色器将在深度测试通过的地方写入值“2”。模板测试设置为总是通过
Shader "Red" {
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
Pass {
Stencil {
Ref 2
Comp always
Pass replace
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
half4 frag(v2f i) : SV_Target {
return half4(1,0,0,1);
}
ENDCG
}
}
}
第二个着色器将只传递第一个(红色)着色器传递的像素,因为它正在检查与值“2”是否相等。它还将在缓冲区中任何Z测试失败的地方递减该值。
Shader "Green" {
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry+1"}
Pass {
Stencil {
Ref 2
Comp equal
Pass keep
ZFail decrWrap
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
half4 frag(v2f i) : SV_Target {
return half4(0,1,0,1);
}
ENDCG
}
}
}
第三个着色器只会在模板值为“1”的地方传递,所以只有红色和绿色球体交点的像素—也就是说,模板被红色着色器设置为“2”,被绿色着色器减少为“1”
Shader "Blue" {
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry+2"}
Pass {
Stencil {
Ref 1
Comp equal
}
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
half4 frag(v2f i) : SV_Target {
return half4(0,0,1,1);
}
ENDCG
}
}
}