Fix : 퍼 쉐이더 최종 업데이트
This commit is contained in:
parent
5a559d888e
commit
e3f18d8726
@ -22,14 +22,10 @@ namespace NiloToon.NiloToonURP
|
||||
[Header("Fur Shell Settings")]
|
||||
|
||||
[Tooltip("Enable to render fur shells.\n\nDefault: ON")]
|
||||
[OverrideDisplayName("Enable?")]
|
||||
[Revertible]
|
||||
public bool ShouldRenderFurShell = true;
|
||||
|
||||
[Tooltip("When to render fur shells in the rendering pipeline.\n\nDefault: AfterRenderingOpaques")]
|
||||
[Revertible]
|
||||
[OverrideDisplayName("Render Timing")]
|
||||
public RenderPassEvent renderTiming = RenderPassEvent.AfterRenderingOpaques;
|
||||
[Tooltip("When to render fur shells in the rendering pipeline.\n\nDefault: AfterRenderingSkybox + 1 (right after classic outline)")]
|
||||
public RenderPassEvent renderTiming = RenderPassEvent.AfterRenderingSkybox + 1;
|
||||
}
|
||||
|
||||
Settings settings;
|
||||
|
||||
@ -140,6 +140,79 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
_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] _PerCharacterTintColor("_PerCharacterTintColor", Color) = (1, 1, 1, 1)
|
||||
[HideInInspector] _PerCharacterAddColor("_PerCharacterAddColor", 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
|
||||
|
||||
// Hidden
|
||||
[HideInInspector] _Surface("__surface", Float) = 0.0
|
||||
[HideInInspector] _Blend("__blend", Float) = 0.0
|
||||
@ -182,6 +255,8 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
#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
|
||||
@ -229,6 +304,8 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
#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
|
||||
@ -263,14 +340,18 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
Tags { "LightMode" = "NiloToonFurShellMask" }
|
||||
|
||||
Cull [_FurCull]
|
||||
ZWrite Off
|
||||
ZTest Always // Always pass - we want to mark ALL fur pixels regardless of depth
|
||||
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
|
||||
@ -305,12 +386,15 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
#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)
|
||||
{
|
||||
@ -328,8 +412,27 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
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;
|
||||
@ -337,6 +440,17 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
|
||||
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;
|
||||
@ -362,12 +476,15 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
|
||||
#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;
|
||||
@ -401,7 +518,26 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
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;
|
||||
}
|
||||
|
||||
@ -409,6 +545,13 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
{
|
||||
half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a;
|
||||
clip(alpha - _Cutoff);
|
||||
|
||||
// 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
|
||||
@ -431,12 +574,15 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
|
||||
#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)
|
||||
{
|
||||
@ -445,7 +591,26 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
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;
|
||||
}
|
||||
|
||||
@ -453,6 +618,13 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
{
|
||||
half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a;
|
||||
clip(alpha - _Cutoff);
|
||||
|
||||
// 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
|
||||
@ -474,12 +646,15 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
|
||||
#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)
|
||||
{
|
||||
@ -488,8 +663,27 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
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;
|
||||
}
|
||||
|
||||
@ -497,6 +691,13 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
{
|
||||
half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a;
|
||||
clip(alpha - _Cutoff);
|
||||
|
||||
// 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
|
||||
@ -520,12 +721,15 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
|
||||
#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)
|
||||
{
|
||||
@ -535,7 +739,26 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
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;
|
||||
}
|
||||
@ -549,6 +772,12 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur"
|
||||
half alpha = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, input.uv).a * _BaseColor.a;
|
||||
clip(alpha - _Cutoff);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@ -22,6 +22,183 @@ half3 GetNormalFromMap(float2 uv, float3 normalWS, float4 tangentWS)
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// Apply Dissolve (NiloToon Style)
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
void ApplyDissolve(inout half3 color, float2 uv, float3 positionWS, float4 positionCS)
|
||||
{
|
||||
#if _NILOTOON_DISSOLVE
|
||||
// Matching to NiloToonPerCharacterRenderController.cs's enum DissolveMode
|
||||
#define DISSOLVEMODE_UV1 1
|
||||
#define DISSOLVEMODE_UV2 2
|
||||
#define DISSOLVEMODE_WorldSpaceNoise 3
|
||||
#define DISSOLVEMODE_WorldSpaceVerticalUpward 4
|
||||
#define DISSOLVEMODE_WorldSpaceVerticalDownward 5
|
||||
#define DISSOLVEMODE_ScreenSpaceNoise 6
|
||||
#define DISSOLVEMODE_ScreenSpaceVerticalUpward 7
|
||||
#define DISSOLVEMODE_ScreenSpaceVerticalDownward 8
|
||||
|
||||
half finalDissolveAmount = _DissolveAmount * _AllowPerCharacterDissolve;
|
||||
if(finalDissolveAmount <= 0) return;
|
||||
|
||||
float noiseStrength = _DissolveNoiseStrength * 0.1;
|
||||
float2 uvTiling = float2(_DissolveThresholdMapTilingX, _DissolveThresholdMapTilingY);
|
||||
|
||||
half dissolveMapThresholdMapValue = 0;
|
||||
|
||||
if(_DissolveMode == DISSOLVEMODE_UV1)
|
||||
{
|
||||
float2 dissolveUV = uv * uvTiling;
|
||||
dissolveMapThresholdMapValue = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).r;
|
||||
}
|
||||
else if(_DissolveMode == DISSOLVEMODE_WorldSpaceNoise)
|
||||
{
|
||||
float2 dissolveUV = positionWS.xz * uvTiling;
|
||||
float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength;
|
||||
dissolveMapThresholdMapValue = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).r + noise;
|
||||
}
|
||||
else if(_DissolveMode == DISSOLVEMODE_WorldSpaceVerticalUpward)
|
||||
{
|
||||
float2 dissolveUV = positionWS.xz * uvTiling;
|
||||
float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength;
|
||||
dissolveMapThresholdMapValue = saturate(positionWS.y * 0.1 + noise);
|
||||
}
|
||||
else if(_DissolveMode == DISSOLVEMODE_WorldSpaceVerticalDownward)
|
||||
{
|
||||
float2 dissolveUV = positionWS.xz * uvTiling;
|
||||
float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength;
|
||||
dissolveMapThresholdMapValue = saturate((1 - positionWS.y * 0.1) + noise);
|
||||
}
|
||||
else if(_DissolveMode == DISSOLVEMODE_ScreenSpaceNoise)
|
||||
{
|
||||
float2 screenUV = positionCS.xy / positionCS.w;
|
||||
float2 dissolveUV = screenUV * uvTiling;
|
||||
float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength;
|
||||
dissolveMapThresholdMapValue = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).r + noise;
|
||||
}
|
||||
else if(_DissolveMode == DISSOLVEMODE_ScreenSpaceVerticalUpward)
|
||||
{
|
||||
float2 screenUV = positionCS.xy / positionCS.w;
|
||||
float2 dissolveUV = screenUV * uvTiling;
|
||||
float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength;
|
||||
dissolveMapThresholdMapValue = saturate(screenUV.y + noise);
|
||||
}
|
||||
else if(_DissolveMode == DISSOLVEMODE_ScreenSpaceVerticalDownward)
|
||||
{
|
||||
float2 screenUV = positionCS.xy / positionCS.w;
|
||||
float2 dissolveUV = screenUV * uvTiling;
|
||||
float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength;
|
||||
dissolveMapThresholdMapValue = saturate((1 - screenUV.y) + noise);
|
||||
}
|
||||
|
||||
half dissolve = dissolveMapThresholdMapValue - finalDissolveAmount;
|
||||
|
||||
// Clip threshold
|
||||
clip(dissolve - 0.0001);
|
||||
|
||||
// HDR color tint to "near threshold area"
|
||||
color = lerp(color, _DissolveBorderTintColor.rgb, smoothstep(finalDissolveAmount + _DissolveBorderRange, finalDissolveAmount, dissolveMapThresholdMapValue));
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// Apply Per-Character Color Controls (Tint, Add, Desaturation, Lerp)
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
half3 ApplyPerCharacterColorControls(half3 color)
|
||||
{
|
||||
// Base Color Multiply & Tint
|
||||
color *= _PerCharacterBaseColorMultiply;
|
||||
color *= _PerCharacterBaseColorTint.rgb;
|
||||
|
||||
// Tint Color
|
||||
color *= _PerCharacterTintColor.rgb;
|
||||
|
||||
// Add Color
|
||||
color += _PerCharacterAddColor.rgb;
|
||||
|
||||
// Desaturation (matching NiloToonCharacter_Shared.hlsl line 4099)
|
||||
color = lerp(color, Luminance(color), _PerCharEffectDesaturatePercentage);
|
||||
|
||||
// Mul Add (already handled above with _PerCharacterTintColor and _PerCharacterAddColor)
|
||||
|
||||
// Replace by Color / Lerp Color (matching NiloToonCharacter_Shared.hlsl line 4105)
|
||||
// Uses alpha channel of _PerCharEffectLerpColor as the lerp amount
|
||||
color.rgb = lerp(color.rgb, _PerCharEffectLerpColor.rgb, _PerCharEffectLerpColor.a);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// Apply BaseMap Override (matching NiloToonPerCharacterRenderController)
|
||||
// Based on ApplyPostLightingPerCharacterBaseMapOverride from NiloToonCharacter_Shared.hlsl
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
half3 ApplyBaseMapOverride(half3 baseColor, float2 uv, float3 positionWS, float4 positionCS)
|
||||
{
|
||||
// Sample texture with tiling/offset
|
||||
float2 overrideUV = uv * _PerCharacterBaseMapOverrideMap_ST.xy + _PerCharacterBaseMapOverrideMap_ST.zw;
|
||||
half4 texValue = SAMPLE_TEXTURE2D(_PerCharacterBaseMapOverrideMap, sampler_PerCharacterBaseMapOverrideMap, overrideUV);
|
||||
|
||||
// Apply tint color
|
||||
texValue.rgb *= _PerCharacterBaseMapOverrideTintColor;
|
||||
|
||||
// KEY FIX: Multiply alpha by Amount (0-1 range)
|
||||
// When Amount is 0, alpha becomes 0, making BlendColor() return baseColor unchanged
|
||||
texValue.a *= _PerCharacterBaseMapOverrideAmount;
|
||||
|
||||
// Create RGBA versions for BlendColor function
|
||||
half4 originalColorRGBA = half4(baseColor.r, baseColor.g, baseColor.b, 1);
|
||||
half4 resultColorRGBA = BlendColor(originalColorRGBA, texValue, _PerCharacterBaseMapOverrideBlendMode);
|
||||
|
||||
// Return only RGB (don't modify alpha)
|
||||
return resultColorRGBA.rgb;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// Apply Character Area Color Fill
|
||||
// Based on NiloToonCharacterAreaColorFillFragmentFunction from NiloToonCharacter.shader
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
half3 ApplyCharacterAreaColorFill(half3 color, float2 uv, float3 positionWS, float4 positionCS)
|
||||
{
|
||||
// Sample texture with tiling/offset
|
||||
float2 fillUV = uv * _CharacterAreaColorFillTexture_ST.xy + _CharacterAreaColorFillTexture_ST.zw;
|
||||
half4 fillTexSample = SAMPLE_TEXTURE2D(_CharacterAreaColorFillTexture, sampler_CharacterAreaColorFillTexture, fillUV);
|
||||
|
||||
// Apply color tint
|
||||
half4 resultColor = _CharacterAreaColorFillColor * fillTexSample;
|
||||
|
||||
// KEY FIX: Multiply alpha by _ShouldRenderCharacterAreaColorFill (acts as enabled flag)
|
||||
// When disabled (0), alpha becomes 0, so the color addition has no effect
|
||||
// Note: Original shader also multiplies by renderArea, but we don't have prepass buffer in fur shader,
|
||||
// so we'll just use the enabled flag
|
||||
resultColor.a *= _ShouldRenderCharacterAreaColorFill;
|
||||
|
||||
// Add the color based on alpha (when disabled, alpha is 0 so nothing is added)
|
||||
color += resultColor.rgb * resultColor.a;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// Apply Dither Opacity (screen-space dithering for transparency)
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
void ApplyDitherOpacity(float4 positionCS, half opacity)
|
||||
{
|
||||
if (opacity >= 1.0) return;
|
||||
|
||||
// 4x4 Bayer matrix for dithering
|
||||
const float4x4 thresholdMatrix = float4x4(
|
||||
1.0 / 17.0, 9.0 / 17.0, 3.0 / 17.0, 11.0 / 17.0,
|
||||
13.0 / 17.0, 5.0 / 17.0, 15.0 / 17.0, 7.0 / 17.0,
|
||||
4.0 / 17.0, 12.0 / 17.0, 2.0 / 17.0, 10.0 / 17.0,
|
||||
16.0 / 17.0, 8.0 / 17.0, 14.0 / 17.0, 6.0 / 17.0
|
||||
);
|
||||
|
||||
int2 pixelPos = int2(positionCS.xy) % 4;
|
||||
float threshold = thresholdMatrix[pixelPos.x][pixelPos.y];
|
||||
|
||||
clip(opacity - threshold);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// Apply All Effects (MatCap, Rim, Emission)
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -56,8 +233,20 @@ half3 ApplyEffects(
|
||||
if (furLayer < 0) // Only for base pass
|
||||
{
|
||||
half NdotV = saturate(dot(normalWS, viewDirWS));
|
||||
half rim = pow(1.0 - NdotV, _RimLightPower);
|
||||
color += rim * _RimLightColor.rgb * _RimLightIntensity * lightColor;
|
||||
half rimPower = _RimLightPower;
|
||||
half rimIntensity = _RimLightIntensity;
|
||||
half3 rimColor = _RimLightColor.rgb;
|
||||
|
||||
// Apply per-character rim light override if enabled
|
||||
if (_UsePerCharacterRimLightIntensity > 0.5)
|
||||
{
|
||||
rimPower = _PerCharacterRimLightSharpnessPower;
|
||||
rimIntensity = _PerCharacterRimLightIntensity;
|
||||
rimColor = _PerCharacterRimLightColor.rgb;
|
||||
}
|
||||
|
||||
half rim = pow(1.0 - NdotV, rimPower);
|
||||
color += rim * rimColor * rimIntensity * lightColor;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -87,6 +276,17 @@ half4 frag(Varyings input) : SV_Target
|
||||
// Alpha cutoff
|
||||
clip(color.a - _Cutoff);
|
||||
|
||||
// Apply Dither Fadeout (FIRST - affects visibility)
|
||||
#if _NILOTOON_DITHER_FADEOUT
|
||||
NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout);
|
||||
#endif
|
||||
|
||||
// Apply dissolve (after dither fadeout)
|
||||
// This will clip pixels and apply border glow
|
||||
#if _NILOTOON_DISSOLVE
|
||||
ApplyDissolve(color.rgb, input.uv, input.positionWS, input.positionCS);
|
||||
#endif
|
||||
|
||||
// Get normal (with normal map if enabled)
|
||||
float3 normalWS = GetNormalFromMap(input.uv, input.normalWS, input.tangentWS);
|
||||
|
||||
@ -109,6 +309,9 @@ half4 frag(Varyings input) : SV_Target
|
||||
occlusion = lerp(1.0, SAMPLE_TEXTURE2D(_OcclusionMap, sampler_OcclusionMap, input.uv).r, _OcclusionStrength);
|
||||
#endif
|
||||
|
||||
// Apply BaseMap Override (before shading)
|
||||
color.rgb = ApplyBaseMapOverride(color.rgb, input.uv, input.positionWS, input.positionCS);
|
||||
|
||||
// Apply NiloToon cel shading
|
||||
color.rgb = ApplyNiloToonCelShading(
|
||||
color.rgb,
|
||||
@ -123,6 +326,15 @@ half4 frag(Varyings input) : SV_Target
|
||||
// Apply additional effects
|
||||
color.rgb = ApplyEffects(color.rgb, input.uv, normalWS, viewDirWS, mainLight.color, input.furLayer);
|
||||
|
||||
// Apply per-character color controls
|
||||
color.rgb = ApplyPerCharacterColorControls(color.rgb);
|
||||
|
||||
// Apply character area color fill
|
||||
color.rgb = ApplyCharacterAreaColorFill(color.rgb, input.uv, input.positionWS, input.positionCS);
|
||||
|
||||
// Apply dither opacity
|
||||
ApplyDitherOpacity(input.positionCS, _DitherOpacity);
|
||||
|
||||
// Apply fog
|
||||
color.rgb = MixFog(color.rgb, input.fogFactor);
|
||||
|
||||
@ -186,6 +398,20 @@ half4 ComputeFurColor(Varyings input, out half furAlpha)
|
||||
// Minimum alpha threshold
|
||||
clip(furAlpha - 0.05);
|
||||
|
||||
// Apply Dither Fadeout (FIRST - affects visibility)
|
||||
#if _NILOTOON_DITHER_FADEOUT
|
||||
NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout);
|
||||
#endif
|
||||
|
||||
// Apply dissolve (after dither fadeout)
|
||||
// This will clip pixels and apply border glow
|
||||
#if _NILOTOON_DISSOLVE
|
||||
ApplyDissolve(color.rgb, input.uv, input.positionWS, input.positionCS);
|
||||
#endif
|
||||
|
||||
// Apply BaseMap Override (before shading)
|
||||
color.rgb = ApplyBaseMapOverride(color.rgb, input.uv, input.positionWS, input.positionCS);
|
||||
|
||||
// Get normal (with normal map if enabled)
|
||||
float3 normalWS = GetNormalFromMap(input.uv, input.normalWS, input.tangentWS);
|
||||
|
||||
@ -260,6 +486,15 @@ half4 ComputeFurColor(Varyings input, out half furAlpha)
|
||||
color.rgb += emission;
|
||||
#endif
|
||||
|
||||
// Apply per-character color controls
|
||||
color.rgb = ApplyPerCharacterColorControls(color.rgb);
|
||||
|
||||
// Apply character area color fill
|
||||
color.rgb = ApplyCharacterAreaColorFill(color.rgb, input.uv, input.positionWS, input.positionCS);
|
||||
|
||||
// Apply dither opacity
|
||||
ApplyDitherOpacity(input.positionCS, _DitherOpacity);
|
||||
|
||||
// Apply fog
|
||||
color.rgb = MixFog(color.rgb, input.fogFactor);
|
||||
|
||||
@ -323,6 +558,17 @@ half4 frag_fur_mask(Varyings input) : SV_Target
|
||||
// Clip pixels that don't pass threshold (same as main fur rendering)
|
||||
clip(furAlpha - 0.05);
|
||||
|
||||
// Apply Dither Fadeout (mask pass must also respect dither fadeout)
|
||||
#if _NILOTOON_DITHER_FADEOUT
|
||||
NiloDoDitherFadeoutClip(input.positionCS.xy, 1.0 - _DitherFadeoutAmount * _AllowPerCharacterDitherFadeout);
|
||||
#endif
|
||||
|
||||
// Apply dissolve clipping (mask pass must also respect dissolve)
|
||||
#if _NILOTOON_DISSOLVE
|
||||
half3 dummyColor = half3(1, 1, 1);
|
||||
ApplyDissolve(dummyColor, input.uv, input.positionWS, float4(0, 0, 0, 1));
|
||||
#endif
|
||||
|
||||
// Output to PrepassBuffer format:
|
||||
// G channel = character visible area (unified mask for face, body, and fur)
|
||||
// All character areas use G channel for consistent masking
|
||||
|
||||
@ -39,44 +39,87 @@ void AppendFurShell(
|
||||
float3 basePositionWS = LerpBary(input[0].positionWS, input[1].positionWS, input[2].positionWS, factor);
|
||||
|
||||
output.positionWS = basePositionWS;
|
||||
output.positionCS = TransformWorldToHClip(basePositionWS);
|
||||
float4 basePositionCS_BeforePerspective = TransformWorldToHClip(basePositionWS);
|
||||
output.furLayer = 0;
|
||||
|
||||
// Clipping canceller for near plane
|
||||
#if defined(UNITY_REVERSED_Z)
|
||||
if(output.positionCS.w < _ProjectionParams.y * 1.01 && output.positionCS.w > 0)
|
||||
{
|
||||
output.positionCS.z = output.positionCS.z * 0.0001 + output.positionCS.w * 0.999;
|
||||
}
|
||||
#else
|
||||
if(output.positionCS.w < _ProjectionParams.y * 1.01 && output.positionCS.w > 0)
|
||||
{
|
||||
output.positionCS.z = output.positionCS.z * 0.0001 - output.positionCS.w * 0.999;
|
||||
}
|
||||
#endif
|
||||
// Apply Perspective Removal to base
|
||||
float4 basePositionCS_AfterPerspective = NiloDoPerspectiveRemoval(
|
||||
basePositionCS_BeforePerspective,
|
||||
basePositionWS,
|
||||
_NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID],
|
||||
_PerspectiveRemovalRadius,
|
||||
_PerspectiveRemovalAmount,
|
||||
_PerspectiveRemovalStartHeight,
|
||||
_PerspectiveRemovalEndHeight
|
||||
);
|
||||
|
||||
output.positionCS = basePositionCS_AfterPerspective;
|
||||
|
||||
// Apply per-character Z offset
|
||||
if (_PerCharacterZOffset != 0)
|
||||
{
|
||||
output.positionCS.z += _PerCharacterZOffset * output.positionCS.w;
|
||||
}
|
||||
|
||||
outStream.Append(output);
|
||||
|
||||
// Tip position (furLayer = 1)
|
||||
float3 mixedFurVector = LerpBary(furVectors[0], furVectors[1], furVectors[2], factor);
|
||||
float3 tipPositionWS = basePositionWS + mixedFurVector;
|
||||
// CRITICAL FIX: Transform fur vector to clip space using the SAME perspective removal parameters as base
|
||||
|
||||
// Get the interpolated fur vector in world space
|
||||
float3 mixedFurVector = LerpBary(furVectors[0], furVectors[1], furVectors[2], factor);
|
||||
|
||||
// Calculate tip in world space (for lighting and shading)
|
||||
float3 tipPositionWS = basePositionWS + mixedFurVector;
|
||||
output.positionWS = tipPositionWS;
|
||||
output.positionCS = TransformWorldToHClip(tipPositionWS);
|
||||
|
||||
// Transform fur vector to clip space by transforming both endpoints
|
||||
// IMPORTANT: Don't apply perspective removal to tip separately!
|
||||
// Instead, transform the fur vector in clip space relative to the base
|
||||
|
||||
// Convert the fur vector direction to clip space
|
||||
// We approximate this by transforming a point at base + furVector
|
||||
float4 furVectorEndCS_BeforePerspective = TransformWorldToHClip(tipPositionWS);
|
||||
|
||||
// Calculate the fur vector in clip space BEFORE perspective removal
|
||||
float4 furVectorCS_BeforePerspective = furVectorEndCS_BeforePerspective - basePositionCS_BeforePerspective;
|
||||
|
||||
// Apply the same perspective removal transformation to the fur vector as we did to the base
|
||||
// This maintains the correct relative offset in perspective-removed space
|
||||
// The key insight: we want to preserve the fur direction/length relative to the base's transformation
|
||||
|
||||
// Transform the fur vector's XY component using the base's perspective removal scale
|
||||
// Perspective removal formula: newXY = lerp(originalXY, originalXY * w / centerPosVSz, amount)
|
||||
// For the fur vector, we need to apply the same scale change
|
||||
|
||||
float3 centerPosWS = _NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID];
|
||||
float centerPosVSz = mul(UNITY_MATRIX_V, float4(centerPosWS,1)).z;
|
||||
|
||||
// Calculate perspective removal amount for base position
|
||||
float perspectiveRemovalAreaSphere = saturate(_PerspectiveRemovalRadius - distance(basePositionWS, centerPosWS) / _PerspectiveRemovalRadius);
|
||||
float perspectiveRemovalAreaWorldHeight = saturate(invLerp(_PerspectiveRemovalStartHeight, _PerspectiveRemovalEndHeight, basePositionWS.y));
|
||||
float perspectiveRemovalFinalAmount = _PerspectiveRemovalAmount * perspectiveRemovalAreaSphere * perspectiveRemovalAreaWorldHeight;
|
||||
|
||||
// Apply perspective removal scale to fur vector
|
||||
// The scale factor is: lerp(1, w / centerPosVSz, amount)
|
||||
float basePerspectiveScale = lerp(1.0, abs(basePositionCS_BeforePerspective.w) * rcp(abs(centerPosVSz)), perspectiveRemovalFinalAmount);
|
||||
|
||||
// Scale the fur vector's XY by the same factor
|
||||
float2 furVectorCS_XY = furVectorCS_BeforePerspective.xy * basePerspectiveScale;
|
||||
|
||||
// Construct the final tip position in clip space
|
||||
output.positionCS = basePositionCS_AfterPerspective;
|
||||
output.positionCS.xy += furVectorCS_XY;
|
||||
output.positionCS.z = furVectorEndCS_BeforePerspective.z; // Keep original Z depth for tip
|
||||
output.positionCS.w = furVectorEndCS_BeforePerspective.w; // Keep original W for tip
|
||||
|
||||
output.furLayer = layerProgress;
|
||||
|
||||
// Clipping canceller for near plane
|
||||
#if defined(UNITY_REVERSED_Z)
|
||||
if(output.positionCS.w < _ProjectionParams.y * 1.01 && output.positionCS.w > 0)
|
||||
{
|
||||
output.positionCS.z = output.positionCS.z * 0.0001 + output.positionCS.w * 0.999;
|
||||
}
|
||||
#else
|
||||
if(output.positionCS.w < _ProjectionParams.y * 1.01 && output.positionCS.w > 0)
|
||||
{
|
||||
output.positionCS.z = output.positionCS.z * 0.0001 - output.positionCS.w * 0.999;
|
||||
}
|
||||
#endif
|
||||
// Apply per-character Z offset
|
||||
if (_PerCharacterZOffset != 0)
|
||||
{
|
||||
output.positionCS.z += _PerCharacterZOffset * output.positionCS.w;
|
||||
}
|
||||
|
||||
outStream.Append(output);
|
||||
}
|
||||
|
||||
@ -8,6 +8,12 @@
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
|
||||
|
||||
// Include NiloToon utility functions (order matters - InvLerpRemapUtil must come before PerspectiveRemovalUtil)
|
||||
#include "../../ShaderLibrary/NiloUtilityHLSL/NiloInvLerpRemapUtil.hlsl"
|
||||
#include "../../ShaderLibrary/NiloUtilityHLSL/NiloBlendEquationUtil.hlsl"
|
||||
#include "../../ShaderLibrary/NiloUtilityHLSL/NiloDitherFadeoutClipUtil.hlsl"
|
||||
#include "../../ShaderLibrary/NiloUtilityHLSL/NiloPerspectiveRemovalUtil.hlsl"
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// NiloToon Global Light Override Variables (from NiloToonCharacterMainLightOverrider)
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -128,8 +134,77 @@ CBUFFER_START(UnityPerMaterial)
|
||||
// Rendering
|
||||
half _Cull;
|
||||
half _FurCull;
|
||||
|
||||
// Dissolve
|
||||
float _DissolveAmount;
|
||||
float _DissolveMode;
|
||||
float _DissolveThresholdMapTilingX;
|
||||
float _DissolveThresholdMapTilingY;
|
||||
float _DissolveNoiseStrength;
|
||||
float _DissolveBorderRange;
|
||||
half4 _DissolveBorderTintColor;
|
||||
float _AllowPerCharacterDissolve;
|
||||
|
||||
// Per-Character Color Controls
|
||||
half _PerCharacterBaseColorMultiply;
|
||||
half4 _PerCharacterBaseColorTint;
|
||||
half4 _PerCharacterTintColor;
|
||||
half4 _PerCharacterAddColor;
|
||||
half _PerCharEffectDesaturatePercentage;
|
||||
half4 _PerCharEffectLerpColor;
|
||||
|
||||
// Per-Character Rim Light
|
||||
half _UsePerCharacterRimLightIntensity;
|
||||
half _PerCharacterRimLightIntensity;
|
||||
half4 _PerCharacterRimLightColor;
|
||||
half _PerCharacterRimLightSharpnessPower;
|
||||
|
||||
// BaseMap Override
|
||||
half _PerCharacterBaseMapOverrideAmount;
|
||||
half4 _PerCharacterBaseMapOverrideTintColor;
|
||||
float4 _PerCharacterBaseMapOverrideMap_ST;
|
||||
half _PerCharacterBaseMapOverrideBlendMode;
|
||||
half _PerCharacterBaseMapOverrideUVOption;
|
||||
|
||||
// Character Area Color Fill
|
||||
half _ShouldRenderCharacterAreaColorFill;
|
||||
half4 _CharacterAreaColorFillColor;
|
||||
float4 _CharacterAreaColorFillTexture_ST;
|
||||
half _CharacterAreaColorFillUVOption;
|
||||
|
||||
// Dither Opacity
|
||||
half _DitherOpacity;
|
||||
|
||||
// Dither Fadeout
|
||||
half _DitherFadeoutAmount;
|
||||
half _DitherFadeoutNormalScaleFix;
|
||||
half _AllowPerCharacterDitherFadeout;
|
||||
|
||||
// Perspective Removal
|
||||
half _PerspectiveRemovalAmount;
|
||||
half _PerspectiveRemovalRadius;
|
||||
half _PerspectiveRemovalStartHeight;
|
||||
half _PerspectiveRemovalEndHeight;
|
||||
|
||||
// ZOffset
|
||||
half _PerCharacterZOffset;
|
||||
|
||||
// Character ID (for accessing global arrays)
|
||||
uint _CharacterID;
|
||||
CBUFFER_END
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// NiloToon Global Per-Character Arrays
|
||||
// For properties that change every frame, use global arrays instead of CBUFFER for performance
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
#ifndef MAX_CHARACTER_COUNT
|
||||
#define MAX_CHARACTER_COUNT 256
|
||||
#endif
|
||||
|
||||
float3 _NiloToonGlobalPerCharHeadBonePosWSArray[MAX_CHARACTER_COUNT];
|
||||
float3 _NiloToonGlobalPerCharFaceForwardDirWSArray[MAX_CHARACTER_COUNT];
|
||||
float3 _NiloToonGlobalPerCharFaceUpwardDirWSArray[MAX_CHARACTER_COUNT];
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// Texture Declarations (all textures declared unconditionally to avoid compilation issues)
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -156,6 +231,17 @@ TEXTURE2D(_OcclusionMap); SAMPLER(sampler_OcclusionMap);
|
||||
// Outline
|
||||
TEXTURE2D(_OutlineWidthMask); SAMPLER(sampler_OutlineWidthMask);
|
||||
|
||||
// Dissolve
|
||||
#if _NILOTOON_DISSOLVE
|
||||
TEXTURE2D(_DissolveThresholdMap); SAMPLER(sampler_DissolveThresholdMap);
|
||||
#endif
|
||||
|
||||
// BaseMap Override
|
||||
TEXTURE2D(_PerCharacterBaseMapOverrideMap); SAMPLER(sampler_PerCharacterBaseMapOverrideMap);
|
||||
|
||||
// Character Area Color Fill
|
||||
TEXTURE2D(_CharacterAreaColorFillTexture); SAMPLER(sampler_CharacterAreaColorFillTexture);
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
// Vertex Input Structure
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -386,6 +472,23 @@ Varyings vert(Attributes input)
|
||||
output.tangentWS = float4(normalInput.tangentWS, input.tangentOS.w);
|
||||
output.uv = TRANSFORM_TEX(input.uv, _BaseMap);
|
||||
|
||||
// Apply Perspective Removal
|
||||
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;
|
||||
}
|
||||
|
||||
// Shadow coord
|
||||
output.shadowCoord = GetShadowCoordSafe(vertexInput);
|
||||
|
||||
@ -412,9 +515,11 @@ V2G vert_fur(Attributes input)
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
|
||||
|
||||
// Transform position and normal to world space
|
||||
// IMPORTANT: Use GetVertexPositionInputs to match Base Pass transformation exactly
|
||||
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
|
||||
VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
|
||||
|
||||
output.positionWS = TransformObjectToWorld(input.positionOS.xyz);
|
||||
output.positionWS = vertexInput.positionWS;
|
||||
output.normalWS = normalInput.normalWS;
|
||||
output.tangentWS = float4(normalInput.tangentWS, input.tangentOS.w);
|
||||
output.uv = TRANSFORM_TEX(input.uv, _BaseMap);
|
||||
@ -429,6 +534,11 @@ V2G vert_fur(Attributes input)
|
||||
float furLengthMask = SAMPLE_TEXTURE2D_LOD(_FurLengthMask, sampler_FurLengthMask, input.uv * _FurLengthMask_ST.xy + _FurLengthMask_ST.zw, 0).r;
|
||||
output.furVector *= furLengthMask;
|
||||
|
||||
// Note: Perspective Removal and Z offset will be applied in geometry shader
|
||||
// We don't apply them here in vertex shader for fur shells
|
||||
// because geometry shader generates multiple shells and needs to apply
|
||||
// the transformations consistently to all generated vertices
|
||||
|
||||
// Fog
|
||||
float4 posCS = TransformWorldToHClip(output.positionWS);
|
||||
output.fogFactor = ComputeFogFactor(posCS.z);
|
||||
|
||||
@ -1,156 +0,0 @@
|
||||
// NiloToon Character Fur Shell Only Shader
|
||||
// Use this shader on a second material slot to render fur shells
|
||||
// The base mesh should use NiloToonCharacter or NiloToonCharacterFur shader
|
||||
|
||||
Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur_ShellOnly"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
_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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[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
|
||||
|
||||
[Header(Outline)]
|
||||
[Space(5)]
|
||||
_OutlineWidth("Outline Width", Range(0, 10)) = 0
|
||||
[HDR] _OutlineColor("Outline Color", Color) = (0, 0, 0, 1)
|
||||
_OutlineWidthMask("Outline Width Mask", 2D) = "white" {}
|
||||
|
||||
[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) = 0
|
||||
_FurZWrite("Fur ZWrite", Float) = 0
|
||||
[Enum(UnityEngine.Rendering.CompareFunction)] _ZTest("ZTest", Float) = 4
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"RenderType" = "Transparent"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
"IgnoreProjector" = "True"
|
||||
"Queue" = "Transparent-50"
|
||||
}
|
||||
LOD 300
|
||||
|
||||
// Fur Shell Pass
|
||||
Pass
|
||||
{
|
||||
Name "FurShell"
|
||||
Tags { "LightMode" = "UniversalForward" }
|
||||
|
||||
Cull [_FurCull]
|
||||
ZWrite [_FurZWrite]
|
||||
ZTest LEqual
|
||||
Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma target 4.5
|
||||
#pragma require geometry
|
||||
|
||||
#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 _ _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
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
||||
FallBack Off
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b3349963a9dea04da1b88df137b8d82
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Resources/Settings/Streamingle Render Pipeline Asset_Renderer.asset
(Stored with Git LFS)
BIN
Assets/Resources/Settings/Streamingle Render Pipeline Asset_Renderer.asset
(Stored with Git LFS)
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user