I’m making AR app, where user can place a model (basically a mesh loaded from OBJ file) over a plane detected by AR. For better user experience, the app should render the part of the model below the plane with transparency, so that user can clearly see, whether the model is below/above the ground. Additionally, the AR plane itself should not be visible.
I’ve been lurking this forum a lot and read Cg Programming/Unity/Outlining_Objects, to get more understanding of shaders and stencil buffer. And what I understood, is that the shader for AR plane should write to stencil buffer, while the model shader should check the buffer to determine how to render.
But I still can’t make it work properly. Here is what I’ve got so far.
The ground plane shader writes stencil buffer and simply makes the plane transparent (alpha = 0):
Shader "Plane"
{
SubShader
{
Tags
{
"RenderType" = "Transparent"
"Queue" = "Transparent-10"
}
Pass
{
Cull Off
Blend SrcAlpha OneMinusSrcAlpha
Stencil {
Ref 1
Comp Always
Pass Replace
}
ZWrite On
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 pos : SV_POSITION;
};
v2f vert(appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
half4 frag(v2f i) : COLOR
{
return float4(1.0, 1.0, 1.0, 0.0);
}
ENDCG
}
}
}
The model shader should make the part of the model below the plane 50% transparent, the part above the plane opaque. For this reason the shader has a two passes. The first pass handles the part of the model below the plane, that is, the transparent part. The second pass handles the part of the model above the plane, that is, the opaque part.
Shader "Model"
{
SubShader
{
Tags
{
"RenderType" = "Transparent"
"Queue" = "Transparent"
}
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
Stencil
{
Ref 1
Comp Equal
Pass Keep
}
ZTest Always
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(vertexPos);
}
float4 frag(void) : COLOR
{
return float4(0.0, 1.0, 0.0, 0.5);
}
ENDCG
}
Pass
{
Stencil
{
Ref 1
Comp NotEqual
Pass Keep
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(vertexPos);
}
float4 frag(void) : COLOR
{
return float4(0.0, 1.0, 0.0, 1);
}
ENDCG
}
}
}
Here is how it looks:

The plane cuts the cube by half horizontally, e.g. they both have pivot 0.5, 0.5, 0.5 and position 0, 0, 0).
As I understand, I made a typical “see through walls”, but I rather need the model to be cut by the AR plane into two parts: transparent (below the plane) and opaque (above the plane).
I’m starting to think, that stencil is not really fits here. Should it be done based on ZWrite/ZTest somehow?
Can anyone help me with this or point what to read?
