Shader "SLS/Postprocessing/HyperTunnel" { SubShader { Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" } ZWrite Off Cull Off ZTest Always HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" float4 _HyperTunnelColor; // x: speed, y: intensity, z: radial blur amount, w: CA intensity float4 _HyperTunnelParams; float2 _HyperTunnelCenter; // --- Fast Mobile-friendly Simplex Noise --- float3 mod2D289(float3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } float2 mod2D289(float2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } float3 permute(float3 x) { return mod2D289(((x * 34.0) + 1.0) * x); } float snoise(float2 v) { const float4 C = float4(0.211324865, 0.366025403, -0.577350269, 0.024390243); float2 i = floor(v + dot(v, C.yy)); float2 x0 = v - i + dot(i, C.xx); float2 i1 = (x0.x > x0.y) ? float2(1.0, 0.0) : float2(0.0, 1.0); float4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1; i = mod2D289(i); float3 p = permute(permute(i.y + float3(0.0, i1.y, 1.0)) + i.x + float3(0.0, i1.x, 1.0)); float3 m = max(0.5 - float3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0); m = m * m; m = m * m; float3 x = 2.0 * frac(p * C.www) - 1.0; float3 h = abs(x) - 0.5; float3 ox = floor(x + 0.5); float3 a0 = x - ox; m *= 1.792842914 - 0.85373472 * (a0 * a0 + h * h); float3 g; g.x = a0.x * x0.x + h.x * x0.y; g.yz = a0.yz * x12.xz + h.yz * x12.yw; return 130.0 * dot(m, g); } half4 Fragment(Varyings input) : SV_Target { float2 uv = input.texcoord; // parameter unpacking setup float speed = _HyperTunnelParams.x; float lineIntensity = _HyperTunnelParams.y; float blurAmount = _HyperTunnelParams.z; float caIntensity = _HyperTunnelParams.w; float2 center = _HyperTunnelCenter; // distance vector from center float2 dir = uv - center; float dist = length(dir); float2 normDir = dir / (dist + 0.0001); // avoid div zero // Mask out the center (Tunnel illusion) // No blur or lines in the exact center focus point float centerMask = smoothstep(0.05, 0.4, dist); // =================================== // 1. Radial Blur + Chromatic Aberration // =================================== // Mobile Optimization: Interleaved 4 loop calculation int samples = 4; float intensityMultiplier = centerMask; half3 finalColor = half3(0, 0, 0); // Unroll loop for mobile shader registers UNITY_UNROLL for(int i = 0; i < 4; ++i) { float t = (float)i / (3.0); float2 offsetBlur = dir * t * blurAmount * intensityMultiplier; // CA offsets are tangent along the line float2 uvR = uv - offsetBlur + normDir * caIntensity * intensityMultiplier * 0.005; float2 uvG = uv - offsetBlur; float2 uvB = uv - offsetBlur - normDir * caIntensity * intensityMultiplier * 0.005; half r = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uvR).r; half g = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uvG).g; half b = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uvB).b; finalColor += half3(r, g, b); } finalColor *= 0.25; // =================================== // 2. Hyper Speed Lines Overlay // =================================== // Convert to Polar coordinates float angle = atan2(dir.y, dir.x); float timeScaled = _Time.y * speed; float2 noiseUV = float2(angle * 15.0, timeScaled + dist * 5.0); float noiseVal = snoise(noiseUV) * 0.5 + 0.5; // [-1,1] to [0,1] // Power curve for intense sharp lines float lines = pow(noiseVal, 9.0) * lineIntensity; lines *= centerMask; half3 hcColor = _HyperTunnelColor.rgb * (_HyperTunnelColor.a * lines); return half4(finalColor + hcColor, 1.0); } ENDHLSL Pass { Name "Hyper Tunnel Pass" HLSLPROGRAM #pragma vertex Vert #pragma fragment Fragment ENDHLSL } } }