You can use the stencil bufferA memory store that holds an 8-bit per-pixel value. In Unity, you can use a stencil buffer to flag pixels, and then only render to pixels that pass the stencil operation. More info
See in Glossary as a general purpose per pixelThe smallest unit in a computer image. Pixel size depends on your screen resolution. Pixel lighting is calculated at every screen pixel. More info
See in Glossary mask for saving or discarding pixels.
The stencil buffer is usually an 8 bit integer per pixel. The value can be written to, increment or decremented. Subsequent draw calls can test against the value, to decide if a pixel should be discarded before running the pixel shaderA small script that contains the mathematical calculations and algorithms for calculating the Color of each pixel rendered, based on the lighting input and the Material configuration. More info
See in Glossary.
Ref referenceValue
The value to be compared against (if Comp is anything else than always) and/or the value to be written to the buffer (if either Pass, Fail or ZFail is set to replace). 0–255 integer.
ReadMask readMask
An 8 bit mask as an 0–255 integer, used when comparing the reference value with the contents of the buffer (referenceValue & readMask) comparisonFunction (stencilBufferValue & readMask). Default: 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
The function used to compare the reference value to the current contents of the buffer. Default: always.
Pass stencilOperation
What to do with the contents of the buffer if the stencil test (and the depth test) passes. Default: keep.
Fail stencilOperation
What to do with the contents of the buffer if the stencil test fails. Default: keep.
ZFail stencilOperation
What to do with the contents of the buffer if the stencil test passes, but the depth test fails. Default: keep.
Comp, Pass, Fail and ZFail will be applied to the front-facing geometry, unless Cull Front is specified, in which case it’s back-facing geometry. You can also explicitly specify the two-sided stencil state by defining CompFront, PassFront, FailFront, ZFailFront (for front-facing geometry), and CompBack, PassBack, FailBack, ZFailBack (for back-facing geometry).
Comparison function is one of the following:
Greater | Only render pixels whose reference value is greater than the value in the buffer. |
GEqual | Only render pixels whose reference value is greater than or equal to the value in the buffer. |
Less | Only render pixels whose reference value is less than the value in the buffer. |
LEqual | Only render pixels whose reference value is less than or equal to the value in the buffer. |
Equal | Only render pixels whose reference value equals the value in the buffer. |
NotEqual | Only render pixels whose reference value differs from the value in the buffer. |
Always | Make the stencil test always pass. |
Never | Make the stencil test always fail. |
Stencil operation is one of the following:
Keep | Keep the current contents of the buffer. |
Zero | Write 0 into the buffer. |
Replace | Write the reference value into the buffer. |
IncrSat | Increment the current value in the buffer. If the value is 255 already, it stays at 255. |
DecrSat | Decrement the current value in the buffer. If the value is 0 already, it stays at 0. |
Invert | Negate all the bits. |
IncrWrap | Increment the current value in the buffer. If the value is 255 already, it becomes 0. |
DecrWrap | Decrement the current value in the buffer. If the value is 0 already, it becomes 255. |
Stencil functionality for objects rendered in the deferred rendering path is somewhat limited, as during the G-buffer pass and lighting pass, Unity uses the stencil buffer for other purposes. During those two stages, the stencil state defined in the shader will be ignored. Because of that, you cannot mask out these objects based on a stencil test, but they can still modify the buffer contents, to be used by objects rendered later in the frame. Objects rendered in the forward renderingA rendering path that renders each object in one or more passes, depending on lights that affect the object. Lights themselves are also treated differently by Forward Rendering, depending on their settings and intensity. More info
See in Glossary path following the deferred path (e.g. transparent objects or objects without a surface shader) will set their stencil state normally again.
These bits are used for the stencil buffer in the deferred renderingThe process of drawing graphics to the screen (or to a render texture). By default, the main camera in Unity renders its view to the screen. More info
See in Glossary path:
It is possible to operate within the range of the unused bits using the stencil read and write masks, or you can force the cameraA component which creates an image of a particular viewpoint in your scene. The output is either drawn to the screen or captured as a texture. More info
See in Glossary to clean the stencil buffer after the lighting pass using 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
}
}
}
The second shader will pass only for the pixels which the first (red) shader passed, because it is checking for equality with the value ‘2’. It will also decrement the value in the buffer wherever it fails the Z test.
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
}
}
}
The third shader will only pass wherever the stencil value is ‘1’, so only pixels at the intersection of both red and green spheres - that is, where the stencil is set to ‘2’ by the red shader and decremented to ‘1’ by the green shader.
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
}
}
}
The result:
Another example of a more directed effect. The sphere is first rendered with this shader to mark-up the proper regions in the stencil buffer:
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
}
}
}
And then rendered once more as a fairly standard surface shaderUnity’s code generation approach that makes it much easier to write lit shaders than using low level vertex/pixel shader programs. More info
See in Glossary, with the exception of front face culling, disabled depth test and stencil test discarding previously marked pixels:
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
}
}
The result:
When you visit any website, it may store or retrieve information on your browser, mostly in the form of cookies. This information might be about you, your preferences or your device and is mostly used to make the site work as you expect it to. The information does not usually directly identify you, but it can give you a more personalized web experience. Because we respect your right to privacy, you can choose not to allow some types of cookies. Click on the different category headings to find out more and change our default settings. However, blocking some types of cookies may impact your experience of the site and the services we are able to offer.
More information
These cookies enable the website to provide enhanced functionality and personalisation. They may be set by us or by third party providers whose services we have added to our pages. If you do not allow these cookies then some or all of these services may not function properly.
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us to know which pages are the most and least popular and see how visitors move around the site. All information these cookies collect is aggregated and therefore anonymous. If you do not allow these cookies we will not know when you have visited our site, and will not be able to monitor its performance.
These cookies may be set through our site by our advertising partners. They may be used by those companies to build a profile of your interests and show you relevant adverts on other sites. They do not store directly personal information, but are based on uniquely identifying your browser and internet device. If you do not allow these cookies, you will experience less targeted advertising. Some 3rd party video providers do not allow video views without targeting cookies. If you are experiencing difficulty viewing a video, you will need to set your cookie preferences for targeting to yes if you wish to view videos from these providers. Unity does not control this.
These cookies are necessary for the website to function and cannot be switched off in our systems. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms. You can set your browser to block or alert you about these cookies, but some parts of the site will not then work. These cookies do not store any personally identifiable information.