// NiloToon Character Fur Shader // Single-material fur shader with Base + Fur Shell rendering // Requires NiloToonFurRendererFeature to be added to URP Renderer // // Usage: // 1. Add NiloToonFurRendererFeature to your URP Renderer Asset // 2. Apply this shader to your mesh material (single material slot) Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur" { Properties { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Base Color ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Base Color)] [Space(5)] [MainTexture] _BaseMap("Base Map", 2D) = "white" {} [HDR][MainColor] _BaseColor("Base Color", Color) = (1,1,1,1) _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Normal Map ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Normal Map)] [Space(5)] [Toggle(_NORMALMAP)] _UseNormalMap("Enable Normal Map", Float) = 0 [Normal] _BumpMap("Normal Map", 2D) = "bump" {} _BumpScale("Normal Scale", Range(0, 2)) = 1.0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Fur Settings ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Fur Shape)] [Space(5)] _FurNoiseMask("Fur Noise Mask", 2D) = "white" {} _FurMask("Fur Mask (where fur appears)", 2D) = "white" {} _FurLengthMask("Fur Length Mask", 2D) = "white" {} _FurVector("Fur Direction (XYZ) + Length (W)", Vector) = (0, 0, 1, 0.02) [Normal] _FurVectorTex("Fur Direction Map (Normal)", 2D) = "bump" {} _FurVectorScale("Fur Direction Scale", Range(-10, 10)) = 1.0 _FurGravity("Fur Gravity", Range(0, 1)) = 0.25 _FurRandomize("Fur Randomize", Range(0, 1)) = 0.1 _FurAO("Fur Ambient Occlusion", Range(0, 1)) = 0.5 [Header(Shell Layers)] [Space(5)] [IntRange] _FurLayerNum("Fur Layer Count", Range(1, 3)) = 2 _FurRootOffset("Fur Root Offset", Range(-1, 0)) = 0 [Header(Fur Rim Light)] [Space(5)] [HDR] _FurRimColor("Fur Rim Color", Color) = (1, 1, 1, 1) _FurRimFresnelPower("Fur Rim Fresnel Power", Range(0.01, 50)) = 3.0 _FurRimAntiLight("Fur Rim Anti-Light", Range(0, 1)) = 0.5 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Toon Shading (NiloToon Style) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Cel Shading)] [Space(5)] _CelShadeMidPoint("Cel Shade Mid Point", Range(-1, 1)) = 0 _CelShadeSoftness("Cel Shade Softness", Range(0, 1)) = 0.1 [Header(Shadow Color)] [Space(5)] [Toggle(_SHADOW_COLOR)] _EnableShadowColor("Enable Shadow Color", Float) = 0 [HDR] _ShadowColor("Shadow Tint Color", Color) = (1, 1, 1, 1) _ShadowBrightness("Shadow Brightness", Range(0, 2)) = 1.0 [Header(HSV Adjustment in Shadow)] [Space(5)] _ShadowHueShift("Shadow Hue Shift", Range(-0.5, 0.5)) = 0 _ShadowSaturationBoost("Shadow Saturation Boost", Range(0, 2)) = 1.0 _ShadowValueMultiplier("Shadow Value Multiplier", Range(0, 2)) = 1.0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // MatCap ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(MatCap Additive)] [Space(5)] [Toggle(_MATCAP_ADD)] _UseMatCapAdd("Enable MatCap (Add)", Float) = 0 _MatCapAddMap("MatCap Add Map", 2D) = "black" {} [HDR] _MatCapAddColor("MatCap Add Color", Color) = (1, 1, 1, 1) _MatCapAddIntensity("MatCap Add Intensity", Range(0, 5)) = 1.0 _MatCapAddMask("MatCap Add Mask", 2D) = "white" {} [Header(MatCap Multiply)] [Space(5)] [Toggle(_MATCAP_MUL)] _UseMatCapMul("Enable MatCap (Multiply)", Float) = 0 _MatCapMulMap("MatCap Multiply Map", 2D) = "white" {} _MatCapMulIntensity("MatCap Multiply Intensity", Range(0, 2)) = 1.0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Rim Light (General) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Rim Light)] [Space(5)] [Toggle(_RIMLIGHT)] _UseRimLight("Enable Rim Light", Float) = 0 [HDR] _RimLightColor("Rim Light Color", Color) = (1, 1, 1, 1) _RimLightPower("Rim Light Power", Range(0.01, 20)) = 5.0 _RimLightIntensity("Rim Light Intensity", Range(0, 5)) = 1.0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Emission ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Emission)] [Space(5)] [Toggle(_EMISSION)] _UseEmission("Enable Emission", Float) = 0 _EmissionMap("Emission Map", 2D) = "white" {} [HDR] _EmissionColor("Emission Color", Color) = (0, 0, 0, 1) _EmissionIntensity("Emission Intensity", Range(0, 10)) = 1.0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Occlusion ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Occlusion)] [Space(5)] [Toggle(_OCCLUSIONMAP)] _UseOcclusion("Enable Occlusion Map", Float) = 0 _OcclusionMap("Occlusion Map", 2D) = "white" {} _OcclusionStrength("Occlusion Strength", Range(0, 1)) = 1.0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Outline ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Outline)] [Space(5)] _OutlineWidth("Outline Width", Range(0, 10)) = 1.0 [HDR] _OutlineColor("Outline Color", Color) = (0, 0, 0, 1) _OutlineWidthMask("Outline Width Mask", 2D) = "white" {} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Rendering Options ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [Header(Rendering Options)] [Space(5)] [Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull Mode", Float) = 2 [Enum(UnityEngine.Rendering.CullMode)] _FurCull("Fur Cull Mode", Float) = 0 [Enum(Off, 0, On, 1)] _ZWrite("ZWrite", Float) = 1 _FurZWrite("Fur ZWrite", Float) = 0 [Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Dissolve (NiloToonPerCharacterRenderController) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [HideInInspector] _DissolveAmount("_DissolveAmount", Range(0,1)) = 0 [HideInInspector] _DissolveMode("_DissolveMode", Integer) = 0 [HideInInspector] _DissolveThresholdMap("_DissolveThresholdMap", 2D) = "linearGrey" {} [HideInInspector] _DissolveThresholdMapTilingX("_DissolveThresholdMapTilingX", Float) = 1 [HideInInspector] _DissolveThresholdMapTilingY("_DissolveThresholdMapTilingY", Float) = 1 [HideInInspector] _DissolveNoiseStrength("_DissolveNoiseStrength", Float) = 1 [HideInInspector] _DissolveBorderRange("_DissolveBorderRange", Float) = 0.02 [HideInInspector] _DissolveBorderTintColor("_DissolveBorderTintColor", Color) = (1, 3, 6, 1) [HideInInspector] _AllowPerCharacterDissolve("_AllowPerCharacterDissolve", Float) = 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Per-Character Color Controls (NiloToonPerCharacterRenderController) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [HideInInspector] _PerCharacterBaseColorMultiply("_PerCharacterBaseColorMultiply", Float) = 1 [HideInInspector] _PerCharacterBaseColorTint("_PerCharacterBaseColorTint", Color) = (1, 1, 1, 1) [HideInInspector] _PerCharEffectTintColor("_PerCharEffectTintColor", Color) = (1, 1, 1, 1) [HideInInspector] _PerCharEffectAddColor("_PerCharEffectAddColor", Color) = (0, 0, 0, 0) [HideInInspector] _PerCharEffectDesaturatePercentage("_PerCharEffectDesaturatePercentage", Range(0,1)) = 0 [HideInInspector] _PerCharEffectLerpColor("_PerCharEffectLerpColor", Color) = (1, 1, 0, 0) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Per-Character Rim Light (NiloToonPerCharacterRenderController) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [HideInInspector] _UsePerCharacterRimLightIntensity("_UsePerCharacterRimLightIntensity", Float) = 0 [HideInInspector] _PerCharacterRimLightIntensity("_PerCharacterRimLightIntensity", Float) = 2 [HideInInspector] _PerCharacterRimLightColor("_PerCharacterRimLightColor", Color) = (1, 1, 1, 1) [HideInInspector] _PerCharacterRimLightSharpnessPower("_PerCharacterRimLightSharpnessPower", Float) = 4 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // BaseMap Override (NiloToonPerCharacterRenderController) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [HideInInspector] _PerCharacterBaseMapOverrideAmount("_PerCharacterBaseMapOverrideAmount", Range(0,1)) = 0 [HideInInspector] _PerCharacterBaseMapOverrideTintColor("_PerCharacterBaseMapOverrideTintColor", Color) = (1, 1, 1, 1) [HideInInspector] _PerCharacterBaseMapOverrideMap("_PerCharacterBaseMapOverrideMap", 2D) = "white" {} [HideInInspector] _PerCharacterBaseMapOverrideBlendMode("_PerCharacterBaseMapOverrideBlendMode", Float) = 0 [HideInInspector] _PerCharacterBaseMapOverrideUVOption("_PerCharacterBaseMapOverrideUVOption", Float) = 0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Character Area Color Fill (NiloToonPerCharacterRenderController) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [HideInInspector] _ShouldRenderCharacterAreaColorFill("_ShouldRenderCharacterAreaColorFill", Float) = 0 [HideInInspector] _CharacterAreaColorFillColor("_CharacterAreaColorFillColor", Color) = (1, 1, 1, 1) [HideInInspector] _CharacterAreaColorFillTexture("_CharacterAreaColorFillTexture", 2D) = "white" {} [HideInInspector] _CharacterAreaColorFillUVOption("_CharacterAreaColorFillUVOption", Float) = 0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Dither Opacity (NiloToonPerCharacterRenderController) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [HideInInspector] _DitherOpacity("_DitherOpacity", Range(0,1)) = 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Dither Fadeout (NiloToonPerCharacterRenderController) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [HideInInspector] _DitherFadeoutAmount("_DitherFadeoutAmount", Range(0,1)) = 0 [HideInInspector] _DitherFadeoutNormalScaleFix("_DitherFadeoutNormalScaleFix", Float) = 1 [HideInInspector] _AllowPerCharacterDitherFadeout("_AllowPerCharacterDitherFadeout", Float) = 1 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Perspective Removal (NiloToonPerCharacterRenderController) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [HideInInspector] _PerspectiveRemovalAmount("_PerspectiveRemovalAmount", Range(0,1)) = 0 [HideInInspector] _PerspectiveRemovalRadius("_PerspectiveRemovalRadius", Float) = 5 [HideInInspector] _PerspectiveRemovalStartHeight("_PerspectiveRemovalStartHeight", Float) = 1 [HideInInspector] _PerspectiveRemovalEndHeight("_PerspectiveRemovalEndHeight", Float) = 0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ZOffset (NiloToonPerCharacterRenderController) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [HideInInspector] _PerCharacterZOffset("_PerCharacterZOffset", Float) = 0 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Character Bound (for dissolve) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [HideInInspector] _CharacterBoundRadius("_CharacterBoundRadius", Float) = 2.5 // Hidden [HideInInspector] _Surface("__surface", Float) = 0.0 [HideInInspector] _Blend("__blend", Float) = 0.0 [HideInInspector] _QueueOffset("Queue offset", Float) = 0.0 } SubShader { Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" "UniversalMaterialType" = "Lit" "IgnoreProjector" = "True" "Queue" = "Geometry" } LOD 300 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Pass 0: ForwardLit - Base Surface (Full NiloToon Style) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Pass { Name "ForwardLit" Tags { "LightMode" = "UniversalForward" } Cull [_Cull] ZWrite On ZTest LEqual Blend One Zero HLSLPROGRAM #pragma target 4.5 // Shader Features #pragma shader_feature_local _NORMALMAP #pragma shader_feature_local _SHADOW_COLOR #pragma shader_feature_local _MATCAP_ADD #pragma shader_feature_local _MATCAP_MUL #pragma shader_feature_local _RIMLIGHT #pragma shader_feature_local _EMISSION #pragma shader_feature_local _OCCLUSIONMAP #pragma multi_compile_local _ _NILOTOON_DISSOLVE #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT // URP 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_fragment _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile_fragment _ _SHADOWS_SOFT #pragma multi_compile_fog // GPU Instancing #pragma multi_compile_instancing #pragma instancing_options renderinglayer #pragma vertex vert #pragma fragment frag #define NILOTOON_FUR_BASE_PASS #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" ENDHLSL } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Pass 1: Fur Shell Pass (Geometry Shader) - Standard single target // Rendered by NiloToonFurRendererFeature via "NiloToonFurShell" LightMode ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Pass { Name "FurShell" Tags { "LightMode" = "NiloToonFurShell" } Cull [_FurCull] ZWrite [_FurZWrite] ZTest LEqual Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha HLSLPROGRAM #pragma target 4.5 #pragma require geometry // Shader Features #pragma shader_feature_local _NORMALMAP #pragma shader_feature_local _SHADOW_COLOR #pragma shader_feature_local _MATCAP_ADD #pragma shader_feature_local _MATCAP_MUL #pragma shader_feature_local _RIMLIGHT #pragma shader_feature_local _EMISSION #pragma shader_feature_local _OCCLUSIONMAP #pragma multi_compile_local _ _NILOTOON_DISSOLVE #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT // URP 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_fragment _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile_fragment _ _SHADOWS_SOFT #pragma multi_compile_fog // GPU Instancing #pragma multi_compile_instancing #pragma instancing_options renderinglayer #pragma vertex vert_fur #pragma geometry geom_fur #pragma fragment frag_fur #define NILOTOON_FUR_SHELL_PASS #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Geometry.hlsl" #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" ENDHLSL } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Pass 1.5: Fur Shell Mask Pass (Geometry Shader) // Renders fur shells to mask buffer only (white where fur is rendered) // Used for fur area detection in post-processing ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Pass { Name "FurShellMask" Tags { "LightMode" = "NiloToonFurShellMask" } Cull [_FurCull] ZWrite On // Write depth to prevent outline from rendering over fur ZTest LEqual // Standard depth test Blend One Zero // Just overwrite HLSLPROGRAM #pragma target 4.5 #pragma require geometry // Dissolve support #pragma multi_compile_local _ _NILOTOON_DISSOLVE #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT // GPU Instancing #pragma multi_compile_instancing #pragma instancing_options renderinglayer #pragma vertex vert_fur #pragma geometry geom_fur #pragma fragment frag_fur_mask #define NILOTOON_FUR_SHELL_PASS #define NILOTOON_FUR_MASK_PASS #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Geometry.hlsl" #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" ENDHLSL } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Pass 2: Outline (NiloToon Style) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Pass { Name "Outline" Tags { "LightMode" = "NiloToonOutline" } Cull Front ZWrite [_ZWrite] ZTest [_ZTest] HLSLPROGRAM #pragma target 4.5 #pragma multi_compile_instancing #pragma instancing_options renderinglayer #pragma multi_compile_fog #pragma multi_compile_local _ _NILOTOON_DISSOLVE #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT #pragma vertex vert_outline #pragma fragment frag_outline #define NILOTOON_FUR_OUTLINE_PASS #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" Varyings vert_outline(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); float outlineWidth = _OutlineWidth * 0.001; float outlineMask = SAMPLE_TEXTURE2D_LOD(_OutlineWidthMask, sampler_OutlineWidthMask, input.uv, 0).r; outlineWidth *= outlineMask; // FOV-aware outline width float fovFactor = unity_OrthoParams.w > 0.5 ? 1.0 : (2.0 * abs(UNITY_MATRIX_P[1][1])); outlineWidth *= fovFactor; float3 posOS = input.positionOS.xyz + input.normalOS * outlineWidth; output.positionWS = TransformObjectToWorld(posOS); output.positionCS = TransformObjectToHClip(posOS); output.uv = input.uv; // Apply Perspective Removal to outline output.positionCS = NiloDoPerspectiveRemoval( output.positionCS, output.positionWS, _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], _PerspectiveRemovalRadius, _PerspectiveRemovalAmount, _PerspectiveRemovalStartHeight, _PerspectiveRemovalEndHeight ); // Apply per-character Z offset if (_PerCharacterZOffset != 0) { output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; } output.fogFactor = ComputeFogFactor(output.positionCS.z); return output; } half4 frag_outline(Varyings input) : SV_Target { // Apply Dither Fadeout to outline (FIRST) #if _NILOTOON_DITHER_FADEOUT NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); #endif // Apply dissolve to outline #if _NILOTOON_DISSOLVE half3 dummyColor = half3(1, 1, 1); ApplyDissolve(dummyColor, input.uv, input.positionWS, input.positionCS); #endif half4 color = _OutlineColor; color.rgb = MixFog(color.rgb, input.fogFactor); return color; } ENDHLSL } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Pass 3: ShadowCaster ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Pass { Name "ShadowCaster" Tags { "LightMode" = "ShadowCaster" } ZWrite On ZTest LEqual ColorMask 0 Cull [_Cull] HLSLPROGRAM #pragma target 4.5 #pragma multi_compile_instancing #pragma instancing_options renderinglayer #pragma multi_compile_local _ _NILOTOON_DISSOLVE #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT #pragma vertex ShadowPassVertex #pragma fragment ShadowPassFragment #define NILOTOON_FUR_SHADOW_PASS #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" float3 _LightDirection; float3 _LightPosition; float4 GetShadowPositionHClip(Attributes input) { float3 positionWS = TransformObjectToWorld(input.positionOS.xyz); float3 normalWS = TransformObjectToWorldNormal(input.normalOS); #if _CASTING_PUNCTUAL_LIGHT_SHADOW float3 lightDirectionWS = normalize(_LightPosition - positionWS); #else float3 lightDirectionWS = _LightDirection; #endif float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, lightDirectionWS)); #if UNITY_REVERSED_Z positionCS.z = min(positionCS.z, UNITY_NEAR_CLIP_VALUE); #else positionCS.z = max(positionCS.z, UNITY_NEAR_CLIP_VALUE); #endif return positionCS; } Varyings ShadowPassVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); output.uv = input.uv; output.positionWS = TransformObjectToWorld(input.positionOS.xyz); output.positionCS = GetShadowPositionHClip(input); // Apply Perspective Removal to shadow casting output.positionCS = NiloDoPerspectiveRemoval( output.positionCS, output.positionWS, _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], _PerspectiveRemovalRadius, _PerspectiveRemovalAmount, _PerspectiveRemovalStartHeight, _PerspectiveRemovalEndHeight ); // Apply per-character Z offset if (_PerCharacterZOffset != 0) { output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; } return output; } half4 ShadowPassFragment(Varyings input) : SV_TARGET { half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a; clip(alpha - _Cutoff); // Apply dither fadeout to shadow casting (must come before dissolve) #if _NILOTOON_DITHER_FADEOUT NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); #endif // Apply dissolve to shadow casting #if _NILOTOON_DISSOLVE half3 dummyColor = half3(1, 1, 1); ApplyDissolve(dummyColor, input.uv, input.positionWS, input.positionCS); #endif return 0; } ENDHLSL } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Pass 4: DepthOnly ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Pass { Name "DepthOnly" Tags { "LightMode" = "DepthOnly" } ZWrite On ColorMask R Cull [_Cull] HLSLPROGRAM #pragma target 4.5 #pragma multi_compile_instancing #pragma instancing_options renderinglayer #pragma multi_compile_local _ _NILOTOON_DISSOLVE #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT #pragma vertex DepthOnlyVertex #pragma fragment DepthOnlyFragment #define NILOTOON_FUR_DEPTH_PASS #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" Varyings DepthOnlyVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); output.uv = input.uv; output.positionWS = TransformObjectToWorld(input.positionOS.xyz); output.positionCS = TransformObjectToHClip(input.positionOS.xyz); // Apply Perspective Removal to depth output.positionCS = NiloDoPerspectiveRemoval( output.positionCS, output.positionWS, _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], _PerspectiveRemovalRadius, _PerspectiveRemovalAmount, _PerspectiveRemovalStartHeight, _PerspectiveRemovalEndHeight ); // Apply per-character Z offset if (_PerCharacterZOffset != 0) { output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; } return output; } half DepthOnlyFragment(Varyings input) : SV_TARGET { half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a; clip(alpha - _Cutoff); // Apply dither fadeout to depth (must come before dissolve) #if _NILOTOON_DITHER_FADEOUT NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); #endif // Apply dissolve to depth #if _NILOTOON_DISSOLVE half3 dummyColor = half3(1, 1, 1); ApplyDissolve(dummyColor, input.uv, input.positionWS, input.positionCS); #endif return input.positionCS.z; } ENDHLSL } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Pass 5: DepthNormals ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Pass { Name "DepthNormals" Tags { "LightMode" = "DepthNormals" } ZWrite On Cull [_Cull] HLSLPROGRAM #pragma target 4.5 #pragma multi_compile_instancing #pragma instancing_options renderinglayer #pragma multi_compile_local _ _NILOTOON_DISSOLVE #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT #pragma vertex DepthNormalsVertex #pragma fragment DepthNormalsFragment #define NILOTOON_FUR_DEPTHNORMALS_PASS #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" Varyings DepthNormalsVertex(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); output.uv = input.uv; output.positionWS = TransformObjectToWorld(input.positionOS.xyz); output.positionCS = TransformObjectToHClip(input.positionOS.xyz); output.normalWS = TransformObjectToWorldNormal(input.normalOS); // Apply Perspective Removal to depth normals output.positionCS = NiloDoPerspectiveRemoval( output.positionCS, output.positionWS, _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], _PerspectiveRemovalRadius, _PerspectiveRemovalAmount, _PerspectiveRemovalStartHeight, _PerspectiveRemovalEndHeight ); // Apply per-character Z offset if (_PerCharacterZOffset != 0) { output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; } return output; } float4 DepthNormalsFragment(Varyings input) : SV_TARGET { half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a; clip(alpha - _Cutoff); // Apply dither fadeout to depth normals (must come before dissolve) // This is critical for HBAO/SSAO - without this, AO will render on dithered areas #if _NILOTOON_DITHER_FADEOUT NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); #endif // Apply dissolve to depth normals #if _NILOTOON_DISSOLVE half3 dummyColor = half3(1, 1, 1); ApplyDissolve(dummyColor, input.uv, input.positionWS, input.positionCS); #endif return float4(normalize(input.normalWS) * 0.5 + 0.5, 0); } ENDHLSL } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Pass 6: NiloToonPrepassBuffer (Base mesh only) // For NiloToon Bloom / Tonemapping character area detection - base mesh ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Pass { Name "NiloToonPrepassBuffer" Tags { "LightMode" = "NiloToonPrepassBuffer" } ZWrite On ZTest LEqual Cull [_Cull] HLSLPROGRAM #pragma target 4.5 #pragma multi_compile_instancing #pragma instancing_options renderinglayer #pragma multi_compile_local _ _NILOTOON_DISSOLVE #pragma multi_compile_local _ _NILOTOON_DITHER_FADEOUT #pragma vertex PrepassBufferVertexBase #pragma fragment PrepassBufferFragmentBase #define NILOTOON_FUR_PREPASSBUFFER_PASS #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl" #include "NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl" Varyings PrepassBufferVertexBase(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); output.uv = input.uv; output.positionWS = TransformObjectToWorld(input.positionOS.xyz); output.positionCS = TransformObjectToHClip(input.positionOS.xyz); // Apply Perspective Removal to prepass buffer output.positionCS = NiloDoPerspectiveRemoval( output.positionCS, output.positionWS, _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID], _PerspectiveRemovalRadius, _PerspectiveRemovalAmount, _PerspectiveRemovalStartHeight, _PerspectiveRemovalEndHeight ); // Apply per-character Z offset if (_PerCharacterZOffset != 0) { output.positionCS.z += _PerCharacterZOffset * output.positionCS.w; } output.furLayer = -1; // Base mesh marker return output; } float4 PrepassBufferFragmentBase(Varyings input) : SV_TARGET { UNITY_SETUP_INSTANCE_ID(input); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); // Base mesh alpha clip half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a; clip(alpha - _Cutoff); // Apply dither fadeout to prepass buffer (must come before dissolve) #if _NILOTOON_DITHER_FADEOUT NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout); #endif // Apply dissolve to prepass buffer #if _NILOTOON_DISSOLVE half3 dummyColor = half3(1, 1, 1); ApplyDissolve(dummyColor, input.uv, input.positionWS, input.positionCS); #endif // Output: character visible area = 1 return float4(0, 1, 0, 1); } ENDHLSL } // Note: Fur shell prepass is handled via MRT in the FurShellMRT pass // When WriteToPrepassBuffer is enabled, FurShellMRT outputs to both: // - SV_Target0: Main color buffer // - SV_Target1: PrepassBuffer (character mask with jagged fur silhouette) } FallBack "Universal Render Pipeline/Lit" CustomEditor "NiloToonURP.ShaderGUI.NiloToonCharacterFurShaderGUI" }