El buffer de stencil (plantilla) se puede utilizar como una máscara de propósito general por píxel para guardar o descartar píxeles.
El buffer de la plantilla es normalmente un entero de 8 bits por píxel. El valor se puede escribir para incrementar o decrementar. Las llamadas de dibujo posteriores pueden probar contra el valor, para decidir si un píxel debe descartarse antes de ejecutar el pixel shader.
Ref referenceValue
El valor con el que se comparará (si Comp es algo más que always) y/o el valor que se escribirá en el buffer (si se cambia Pass, Fail o ZFail). 0–255 entero.
ReadMask readMask
Una máscara de 8 bits como un entero 0–255, que se utiliza al comparar el valor de referencia con el contenido del buffer (referenceValue & readMask) comparisonFunction (stencilBufferValue & readMask). Predeterminado: 255.
WriteMask writeMask
An 8 bit mask as an 0–255 integer, used when writing to the buffer. Note that, like other write masks, it specifies which bits of stencil buffer will be affected by write (i.e. WriteMask 0 means that no bits are affected and not that 0 will be written). Default: 255.
Comp comparisonFunction
Función utilizada para comparar el valor de referencia con el contenido actual del buffer. Predeterminado: always.
Pass stencilOperation
Qué hacer con el contenido de la memoria intermedia si la prueba de stencil (plantilla) (y la prueba de profundidad) pasa. Predeterminado: keep.
Fail stencilOperation
Qué hacer con el contenido del buffer si la prueba del stencil (plantilla) falla. Predeterminado: keep.
ZFail stencilOperation
Qué hacer con el contenido de la memoria intermedia si la prueba del stencil (plantilla) pasa, pero la prueba de profundidad falla. Predeterminado: keep.
Comp, Pass, Fail y ZFail se aplicarán a la geometría frontal, a menos que se especifique Cull Front, en cuyo caso es la geometría orientada hacia atrás. También puede especificar explícitamente el estado del stencil de dos caras definiendo CompFront, PassFront, FailFront, ZFailFront (para geometría frontal) y CompBack, PassBack, FailBack, ZFailBack (para la geometría orientada hacia atrás).
La función de comparación es una de las siguientes:
Greater | Sólo renderiza píxeles cuyo valor de referencia sea mayor al valor en el buffer. |
GEqual | Sólo renderiza píxeles cuyo valor de referencia sea mayor o igual al valor en el buffer. |
Less | Sólo renderiza píxeles cuyo valor de referencia sea menor al valor en el buffer. |
LEqual | Sólo renderiza píxeles cuyo valor de referencia sea menor o igual al valor en el buffer. |
Equal | Sólo renderiza píxeles cuyo valor de referencia sea igual al valor en el buffer. |
NotEqual | Sólo renderiza píxeles cuyo valor de referencia difiera al valor en el buffer. |
Always | Haga que la prueba del stencil (plantilla) siempre pase. |
Never | Hace que la prueba de stencil (plantilla) siempre falle. |
Operación Stencil es una de las siguientes:
Keep | Mantiene el contenido actual del buffer. |
Zero | Escribo 0 al buffer. |
Replace | Escribe el valor de referencia al buffer. |
IncrSat | Incrementa el valor actual en el buffer. Si el valor es 255 ya, permanece en 255. |
DecrSat | Reduce el valor actual en el buffer. Si el valor es 0 ya, se mantiene en 0. |
Invert | Niega todos los bits. |
IncrWrap | Incrementa el valor actual en el buffer. Si el valor es 255, se convierte en 0. |
DecrWrap | Reduce el valor actual en el buffer. Si el valor es 0, se convierte en 255. |
La funcionalidad del stencil para objetos procesados en el deferred rendering path es algo limitada, ya que durante el pass base y el pass de iluminación, el buffer del stencil se utiliza para otros fines. Durante esas dos etapas, el estado del stencil definido en el shader será ignorado y solo se tendrá en cuenta durante el pass final. Debido a esto no es posible enmascarar estos objetos basados en una prueba de stencil, pero todavía pueden modificar el contenido del buffer, para ser utilizados por los objetos que se muestran más adelante en el frame. Los objetos renderizados en forward rendering path siguiendo el deferred path (por ejemplo, objetos transparentes u objetos sin un surface shader) establecerán su estado del stencil (plantilla) normalmente de nuevo.
El deferred rendering path utiliza los tres bits más altos del buffer del stencil, además de hasta cuatro bits más altos, dependiendo de cuántas mask layers de luz se utilizan en la escena. Es posible operar dentro del rango de los bits “limpios” usando las máscaras de lectura y escritura del stencil, o puede forzar a la cámara a limpiar el buffer del stencil después del paso de iluminación usando Camera.clearStencilAfterLightingPass.
The first example shader will write the value ‘2’ wherever the depth test passes. The stencil test is set to always pass.
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
}
}
}
El segundo shader pasará sólo para los píxeles que pasó el primer shader (rojo), porque está comprobando la igualdad con el valor ‘2’. También disminuirá el valor en el buffer dondequiera que falle la prueba de 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
}
}
}
El tercer shader sólo pasará cuando el valor del stencil sea “1”, lo que significa sólo los píxeles en la intersección de las dos esferas rojas y verdes - es decir, donde el stencil se configure en “2” por el shader rojo y se decrementa a “1” Por el shader verde.
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
}
}
}
El resultado:
Otro ejemplo de un efecto más dirigido. La esfera se procesa primero con este shader para marcar las regiones apropiadas en el buffer del stencil:
Shader "HolePrepare" {
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry+1"}
ColorMask 0
ZWrite off
Stencil {
Ref 1
Comp always
Pass replace
}
CGINCLUDE
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,1,0,1);
}
ENDCG
Pass {
Cull Front
ZTest Less
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}
Pass {
Cull Back
ZTest Greater
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}
Y luego se vuelve a presentar como un standard surface shader, con la excepción de la eliminación de la cara frontal, la prueba de profundidad inhabilitada y la prueba del stencil que descartan los píxeles previamente marcados:
Shader "Hole" {
Properties {
_Color ("Main Color", Color) = (1,1,1,0)
}
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry+2"}
ColorMask RGB
Cull Front
ZTest Always
Stencil {
Ref 1
Comp notequal
}
CGPROGRAM
#pragma surface surf Lambert
float4 _Color;
struct Input {
float4 color : COLOR;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = _Color.rgb;
o.Normal = half3(0,0,-1);
o.Alpha = 1;
}
ENDCG
}
}
El resultado: