diff --git a/Assets/Materials/Hero Cutout Occluder.mat b/Assets/Materials/Hero Cutout Occluder.mat
new file mode 100644
index 0000000..ae6d770
--- /dev/null
+++ b/Assets/Materials/Hero Cutout Occluder.mat
@@ -0,0 +1,123 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!21 &2100000
+Material:
+ serializedVersion: 8
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_Name: Hero Cutout Occluder
+ m_Shader: {fileID: 4800000, guid: 023c98a32f6cc00478e50479839530c5, type: 3}
+ m_Parent: {fileID: 0}
+ m_ModifiedSerializedProperties: 0
+ m_ValidKeywords: []
+ m_InvalidKeywords: []
+ m_LightmapFlags: 4
+ m_EnableInstancingVariants: 0
+ m_DoubleSidedGI: 0
+ m_CustomRenderQueue: -1
+ stringTagMap:
+ RenderType: Opaque
+ disabledShaderPasses: []
+ m_LockedProperties:
+ m_SavedProperties:
+ serializedVersion: 3
+ m_TexEnvs:
+ - _BaseMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _BumpMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailAlbedoMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailMask:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _DetailNormalMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _EmissionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MainTex:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _MetallicGlossMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _OcclusionMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _ParallaxMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - _SpecGlossMap:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - unity_Lightmaps:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - unity_LightmapsInd:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ - unity_ShadowMasks:
+ m_Texture: {fileID: 0}
+ m_Scale: {x: 1, y: 1}
+ m_Offset: {x: 0, y: 0}
+ m_Ints: []
+ m_Floats:
+ - _AddPrecomputedVelocity: 0
+ - _AlphaClip: 0
+ - _AlphaToMask: 0
+ - _Blend: 0
+ - _BlendModePreserveSpecular: 1
+ - _BumpScale: 1
+ - _ClearCoatMask: 0
+ - _ClearCoatSmoothness: 0
+ - _Cull: 2
+ - _Cutoff: 0.5
+ - _DetailAlbedoMapScale: 1
+ - _DetailNormalMapScale: 1
+ - _DstBlend: 0
+ - _DstBlendAlpha: 0
+ - _EnvironmentReflections: 1
+ - _GlossMapScale: 0
+ - _Glossiness: 0
+ - _GlossyReflections: 0
+ - _Metallic: 0
+ - _OcclusionStrength: 1
+ - _Parallax: 0.005
+ - _QueueOffset: 0
+ - _ReceiveShadows: 1
+ - _Smoothness: 0.5
+ - _SmoothnessTextureChannel: 0
+ - _SpecularHighlights: 1
+ - _SrcBlend: 1
+ - _SrcBlendAlpha: 1
+ - _Surface: 0
+ - _WorkflowMode: 1
+ - _XRMotionVectorsPass: 1
+ - _ZWrite: 1
+ m_Colors:
+ - _BaseColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
+ - _Color: {r: 0.5, g: 0.5, b: 0.5, a: 1}
+ - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
+ - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
+ m_BuildTextureStacks: []
+ m_AllowLocking: 1
diff --git a/Assets/Materials/Hero Cutout Occluder.mat.meta b/Assets/Materials/Hero Cutout Occluder.mat.meta
new file mode 100644
index 0000000..7569908
--- /dev/null
+++ b/Assets/Materials/Hero Cutout Occluder.mat.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 284ac320f0449154dae9b92d90f5550b
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 2100000
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scenes/Lobby.unity b/Assets/Scenes/Lobby.unity
index d72cce8..a5d4aca 100644
--- a/Assets/Scenes/Lobby.unity
+++ b/Assets/Scenes/Lobby.unity
@@ -184,7 +184,7 @@ MeshRenderer:
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ - {fileID: 2100000, guid: 284ac320f0449154dae9b92d90f5550b, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
@@ -296,7 +296,7 @@ MeshRenderer:
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ - {fileID: 2100000, guid: 284ac320f0449154dae9b92d90f5550b, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
@@ -408,7 +408,7 @@ MeshRenderer:
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ - {fileID: 2100000, guid: 284ac320f0449154dae9b92d90f5550b, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
@@ -520,7 +520,7 @@ MeshRenderer:
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ - {fileID: 2100000, guid: 284ac320f0449154dae9b92d90f5550b, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
@@ -632,7 +632,7 @@ MeshRenderer:
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ - {fileID: 2100000, guid: 284ac320f0449154dae9b92d90f5550b, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
@@ -856,7 +856,7 @@ MeshRenderer:
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ - {fileID: 2100000, guid: 284ac320f0449154dae9b92d90f5550b, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
@@ -968,7 +968,7 @@ MeshRenderer:
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2}
+ - {fileID: 2100000, guid: 284ac320f0449154dae9b92d90f5550b, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
diff --git a/Assets/Scenes/Main.unity b/Assets/Scenes/Main.unity
index 4ad0749..7f970b6 100644
--- a/Assets/Scenes/Main.unity
+++ b/Assets/Scenes/Main.unity
@@ -1823,6 +1823,7 @@ GameObject:
m_Component:
- component: {fileID: 1516578028}
- component: {fileID: 1516578027}
+ - component: {fileID: 1516578029}
m_Layer: 0
m_Name: GameManager
m_TagString: Untagged
@@ -1864,6 +1865,24 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1516578029
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1516578026}
+ m_Enabled: 0
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: c7d67030b8dcdec489471b88c35dd78b, type: 3}
+ m_Name:
+ m_EditorClassIdentifier: Assembly-CSharp::HeroCutout
+ orbitInput: {fileID: 0}
+ modes: {fileID: 0}
+ radius: 0.3
+ feather: 0.1
+ depthBias: 0.5
+ heightOffset: 0
--- !u!21 &1752619484
Material:
serializedVersion: 8
diff --git a/Assets/Scripts/HeroCutout.cs b/Assets/Scripts/HeroCutout.cs
new file mode 100644
index 0000000..057c044
--- /dev/null
+++ b/Assets/Scripts/HeroCutout.cs
@@ -0,0 +1,94 @@
+using UnityEngine;
+using Unity.Cinemachine;
+
+///
+/// Drives the screen-space radial "hero cutout". Every late frame it projects the local player to
+/// screen space and feeds that position + a circle radius/feather + the player's eye-space depth into
+/// two global shader properties (_HeroCutoutPosRadius, _HeroCutoutDepthOn) that the
+/// Custom/HeroCutoutLit shader reads to clip occluder geometry between the camera and the
+/// player - punching a soft see-through hole toward the character.
+///
+/// The effect is only armed while the third-person orbit is the live
+/// Cinemachine camera (i.e. Player Control / Paint mode). In first-person, free-cam, or while a menu
+/// is open a different vcam is live, so the cutout disarms and occluders render solid. Disarming sets
+/// the global "enabled" flag to 0, which also matches the zero-initialised default - so any scene
+/// without this driver leaves cutout materials looking exactly like URP/Lit.
+///
+/// Attach to a persistent scene object (e.g. the GameModeManager host).
+///
+[DisallowMultipleComponent]
+public class HeroCutout : MonoBehaviour
+{
+ [Tooltip("Orbit camera input whose CinemachineCamera must be live for the cutout to arm. Empty = found automatically.")]
+ public ThirdPersonOrbitInput orbitInput;
+
+ [Tooltip("Game mode manager, used as a fallback source for the live player. Empty = found automatically.")]
+ public GameModeManager modes;
+
+ [Header("Circle")]
+ [Tooltip("Radius of the see-through circle, as a fraction of screen height (0.13 = 13% of height).")]
+ [Range(0.02f, 0.6f)] public float radius = 0.13f;
+
+ [Tooltip("Soft-edge width of the circle, as a fraction of screen height.")]
+ [Range(0f, 0.3f)] public float feather = 0.05f;
+
+ [Tooltip("Metres added to the player's depth so geometry right at the player isn't clipped away.")]
+ public float depthBias = 0.5f;
+
+ [Tooltip("Vertical offset (m) from the follow target where the circle centres (chest/head height).")]
+ public float heightOffset = 0f;
+
+ static readonly int PosRadiusId = Shader.PropertyToID("_HeroCutoutPosRadius");
+ static readonly int DepthOnId = Shader.PropertyToID("_HeroCutoutDepthOn");
+
+ private CinemachineCamera _orbitCam;
+ private CinemachineBrain _brain;
+
+ private void Awake()
+ {
+ if (!orbitInput) orbitInput = FindFirstObjectByType(FindObjectsInactive.Include);
+ if (!modes) modes = FindFirstObjectByType();
+ if (orbitInput) _orbitCam = orbitInput.GetComponent();
+ }
+
+ private void OnDisable() => Disarm();
+
+ private void LateUpdate()
+ {
+ Camera cam = Camera.main;
+ if (!cam) { Disarm(); return; }
+
+ if (!_brain || _brain.gameObject != cam.gameObject)
+ _brain = cam.GetComponent();
+
+ if (!IsThirdPersonLive()) { Disarm(); return; }
+
+ Transform target = ResolveHeroTarget();
+ if (!target) { Disarm(); return; }
+
+ Vector3 heroPos = target.position + Vector3.up * heightOffset;
+ Vector3 vp = cam.WorldToViewportPoint(heroPos);
+ if (vp.z <= 0f) { Disarm(); return; } // hero is behind the camera
+
+ Shader.SetGlobalVector(PosRadiusId, new Vector4(vp.x, vp.y, radius, Mathf.Max(feather, 1e-4f)));
+ Shader.SetGlobalVector(DepthOnId, new Vector4(vp.z + depthBias, 1f, 0f, 0f));
+ }
+
+ /// True only when the orbit vcam is the live Cinemachine camera (third-person modes).
+ private bool IsThirdPersonLive()
+ {
+ if (!_orbitCam || !_brain) return false;
+ var live = _brain.ActiveVirtualCamera as CinemachineCamera;
+ return live && live == _orbitCam;
+ }
+
+ private Transform ResolveHeroTarget()
+ {
+ if (_orbitCam && _orbitCam.Follow) return _orbitCam.Follow;
+ if (modes && modes.Player) return modes.Player.transform;
+ return null;
+ }
+
+ /// Clears the "enabled" flag so cutout materials render as plain URP/Lit.
+ private void Disarm() => Shader.SetGlobalVector(DepthOnId, Vector4.zero);
+}
diff --git a/Assets/Scripts/HeroCutout.cs.meta b/Assets/Scripts/HeroCutout.cs.meta
new file mode 100644
index 0000000..b3f46ea
--- /dev/null
+++ b/Assets/Scripts/HeroCutout.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: c7d67030b8dcdec489471b88c35dd78b
\ No newline at end of file
diff --git a/Assets/Shaders/HeroCutout.hlsl b/Assets/Shaders/HeroCutout.hlsl
new file mode 100644
index 0000000..584bc7d
--- /dev/null
+++ b/Assets/Shaders/HeroCutout.hlsl
@@ -0,0 +1,46 @@
+#ifndef HERO_CUTOUT_INCLUDED
+#define HERO_CUTOUT_INCLUDED
+
+// Screen-space radial "hero cutout": clips occluder fragments that sit inside a circle around the
+// on-screen player AND in front of it, punching a clean see-through hole toward the character.
+//
+// These two globals are driven every frame by HeroCutout.cs (Shader.SetGlobalVector). They live
+// OUTSIDE UnityPerMaterial, so the SRP Batcher is unaffected. When the effect is disabled
+// (_HeroCutoutDepthOn.y < 0.5, also the zero-initialised default) ApplyHeroCutout early-outs and the
+// shader renders exactly like URP/Lit.
+// _HeroCutoutPosRadius : xy = hero viewport pos (0..1, bottom-left), z = radius, w = feather
+// radius/feather are in normalized viewport-HEIGHT units
+// _HeroCutoutDepthOn : x = hero eye-space depth (incl. bias), y = enabled (0/1)
+float4 _HeroCutoutPosRadius;
+float4 _HeroCutoutDepthOn;
+
+// Interleaved-gradient noise -> screen-door dither, gives the circle a soft edge with no extra
+// textures or includes.
+float HeroCutoutDither(float2 positionSS)
+{
+ return frac(52.9829189 * frac(dot(positionSS, float2(0.06711056, 0.00583715))));
+}
+
+void ApplyHeroCutout(float4 positionCS)
+{
+ if (_HeroCutoutDepthOn.y < 0.5)
+ return;
+
+ // Flip-correct screen UV (matches Camera.WorldToViewportPoint's bottom-left convention).
+ float2 uv = GetNormalizedScreenSpaceUV(positionCS);
+ float2 delta = uv - _HeroCutoutPosRadius.xy;
+ delta.x *= _ScreenParams.x / max(_ScreenParams.y, 1.0); // aspect-correct -> a round circle
+ float dist = length(delta);
+
+ float radius = _HeroCutoutPosRadius.z;
+ float feather = max(_HeroCutoutPosRadius.w, 1e-4);
+ float inside = 1.0 - smoothstep(radius - feather, radius, dist); // 1 inside, 0 outside
+
+ // Only hole geometry between the camera and the hero; anything at/behind the player stays solid.
+ float eyeDepth = LinearEyeDepth(positionCS.z, _ZBufferParams);
+ float inFront = step(eyeDepth, _HeroCutoutDepthOn.x);
+
+ float cut = inside * inFront;
+ clip(HeroCutoutDither(positionCS.xy) - cut);
+}
+#endif
diff --git a/Assets/Shaders/HeroCutout.hlsl.meta b/Assets/Shaders/HeroCutout.hlsl.meta
new file mode 100644
index 0000000..5d677b3
--- /dev/null
+++ b/Assets/Shaders/HeroCutout.hlsl.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 8fbf575abd6dde145ac13a28b92a87a0
+ShaderIncludeImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Shaders/HeroCutoutLit.shader b/Assets/Shaders/HeroCutoutLit.shader
new file mode 100644
index 0000000..94b65b3
--- /dev/null
+++ b/Assets/Shaders/HeroCutoutLit.shader
@@ -0,0 +1,581 @@
+// Drop-in clone of "Universal Render Pipeline/Lit" (URP 17) that adds a screen-space radial
+// "hero cutout": occluder geometry between the third-person camera and the player is clipped away
+// in a soft circle (see HeroCutout.hlsl + HeroCutout.cs).
+//
+// It is a faithful copy of URP's Lit.shader - same properties, keywords and includes, so material
+// values transfer 1:1 and the inspector GUI keeps working. The ONLY change is in four passes
+// (ForwardLit, ShadowCaster, DepthOnly, DepthNormals): the stock fragment entry point is replaced by
+// a thin wrapper that runs ApplyHeroCutout() and then delegates to URP's original fragment. All
+// shading is therefore URP's own - zero reimplementation, so it stays correct across URP updates.
+Shader "Custom/HeroCutoutLit"
+{
+ Properties
+ {
+ // Specular vs Metallic workflow
+ _WorkflowMode("WorkflowMode", Float) = 1.0
+
+ [MainTexture] _BaseMap("Albedo", 2D) = "white" {}
+ [MainColor] _BaseColor("Color", Color) = (1,1,1,1)
+
+ _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
+
+ _Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5
+ _SmoothnessTextureChannel("Smoothness texture channel", Float) = 0
+
+ _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
+ _MetallicGlossMap("Metallic", 2D) = "white" {}
+
+ _SpecColor("Specular", Color) = (0.2, 0.2, 0.2)
+ _SpecGlossMap("Specular", 2D) = "white" {}
+
+ [ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
+ [ToggleOff] _EnvironmentReflections("Environment Reflections", Float) = 1.0
+
+ _BumpScale("Scale", Float) = 1.0
+ _BumpMap("Normal Map", 2D) = "bump" {}
+
+ _Parallax("Scale", Range(0.005, 0.08)) = 0.005
+ _ParallaxMap("Height Map", 2D) = "black" {}
+
+ _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
+ _OcclusionMap("Occlusion", 2D) = "white" {}
+
+ [HDR] _EmissionColor("Color", Color) = (0,0,0)
+ _EmissionMap("Emission", 2D) = "white" {}
+
+ _DetailMask("Detail Mask", 2D) = "white" {}
+ _DetailAlbedoMapScale("Scale", Range(0.0, 2.0)) = 1.0
+ _DetailAlbedoMap("Detail Albedo x2", 2D) = "linearGrey" {}
+ _DetailNormalMapScale("Scale", Range(0.0, 2.0)) = 1.0
+ [Normal] _DetailNormalMap("Normal Map", 2D) = "bump" {}
+
+ // SRP batching compatibility for Clear Coat (Not used in Lit)
+ [HideInInspector] _ClearCoatMask("_ClearCoatMask", Float) = 0.0
+ [HideInInspector] _ClearCoatSmoothness("_ClearCoatSmoothness", Float) = 0.0
+
+ // Blending state
+ _Surface("__surface", Float) = 0.0
+ _Blend("__blend", Float) = 0.0
+ _Cull("__cull", Float) = 2.0
+ [ToggleUI] _AlphaClip("__clip", Float) = 0.0
+ [HideInInspector] _SrcBlend("__src", Float) = 1.0
+ [HideInInspector] _DstBlend("__dst", Float) = 0.0
+ [HideInInspector] _SrcBlendAlpha("__srcA", Float) = 1.0
+ [HideInInspector] _DstBlendAlpha("__dstA", Float) = 0.0
+ [HideInInspector] _ZWrite("__zw", Float) = 1.0
+ [HideInInspector] _BlendModePreserveSpecular("_BlendModePreserveSpecular", Float) = 1.0
+ [HideInInspector] _AlphaToMask("__alphaToMask", Float) = 0.0
+ [HideInInspector] _AddPrecomputedVelocity("_AddPrecomputedVelocity", Float) = 0.0
+ [HideInInspector] _XRMotionVectorsPass("_XRMotionVectorsPass", Float) = 1.0
+
+ [ToggleUI] _ReceiveShadows("Receive Shadows", Float) = 1.0
+ // Editmode props
+ _QueueOffset("Queue offset", Float) = 0.0
+
+ // ObsoleteProperties
+ [HideInInspector] _MainTex("BaseMap", 2D) = "white" {}
+ [HideInInspector] _Color("Base Color", Color) = (1, 1, 1, 1)
+ [HideInInspector] _GlossMapScale("Smoothness", Float) = 0.0
+ [HideInInspector] _Glossiness("Smoothness", Float) = 0.0
+ [HideInInspector] _GlossyReflections("EnvironmentReflections", Float) = 0.0
+
+ [HideInInspector][NoScaleOffset]unity_Lightmaps("unity_Lightmaps", 2DArray) = "" {}
+ [HideInInspector][NoScaleOffset]unity_LightmapsInd("unity_LightmapsInd", 2DArray) = "" {}
+ [HideInInspector][NoScaleOffset]unity_ShadowMasks("unity_ShadowMasks", 2DArray) = "" {}
+ }
+
+ SubShader
+ {
+ Tags
+ {
+ "RenderType" = "Opaque"
+ "RenderPipeline" = "UniversalPipeline"
+ "UniversalMaterialType" = "Lit"
+ "IgnoreProjector" = "True"
+ }
+ LOD 300
+
+ // ------------------------------------------------------------------
+ // Forward pass. Shades all light in a single pass. GI + emission + Fog
+ Pass
+ {
+ Name "ForwardLit"
+ Tags
+ {
+ "LightMode" = "UniversalForward"
+ }
+
+ // -------------------------------------
+ // Render State Commands
+ Blend[_SrcBlend][_DstBlend], [_SrcBlendAlpha][_DstBlendAlpha]
+ ZWrite[_ZWrite]
+ Cull[_Cull]
+ AlphaToMask[_AlphaToMask]
+
+ HLSLPROGRAM
+ #pragma target 2.0
+
+ // -------------------------------------
+ // Shader Stages
+ #pragma vertex LitPassVertex
+ #pragma fragment HeroForwardFragment
+
+ // -------------------------------------
+ // Material Keywords
+ #pragma shader_feature_local _NORMALMAP
+ #pragma shader_feature_local _PARALLAXMAP
+ #pragma shader_feature_local _RECEIVE_SHADOWS_OFF
+ #pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
+ #pragma shader_feature_local_fragment _SURFACE_TYPE_TRANSPARENT
+ #pragma shader_feature_local_fragment _ALPHATEST_ON
+ #pragma shader_feature_local_fragment _ _ALPHAPREMULTIPLY_ON _ALPHAMODULATE_ON
+ #pragma shader_feature_local_fragment _EMISSION
+ #pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
+ #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+ #pragma shader_feature_local_fragment _OCCLUSIONMAP
+ #pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_OFF
+ #pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS_OFF
+ #pragma shader_feature_local_fragment _SPECULAR_SETUP
+
+ // -------------------------------------
+ // Universal Pipeline keywords
+ #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
+ #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
+ #pragma multi_compile _ EVALUATE_SH_MIXED EVALUATE_SH_VERTEX
+ #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
+ #pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
+ #pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
+ #pragma multi_compile_fragment _ _REFLECTION_PROBE_ATLAS
+ #pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
+ #pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
+ #pragma multi_compile_fragment _ _SCREEN_SPACE_IRRADIANCE
+ #pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
+ #pragma multi_compile_fragment _ _LIGHT_COOKIES
+ #pragma multi_compile _ _LIGHT_LAYERS
+ #pragma multi_compile _ _CLUSTER_LIGHT_LOOP
+ #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"
+
+
+ // -------------------------------------
+ // Unity defined keywords
+ #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
+ #pragma multi_compile _ SHADOWS_SHADOWMASK
+ #pragma multi_compile _ DIRLIGHTMAP_COMBINED
+ #pragma multi_compile _ LIGHTMAP_ON
+ #pragma multi_compile_fragment _ LIGHTMAP_BICUBIC_SAMPLING
+ #pragma multi_compile_fragment _ REFLECTION_PROBE_ROTATION
+ #pragma multi_compile _ DYNAMICLIGHTMAP_ON
+ #pragma multi_compile _ USE_LEGACY_LIGHTMAPS
+ #pragma multi_compile _ LOD_FADE_CROSSFADE
+ #pragma multi_compile_fragment _ DEBUG_DISPLAY
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Fog.hlsl"
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ProbeVolumeVariants.hlsl"
+
+ //--------------------------------------
+ // GPU Instancing
+ #pragma multi_compile_instancing
+ #pragma instancing_options renderinglayer
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
+
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitForwardPass.hlsl"
+ #include "HeroCutout.hlsl"
+
+ // Radial cutout, then delegate to URP's stock LitPassFragment for all shading.
+ void HeroForwardFragment(
+ Varyings input
+ , out half4 outColor : SV_Target0
+ #ifdef _WRITE_RENDERING_LAYERS
+ , out uint outRenderingLayers : SV_Target1
+ #endif
+ )
+ {
+ ApplyHeroCutout(input.positionCS);
+ LitPassFragment(input, outColor
+ #ifdef _WRITE_RENDERING_LAYERS
+ , outRenderingLayers
+ #endif
+ );
+ }
+ ENDHLSL
+ }
+
+ Pass
+ {
+ Name "ShadowCaster"
+ Tags
+ {
+ "LightMode" = "ShadowCaster"
+ }
+
+ // -------------------------------------
+ // Render State Commands
+ ZWrite On
+ ZTest LEqual
+ ColorMask 0
+ Cull[_Cull]
+
+ HLSLPROGRAM
+ #pragma target 2.0
+
+ // -------------------------------------
+ // Shader Stages
+ // NOTE: shadows are intentionally NOT cut out. ShadowCaster runs in light clip space,
+ // so the camera-space radial mask in ApplyHeroCutout would be meaningless there (and the
+ // occluder is conceptually "still there", just visually see-through). Stock fragment.
+ #pragma vertex ShadowPassVertex
+ #pragma fragment ShadowPassFragment
+
+ // -------------------------------------
+ // Material Keywords
+ #pragma shader_feature_local _ALPHATEST_ON
+ #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+
+ //--------------------------------------
+ // GPU Instancing
+ #pragma multi_compile_instancing
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
+
+ // -------------------------------------
+ // Universal Pipeline keywords
+
+ // -------------------------------------
+ // Unity defined keywords
+ #pragma multi_compile _ LOD_FADE_CROSSFADE
+
+ // This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
+ #pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
+
+ // -------------------------------------
+ // Includes
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
+ ENDHLSL
+ }
+
+ Pass
+ {
+ Name "GBuffer"
+ Tags
+ {
+ "LightMode" = "UniversalGBuffer"
+ }
+
+ // -------------------------------------
+ // Render State Commands
+ ZWrite[_ZWrite]
+ ZTest LEqual
+ Cull[_Cull]
+
+ HLSLPROGRAM
+ #pragma target 4.5
+
+ // Deferred Rendering Path does not support the OpenGL-based graphics API:
+ // Desktop OpenGL, OpenGL ES 3.0, WebGL 2.0.
+ #pragma exclude_renderers gles3 glcore
+
+ // -------------------------------------
+ // Shader Stages
+ #pragma vertex LitGBufferPassVertex
+ #pragma fragment LitGBufferPassFragment
+
+ // -------------------------------------
+ // Material Keywords
+ #pragma shader_feature_local _NORMALMAP
+ #pragma shader_feature_local_fragment _ALPHATEST_ON
+ //#pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON
+ #pragma shader_feature_local_fragment _EMISSION
+ #pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
+ #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+ #pragma shader_feature_local_fragment _OCCLUSIONMAP
+ #pragma shader_feature_local _PARALLAXMAP
+ #pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
+
+ #pragma shader_feature_local_fragment _SPECULARHIGHLIGHTS_OFF
+ #pragma shader_feature_local_fragment _ENVIRONMENTREFLECTIONS_OFF
+ #pragma shader_feature_local_fragment _SPECULAR_SETUP
+ #pragma shader_feature_local _RECEIVE_SHADOWS_OFF
+
+ // -------------------------------------
+ // Universal Pipeline keywords
+ #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
+ //#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
+ //#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
+ #pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
+ #pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
+ #pragma multi_compile_fragment _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH
+ #pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
+ #pragma multi_compile_fragment _ _RENDER_PASS_ENABLED
+ #pragma multi_compile _ _CLUSTER_LIGHT_LOOP
+ #pragma multi_compile _ EVALUATE_SH_MIXED EVALUATE_SH_VERTEX
+ #include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"
+
+ // -------------------------------------
+ // Unity defined keywords
+ #pragma multi_compile _ LIGHTMAP_SHADOW_MIXING
+ #pragma multi_compile _ SHADOWS_SHADOWMASK
+ #pragma multi_compile _ DIRLIGHTMAP_COMBINED
+ #pragma multi_compile _ LIGHTMAP_ON
+ #pragma multi_compile_fragment _ LIGHTMAP_BICUBIC_SAMPLING
+ #pragma multi_compile_fragment _ REFLECTION_PROBE_ROTATION
+ #pragma multi_compile _ DYNAMICLIGHTMAP_ON
+ #pragma multi_compile _ USE_LEGACY_LIGHTMAPS
+ #pragma multi_compile _ LOD_FADE_CROSSFADE
+ #pragma multi_compile_fragment _ _GBUFFER_NORMALS_OCT
+ #pragma multi_compile_fragment _ _SCREEN_SPACE_IRRADIANCE
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ProbeVolumeVariants.hlsl"
+
+ //--------------------------------------
+ // GPU Instancing
+ #pragma multi_compile_instancing
+ #pragma instancing_options renderinglayer
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
+
+ // -------------------------------------
+ // Includes
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitGBufferPass.hlsl"
+ ENDHLSL
+ }
+
+ Pass
+ {
+ Name "DepthOnly"
+ Tags
+ {
+ "LightMode" = "DepthOnly"
+ }
+
+ // -------------------------------------
+ // Render State Commands
+ ZWrite On
+ ColorMask R
+ Cull[_Cull]
+
+ HLSLPROGRAM
+ #pragma target 2.0
+
+ // -------------------------------------
+ // Shader Stages
+ #pragma vertex DepthOnlyVertex
+ #pragma fragment HeroDepthOnlyFragment
+
+ // -------------------------------------
+ // Material Keywords
+ #pragma shader_feature_local _ALPHATEST_ON
+ #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+
+ // -------------------------------------
+ // Unity defined keywords
+ #pragma multi_compile _ LOD_FADE_CROSSFADE
+
+ //--------------------------------------
+ // GPU Instancing
+ #pragma multi_compile_instancing
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
+
+ // -------------------------------------
+ // Includes
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
+ #include "HeroCutout.hlsl"
+
+ half HeroDepthOnlyFragment(Varyings input) : SV_TARGET
+ {
+ ApplyHeroCutout(input.positionCS);
+ return DepthOnlyFragment(input);
+ }
+ ENDHLSL
+ }
+
+ // This pass is used when drawing to a _CameraNormalsTexture texture
+ Pass
+ {
+ Name "DepthNormals"
+ Tags
+ {
+ "LightMode" = "DepthNormals"
+ }
+
+ // -------------------------------------
+ // Render State Commands
+ ZWrite On
+ Cull[_Cull]
+
+ HLSLPROGRAM
+ #pragma target 2.0
+
+ // -------------------------------------
+ // Shader Stages
+ #pragma vertex DepthNormalsVertex
+ #pragma fragment HeroDepthNormalsFragment
+
+ // -------------------------------------
+ // Material Keywords
+ #pragma shader_feature_local _NORMALMAP
+ #pragma shader_feature_local _PARALLAXMAP
+ #pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
+ #pragma shader_feature_local _ALPHATEST_ON
+ #pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+
+ // -------------------------------------
+ // Unity defined keywords
+ #pragma multi_compile _ LOD_FADE_CROSSFADE
+
+ // -------------------------------------
+ // Universal Pipeline keywords
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RenderingLayers.hlsl"
+
+ //--------------------------------------
+ // GPU Instancing
+ #pragma multi_compile_instancing
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
+
+ // -------------------------------------
+ // Includes
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitDepthNormalsPass.hlsl"
+ #include "HeroCutout.hlsl"
+
+ void HeroDepthNormalsFragment(
+ Varyings input
+ , out half4 outNormalWS : SV_Target0
+ #ifdef _WRITE_RENDERING_LAYERS
+ , out uint outRenderingLayers : SV_Target1
+ #endif
+ )
+ {
+ ApplyHeroCutout(input.positionCS);
+ DepthNormalsFragment(input, outNormalWS
+ #ifdef _WRITE_RENDERING_LAYERS
+ , outRenderingLayers
+ #endif
+ );
+ }
+ ENDHLSL
+ }
+
+ // This pass it not used during regular rendering, only for lightmap baking.
+ Pass
+ {
+ Name "Meta"
+ Tags
+ {
+ "LightMode" = "Meta"
+ }
+
+ // -------------------------------------
+ // Render State Commands
+ Cull Off
+
+ HLSLPROGRAM
+ #pragma target 2.0
+
+ // -------------------------------------
+ // Shader Stages
+ #pragma vertex UniversalVertexMeta
+ #pragma fragment UniversalFragmentMetaLit
+
+ // -------------------------------------
+ // Material Keywords
+ #pragma shader_feature_local_fragment _SPECULAR_SETUP
+ #pragma shader_feature_local_fragment _EMISSION
+ #pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
+ #pragma shader_feature_local_fragment _ALPHATEST_ON
+ #pragma shader_feature_local_fragment _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
+ #pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
+ #pragma shader_feature_local_fragment _SPECGLOSSMAP
+ #pragma shader_feature EDITOR_VISUALIZATION
+
+ // -------------------------------------
+ // Includes
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitMetaPass.hlsl"
+
+ ENDHLSL
+ }
+
+ Pass
+ {
+ Name "Universal2D"
+ Tags
+ {
+ "LightMode" = "Universal2D"
+ }
+
+ // -------------------------------------
+ // Render State Commands
+ Blend[_SrcBlend][_DstBlend]
+ ZWrite[_ZWrite]
+ Cull[_Cull]
+
+ HLSLPROGRAM
+ #pragma target 2.0
+
+ // -------------------------------------
+ // Shader Stages
+ #pragma vertex vert
+ #pragma fragment frag
+
+ // -------------------------------------
+ // Material Keywords
+ #pragma shader_feature_local_fragment _ALPHATEST_ON
+ #pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON
+
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
+
+ // -------------------------------------
+ // Includes
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/Utils/Universal2D.hlsl"
+ ENDHLSL
+ }
+
+ Pass
+ {
+ Name "MotionVectors"
+ Tags { "LightMode" = "MotionVectors" }
+ ColorMask RG
+
+ HLSLPROGRAM
+ #pragma shader_feature_local _ALPHATEST_ON
+ #pragma multi_compile _ LOD_FADE_CROSSFADE
+ #pragma shader_feature_local_vertex _ADD_PRECOMPUTED_VELOCITY
+
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ObjectMotionVectors.hlsl"
+ ENDHLSL
+ }
+
+ Pass
+ {
+ Name "XRMotionVectors"
+ Tags { "LightMode" = "XRMotionVectors" }
+ ColorMask RGBA
+
+ // Stencil write for obj motion pixels
+ Stencil
+ {
+ WriteMask 1
+ Ref 1
+ Comp Always
+ Pass Replace
+ }
+
+ HLSLPROGRAM
+ #pragma shader_feature_local _ALPHATEST_ON
+ #pragma multi_compile _ LOD_FADE_CROSSFADE
+ #pragma shader_feature_local_vertex _ADD_PRECOMPUTED_VELOCITY
+ #define APPLICATION_SPACE_WARP_MOTION 1
+
+ #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
+ #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ObjectMotionVectors.hlsl"
+ ENDHLSL
+ }
+ }
+
+ FallBack "Hidden/Universal Render Pipeline/FallbackError"
+ CustomEditor "UnityEditor.Rendering.Universal.ShaderGUI.LitShader"
+}
diff --git a/Assets/Shaders/HeroCutoutLit.shader.meta b/Assets/Shaders/HeroCutoutLit.shader.meta
new file mode 100644
index 0000000..f9081c8
--- /dev/null
+++ b/Assets/Shaders/HeroCutoutLit.shader.meta
@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 023c98a32f6cc00478e50479839530c5
+ShaderImporter:
+ externalObjects: {}
+ defaultTextures: []
+ nonModifiableTextures: []
+ userData:
+ assetBundleName:
+ assetBundleVariant: