Shader "Universal Render Pipeline/NiloToon/GenericStencilUnlit" { Properties { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Base ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Base Color)] [MainTexture]_BaseMap("_BaseMap (Albedo) (Default White)", 2D) = "white" {} // Not using [Tex] to preserve tiling and offset GUI [HDR][MainColor]_BaseColor("_BaseColor (Default White)", Color) = (1,1,1,1) [Header(UV Animation)] _UvAnimSpeed("_UvAnimSpeed (xy)", Vector) = (0,0,0,0) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Render States (can't use LWGUI's group, because of using [Enum(UnityEngine.Rendering.XXX)]) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Stencil)] // to match NiloToonCharacter's default stencil value _StencilRef("_StencilRef (Default 199)", Range(0,255)) = 199 // 3 is Equal, so this shader will by default draw only on NiloTOon character pixels [Enum(UnityEngine.Rendering.CompareFunction)]_StencilComp("_StencilComp (Default Equal)", Float) = 3 [Header(Polygon Face Culling)] // https://docs.unity3d.com/ScriptReference/Rendering.CullMode.html [Enum(UnityEngine.Rendering.CullMode)]_Cull("_Cull (Default Back)", Float) = 2 [Header(Blending state)] // https://docs.unity3d.com/ScriptReference/Rendering.BlendMode.html // this section will only affect ForwardLit pass [Enum(UnityEngine.Rendering.BlendMode)]_SrcBlend("_SrcBlend (Default SrcAlpha)", Float) = 5 [Enum(UnityEngine.Rendering.BlendMode)]_DstBlend("_DstBlend (Default OneMinusSrcAlpha)", Float) = 10 [Header(ZWrite)] [ToggleUI]_ZWrite("_ZWrite (Default Off) ", Float) = 0 [Header(ZTest)] // https://docs.unity3d.com/ScriptReference/Rendering.CompareFunction.html [Enum(UnityEngine.Rendering.CompareFunction)]_ZTest("_ZTest (Default LEqual) ", Float) = 4 [Header(ColorMask)] // not using https://docs.unity3d.com/ScriptReference/Rendering.ColorWriteMask.html, // because we can't select RGB if we use Unity's ColorWriteMask. // So here we define 2 custom enum // 15 = 1111 (RGBA) // 14 = 1110 (RGB) [Enum(RGBA,15,RGB,14)]_ColorMask("_ColorMask (Default RGB)", Float) = 14 // 14 is RGB (1110) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Set by script ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // perspective removal [HideInInspector]_PerspectiveRemovalAmount("_PerspectiveRemovalAmount", Range(0,1)) = 0 [HideInInspector]_PerspectiveRemovalRadius("_PerspectiveRemovalRadius", Float) = 1 [HideInInspector]_HeadBonePositionWS("_HeadBonePositionWS", Vector) = (0,0,0) [HideInInspector]_PerspectiveRemovalStartHeight("_PerspectiveRemovalStartHeight", Float) = 0 // ground [HideInInspector]_PerspectiveRemovalEndHeight("_PerspectiveRemovalEndHeight", Float) = 1 // a point above ground and below character head // Character ID for read global 1D array or load 1D texture [HideInInspector]_CharacterID("_CharacterID", Integer) = 0 // use 0 instead of -1, to avoid array or texture read out of bound } SubShader { // draw after NiloToonCharacter shader, so when drawing this shader, stencil buffer's value is usable already Tags { "RenderType"="transparent" "Queue"="transparent-1" } // render state Cull [_Cull] ZWrite [_ZWrite] ZTest [_ZTest] Blend [_SrcBlend] [_DstBlend] ColorMask [_ColorMask] Stencil { Ref [_StencilRef] Comp [_StencilComp] } Pass { HLSLPROGRAM #pragma vertex vert #pragma fragment frag // Required by all Universal Render Pipeline shaders. // It will include Unity built-in shader variables (except the lighting variables) // (https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html // It will also include many utilitary functions. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" // Include this if you are doing a lit shader. This includes lighting shader variables, // lighting and shadow functions #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" // include a few small utility .hlsl files to help us #include "../../ShaderLibrary/NiloUtilityHLSL/NiloAllUtilIncludes.hlsl" struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; // to support GPU instancing and Single Pass Stereo rendering(VR), add the following section //------------------------------------------------------------------------------------------------------------------------------ UNITY_VERTEX_INPUT_INSTANCE_ID // in non OpenGL / non PSSL, will turn into -> uint instanceID : SV_InstanceID; //------------------------------------------------------------------------------------------------------------------------------ }; struct Varyings { float4 positionHCS : SV_POSITION; float2 uv : TEXCOORD0; // to support GPU instancing and Single Pass Stereo rendering(VR), add the following section //------------------------------------------------------------------------------------------------------------------------------ UNITY_VERTEX_INPUT_INSTANCE_ID // will turn into this in non OpenGL / non PSSL -> uint instanceID : SV_InstanceID; UNITY_VERTEX_OUTPUT_STEREO // will turn into this in non OpenGL / non PSSL -> uint stereoTargetEyeIndexAsRTArrayIdx : SV_RenderTargetArrayIndex; //------------------------------------------------------------------------------------------------------------------------------ }; sampler2D _BaseMap; CBUFFER_START(UnityPerMaterial) float4 _BaseMap_ST; float2 _UvAnimSpeed; half4 _BaseColor; // perspective removal float _PerspectiveRemovalAmount; // total amount // perspective removal(sphere) float _PerspectiveRemovalRadius; //float3 _HeadBonePositionWS; // Converted to global array // perspective removal(world height) float _PerspectiveRemovalStartHeight; // usually is world space pos.y 0 float _PerspectiveRemovalEndHeight; // Character ID for read global 1D array or load 1D texture uint _CharacterID; CBUFFER_END //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Global Arrays //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define MAX_CHARACTER_COUNT 128 float3 _NiloToonGlobalPerCharHeadBonePosWSArray[MAX_CHARACTER_COUNT]; Varyings vert (Attributes IN) { Varyings OUT; // to support GPU instancing and Single Pass Stereo rendering(VR), add the following section //------------------------------------------------------------------------------------------------------------------------------ UNITY_SETUP_INSTANCE_ID(IN); // will turn into this in non OpenGL / non PSSL -> UnitySetupInstanceID(input.instanceID); UNITY_TRANSFER_INSTANCE_ID(IN, OUT); // will turn into this in non OpenGL / non PSSL -> output.instanceID = input.instanceID; UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); // will turn into this in non OpenGL / non PSSL -> output.stereoTargetEyeIndexAsRTArrayIdx = unity_StereoEyeIndex; //------------------------------------------------------------------------------------------------------------------------------ OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz); // perspective removal float3 positionWS = mul(UNITY_MATRIX_M, float4(IN.positionOS.xyz,1)).xyz; OUT.positionHCS = NiloDoPerspectiveRemoval(OUT.positionHCS,positionWS,_NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID],_PerspectiveRemovalRadius,_PerspectiveRemovalAmount, _PerspectiveRemovalStartHeight, _PerspectiveRemovalEndHeight); OUT.uv = TRANSFORM_TEX(IN.uv, _BaseMap) + frac(_UvAnimSpeed.xy * _Time.y); return OUT; } half4 frag (Varyings IN) : SV_Target { // to support GPU instancing and Single Pass Stereo rendering(VR), add the following section //------------------------------------------------------------------------------------------------------------------------------ UNITY_SETUP_INSTANCE_ID(IN); // in non OpenGL / non PSSL, MACRO will turn into -> UnitySetupInstanceID(input.instanceID); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN); // in non OpenGL / non PSSL, MACRO will turn into -> unity_StereoEyeIndex = input.stereoTargetEyeIndexAsRTArrayIdx; //------------------------------------------------------------------------------------------------------------------------------ // sample the texture half4 col = tex2D(_BaseMap, IN.uv) * _BaseColor; return col; } ENDHLSL } } }