190 lines
10 KiB
GLSL

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
}
}
}