diff --git a/Assets/Shaders/PlayerCamo.hlsl b/Assets/Shaders/PlayerCamo.hlsl index 48d54a5..53fc855 100644 --- a/Assets/Shaders/PlayerCamo.hlsl +++ b/Assets/Shaders/PlayerCamo.hlsl @@ -55,7 +55,8 @@ float4 _OcclusionMap_TexelSize; // the separate XRayOverlay pass (SRPDefaultUnlit) covers the OCCLUDED parts. See CamoForwardFragment. half4 _XRayColor; half _XRayPulseSpeed; // 0 = steady; otherwise breathing pulse via _Time (see CamoForwardFragment) -half _XRayPulseStrength; // modulation depth of the pulse around the authored intensity +half _XRayPulseStrength; // modulation depth: how far the trough dims below the full-intensity peak +half _XRayPulseShape; // >1 bends the pulse: longer near-off plateau, rising to a brief full peak // Remaps the painted occlusion/height value into surface AO + a relief normal. Runs after URP's // InitializeStandardLitSurfaceData (uv is already parallax-displaced) and before InitializeInputData, @@ -298,9 +299,12 @@ void CamoForwardFragment( // same additive term here reveals the glow on the visible parts too. Visible (here) and occluded // (overlay, ZTest Greater) are mutually exclusive by depth => no double contribution. Added // post-fog to match the overlay, which outputs the raw color. - // Breathing pulse (sin over _Time) on the glow master, matching the XRayOverlay pass exactly so the - // visible and occluded halves stay in phase. Speed 0 => term is 1 => identical to no pulse. - half xrayPulse = 1.0h + sin(_Time.y * _XRayPulseSpeed) * _XRayPulseStrength; + // Asymmetric breathing pulse on the glow master, matching the XRayOverlay pass exactly so the visible + // and occluded halves stay in phase. A raised cosine (0..1, peak once per cycle) raised to _XRayPulseShape + // rises from a long near-off plateau to a brief peak; _XRayPulseStrength sets how deep the trough dims + // (peak stays at the authored intensity). Speed 0 => cos term constant => steady glow. + half xrayCurve = pow(0.5h - 0.5h * cos(_Time.y * _XRayPulseSpeed), _XRayPulseShape); + half xrayPulse = 1.0h - _XRayPulseStrength * (1.0h - xrayCurve); color.rgb += _XRayColor.rgb * (_XRayColor.a * xrayPulse); color.a = OutputAlpha(color.a, IsSurfaceTypeTransparent(_Surface)); diff --git a/Assets/Shaders/PlayerCamoLit.shader b/Assets/Shaders/PlayerCamoLit.shader index eec5ba3..deb75f4 100644 --- a/Assets/Shaders/PlayerCamoLit.shader +++ b/Assets/Shaders/PlayerCamoLit.shader @@ -62,10 +62,13 @@ Shader "Custom/PlayerCamoLit" [HDR] _XRayColor("X-Ray Overlay Color", Color) = (0,0,0,0) // Optional breathing pulse for the X-ray glow (driven by _Time). Speed 0 => steady, identical to - // no pulse; strength = modulation depth around the authored intensity. Applied identically to the - // visible (ForwardLit) and occluded (XRayOverlay) halves so they stay in phase. + // no pulse; strength = modulation depth (how far the trough dims below the peak). Shape bends the + // pulse into an asymmetric curve: 1 = smooth (raised-cosine) breathe, higher = a longer near-off + // plateau that rises to a brief full-intensity peak. Applied identically to the visible (ForwardLit) + // and occluded (XRayOverlay) halves so they stay in phase. _XRayPulseSpeed("X-Ray Pulse Speed", Float) = 3 _XRayPulseStrength("X-Ray Pulse Strength", Range(0,1)) = 0.5 + _XRayPulseShape("X-Ray Pulse Shape", Range(1,8)) = 3 _DetailMask("Detail Mask", 2D) = "white" {} _DetailAlbedoMapScale("Scale", Range(0.0, 2.0)) = 1.0 @@ -260,7 +263,8 @@ Shader "Custom/PlayerCamoLit" // SRP batcher, see PlayerCamo.hlsl), so there is no CBUFFER-layout match to keep here. half4 _XRayColor; half _XRayPulseSpeed; // 0 = steady; otherwise breathing pulse via _Time (same math as the forward half) - half _XRayPulseStrength; // modulation depth of the pulse around the authored intensity + half _XRayPulseStrength; // modulation depth: how far the trough dims below the full-intensity peak + half _XRayPulseShape; // >1 bends the pulse: longer near-off plateau, rising to a brief full peak struct XRayAttributes { @@ -289,10 +293,11 @@ Shader "Custom/PlayerCamoLit" { UNITY_SETUP_INSTANCE_ID(input); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); - // Flat additive glow: HDR rgb is the reveal color, alpha the fade/opacity master. - // Breathing pulse (sin over _Time) on the alpha master; kept in phase with the forward - // half via the shared _Time and identical math. Speed 0 => term is 1 => steady glow. - half xrayPulse = 1.0h + sin(_Time.y * _XRayPulseSpeed) * _XRayPulseStrength; + // Flat additive glow: HDR rgb is the reveal color, alpha the fade/opacity master. Asymmetric + // breathing pulse on the alpha master; kept in phase with the forward half via the shared + // _Time and identical math. Speed 0 => term is 1 => steady glow. See CamoForwardFragment. + half xrayCurve = pow(0.5h - 0.5h * cos(_Time.y * _XRayPulseSpeed), _XRayPulseShape); + half xrayPulse = 1.0h - _XRayPulseStrength * (1.0h - xrayCurve); return half4(_XRayColor.rgb, _XRayColor.a * xrayPulse); } ENDHLSL