Thanks for refactoring my code! Much appreciated. What I’m having issues with is getting the stencil buffer to do its rendering within the circle
I have the stencil added in my custom shader:
Shader "Custom/NewSurfaceShader" {
Properties{
_Color("Color", Color) = (1,1,1,1)
_MainTex("Albedo (RGB)", 2D) = "white" {}
_Glossiness("Smoothness", Range(0,1)) = 0.5
_Metallic("Metallic", Range(0,1)) = 0.0
_PBRReality("PBR Reality", 2D) = "white" {}
_PBRRealm("PBR Realm", 2D) = "white" {}
_StencilTex("Stencil Texture", 2D) = "white" {}
}
SubShader{
Tags {"RenderType" = "Opaque" "Queue" = "Geometry"}
LOD 100
Pass{
Stencil {
Ref 1
Comp always
Pass replace
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _PBRReality;
sampler2D _PBRRealm;
sampler2D _StencilTex;
float _PlayerLayer;
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target{
fixed4 finalColor;
if (_PlayerLayer == 0.0) {
finalColor = tex2D(_PBRReality, i.uv);
} else {
finalColor = tex2D(_PBRRealm, i.uv);
}
fixed stencilValue = tex2D(_StencilTex, i.uv).r;
finalColor.a *= stencilValue;
return finalColor;
}
ENDCG
}
}
FallBack "Diffuse"
}
And then referenced in the Linger coroutine:
private IEnumerator Linger()
{
Vector3 center = GetCenter();
GameObject portal = new GameObject("Portal");
portal.transform.position = center;
portal.AddComponent<MeshFilter>();
MeshRenderer meshRenderer = portal.AddComponent<MeshRenderer>();
Mesh mesh = CreateMesh();
portal.GetComponent<MeshFilter>().mesh = mesh;
Material material = new Material(Shader.Find("Custom/NewSurfaceShader"));
meshRenderer.material = material;
// Set the initial stencil parameters for the portal
material.SetInt("_StencilComp", (int)UnityEngine.Rendering.CompareFunction.Always);
material.SetInt("_StencilOp", (int)UnityEngine.Rendering.StencilOp.Replace);
material.SetInt("_StencilWriteMask", 0xFF);
material.SetInt("_StencilRef", 1);
// Set the player layer float based on the current layer of the player
int playerLayer = player.layer;
float playerLayerFloat = playerLayer == LayerMask.NameToLayer("Realm") ? 1.0f : 0.0f;
material.SetFloat("_PlayerLayer", playerLayerFloat);
yield return new WaitForSeconds(lingerTime);
// Set stencil comparison function to equal and stencil reference to 1
material.SetInt("_StencilComp", (int)UnityEngine.Rendering.CompareFunction.Equal);
material.SetInt("_StencilRef", 1);
// Destroy the portal and clear the line renderer
line.positionCount = 0;
Destroy(portal);
}
The Portal gameobject is created along the lines of the drawn shape, but nothing changes as far as rendering it goes. Is there something in the camera settings that needs to be adjusted to render the stencil mask? Also, as far as I understand, stencil buffer is a way for part of one camera to be rendered differently, so this method doesn’t require a separate camera to render it, correct?
I’m on standard 2D project, do I need URP for this to work?