diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur.shader b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur.shader index a6838dce..d36cc085 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur.shader +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur.shader @@ -213,6 +213,11 @@ Shader "Universal Render Pipeline/NiloToon/NiloToon_Character_Fur" ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// [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 diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl index f47f8a30..2ebfe2ee 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Fragment.hlsl @@ -46,49 +46,82 @@ void ApplyDissolve(inout half3 color, float2 uv, float3 positionWS, float4 posit half dissolveMapThresholdMapValue = 0; + // UV1 - sample .g channel (matching NiloToonCharacter) if(_DissolveMode == DISSOLVEMODE_UV1) { float2 dissolveUV = uv * uvTiling; - dissolveMapThresholdMapValue = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).r; + dissolveMapThresholdMapValue = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g; } + // WorldSpaceNoise - 3-axis multiplication (matching NiloToonCharacter) 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; + float2 dissolveUV; + + dissolveUV = positionWS.xz * uvTiling; + dissolveMapThresholdMapValue = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g; + + dissolveUV = positionWS.xy * uvTiling; + dissolveMapThresholdMapValue *= SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g; + + dissolveUV = positionWS.yz * uvTiling; + dissolveMapThresholdMapValue *= SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g; } + // WorldSpaceVerticalUpward - use character bound data from global arrays 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); + // Calculate character bound from center pos and radius (same as NiloToonCharacter) + float3 characterBoundCenterPosWS = _NiloToonGlobalPerCharBoundCenterPosWSArray[_CharacterID]; + float characterBoundBottom = characterBoundCenterPosWS.y - _CharacterBoundRadius; + float characterBoundTop = characterBoundCenterPosWS.y + _CharacterBoundRadius; + dissolveMapThresholdMapValue = invLerpClamp(characterBoundBottom, characterBoundTop, positionWS.y + noise); } + // WorldSpaceVerticalDownward - use character bound data from global arrays 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); + // Calculate character bound from center pos and radius (same as NiloToonCharacter) + float3 characterBoundCenterPosWS = _NiloToonGlobalPerCharBoundCenterPosWSArray[_CharacterID]; + float characterBoundBottom = characterBoundCenterPosWS.y - _CharacterBoundRadius; + float characterBoundTop = characterBoundCenterPosWS.y + _CharacterBoundRadius; + dissolveMapThresholdMapValue = invLerpClamp(characterBoundTop, characterBoundBottom, positionWS.y + noise); } + // ScreenSpaceNoise - use character bound 2D rect UV (matching NiloToonCharacter) 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; + // Calculate character bound 2D rect UV using Calc3DSphereTo2DUV (same as NiloToonCharacter) + float3 characterBoundCenterPosWS = _NiloToonGlobalPerCharBoundCenterPosWSArray[_CharacterID]; + float2 characterBound2DRectUV01 = Calc3DSphereTo2DUV(positionWS, characterBoundCenterPosWS, _CharacterBoundRadius); + + // since the default bounding sphere is 2.5m, when compared to world space, it should have 2.5x Tiling + float2 dissolveUV = characterBound2DRectUV01 * uvTiling * 2.5; + dissolveMapThresholdMapValue = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g; } + // ScreenSpaceVerticalUpward else if(_DissolveMode == DISSOLVEMODE_ScreenSpaceVerticalUpward) { - float2 screenUV = positionCS.xy / positionCS.w; - float2 dissolveUV = screenUV * uvTiling; + // Calculate character bound 2D rect UV using Calc3DSphereTo2DUV (same as NiloToonCharacter) + float3 characterBoundCenterPosWS = _NiloToonGlobalPerCharBoundCenterPosWSArray[_CharacterID]; + float2 characterBound2DRectUV01 = Calc3DSphereTo2DUV(positionWS, characterBoundCenterPosWS, _CharacterBoundRadius); + + // since the default bounding sphere is 2.5m, when compared to world space, it should have 2.5x Tiling + float2 dissolveUV = characterBound2DRectUV01 * uvTiling * 2.5; float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength; - dissolveMapThresholdMapValue = saturate(screenUV.y + noise); + dissolveMapThresholdMapValue = saturate(characterBound2DRectUV01.y + noise); } + // ScreenSpaceVerticalDownward else if(_DissolveMode == DISSOLVEMODE_ScreenSpaceVerticalDownward) { - float2 screenUV = positionCS.xy / positionCS.w; - float2 dissolveUV = screenUV * uvTiling; + // Calculate character bound 2D rect UV using Calc3DSphereTo2DUV (same as NiloToonCharacter) + float3 characterBoundCenterPosWS = _NiloToonGlobalPerCharBoundCenterPosWSArray[_CharacterID]; + float2 characterBound2DRectUV01 = Calc3DSphereTo2DUV(positionWS, characterBoundCenterPosWS, _CharacterBoundRadius); + + // since the default bounding sphere is 2.5m, when compared to world space, it should have 2.5x Tiling + float2 dissolveUV = characterBound2DRectUV01 * uvTiling * 2.5; float noise = SAMPLE_TEXTURE2D(_DissolveThresholdMap, sampler_DissolveThresholdMap, dissolveUV).g * noiseStrength; - dissolveMapThresholdMapValue = saturate((1 - screenUV.y) + noise); + dissolveMapThresholdMapValue = saturate((1 - characterBound2DRectUV01.y) + noise); } half dissolve = dissolveMapThresholdMapValue - finalDissolveAmount; diff --git a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl index a958ffbf..5f0fe867 100644 --- a/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl +++ b/Assets/NiloToonURP/Shaders/NiloToonCharacterFur_HLSL/NiloToonCharacterFur_Shared.hlsl @@ -13,6 +13,7 @@ #include "../../ShaderLibrary/NiloUtilityHLSL/NiloBlendEquationUtil.hlsl" #include "../../ShaderLibrary/NiloUtilityHLSL/NiloDitherFadeoutClipUtil.hlsl" #include "../../ShaderLibrary/NiloUtilityHLSL/NiloPerspectiveRemovalUtil.hlsl" +#include "../../ShaderLibrary/NiloUtilityHLSL/NiloUVCalculateUtil.hlsl" //------------------------------------------------------------------------------------------------------------------------------ // NiloToon Global Light Override Variables (from NiloToonCharacterMainLightOverrider) @@ -189,6 +190,9 @@ CBUFFER_START(UnityPerMaterial) // ZOffset half _PerCharacterZOffset; + // Character Bound (for dissolve) + float _CharacterBoundRadius; + // Character ID (for accessing global arrays) uint _CharacterID; CBUFFER_END @@ -204,6 +208,7 @@ CBUFFER_END float3 _NiloToonGlobalPerCharHeadBonePosWSArray[MAX_CHARACTER_COUNT]; float3 _NiloToonGlobalPerCharFaceForwardDirWSArray[MAX_CHARACTER_COUNT]; float3 _NiloToonGlobalPerCharFaceUpwardDirWSArray[MAX_CHARACTER_COUNT]; +float3 _NiloToonGlobalPerCharBoundCenterPosWSArray[MAX_CHARACTER_COUNT]; //------------------------------------------------------------------------------------------------------------------------------ // Texture Declarations (all textures declared unconditionally to avoid compilation issues)