Shader "Soullies/DTM_RandomGridFloor" { Properties { [HDR]_Color0("Color0", Color) = (1, 1, 1, 0) [Header(Pattern Settings)] _PatternSize("Pattern Size (X, Y)", Vector) = (2.0, 2.0, 0, 0) _GridDensity("Grid Density (Quantity Multiplier)", Float) = 1.0 _TimeAngle("Time Angle (Speed)", Float) = 1.0 [Header(Edge Settings)] _StepA("Step A", Range(0, 1)) = 0.293 _StepB("Step B", Range(0, 1)) = 0.345 [Header(Outer Enclosing Border)] [Toggle(_OUTER_BORDER_ON)] _EnableOuterBorder("Enable Outer Border", Float) = 0 [HDR] _OuterBorderColor("Outer Border Color", Color) = (1, 1, 1, 1) _OuterBorderWidth("Outer Border Width", Range(0.0, 0.5)) = 0.02 [Header(Render State)] [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Src Blend", Float) = 5 // SrcAlpha [Enum(UnityEngine.Rendering.BlendMode)] _DstBlend("Dst Blend", Float) = 10 // OneMinusSrcAlpha [Enum(Off, 0, On, 1)] _ZWrite("Z Write", Float) = 0 [Enum(Front, Back, Off)] _CullMode("Cull Mode", Float) = 2 // Off } SubShader { Tags { "RenderPipeline" = "UniversalPipeline" "RenderType" = "Transparent" "Queue" = "Transparent-300" "UniversalMaterialType" = "Unlit" "IgnoreProjector" = "True" } Blend [_SrcBlend] [_DstBlend] ZWrite [_ZWrite] Cull [_CullMode] Pass { Name "ForwardOnly" Tags { "LightMode" = "UniversalForwardOnly" } HLSLPROGRAM // ------------------------------------- // Target Config #pragma target 4.5 #pragma prefer_hlslcc gles // DOTS and Instancing #pragma multi_compile_instancing #pragma multi_compile_fog // Feature Flags #pragma shader_feature_local _OUTER_BORDER_ON #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; float3 positionWS : TEXCOORD0; float2 uv : TEXCOORD1; half fogFactor : TEXCOORD2; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO }; CBUFFER_START(UnityPerMaterial) half4 _Color0; float4 _PatternSize; float _GridDensity; float _TimeAngle; float _StepA; float _StepB; half4 _OuterBorderColor; float _OuterBorderWidth; CBUFFER_END // ------------------------------------- // Custom Helper Functions float2 VoronoiHash(float2 p) { p = float2(dot(p, float2(127.1, 311.7)), dot(p, float2(269.5, 183.3))); return frac(sin(p) * 43758.5453); } // Manhattan-based Voronoi optimized for Mobile URP float VoronoiDistance(float2 v, float t) { float2 n = floor(v); float2 f = frac(v); float minDist = 8.0; UNITY_UNROLL for (int j = -1; j <= 1; j++) { UNITY_UNROLL for (int i = -1; i <= 1; i++) { float2 g = float2((float)i, (float)j); float2 o = VoronoiHash(n + g); // Oscillating movement o = sin(t + o * 6.2831853) * 0.5 + 0.5; float2 r = f - g - o; // Manhattan distance for rectangular frames float d = 0.5 * (abs(r.x) + abs(r.y)); minDist = min(minDist, d); } } return minDist; } // ------------------------------------- // Vertex Shader Varyings vert(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz); output.positionCS = vertexInput.positionCS; output.positionWS = vertexInput.positionWS; output.uv = input.uv; output.fogFactor = ComputeFogFactor(vertexInput.positionCS.z); return output; } // ------------------------------------- // Fragment Shader half4 frag(Varyings input) : SV_Target { UNITY_SETUP_INSTANCE_ID(input); UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input); // ========================================== // 1. inner Grid Pattern Calculation // ========================================== float2 worldUV = input.positionWS.xz; // Density Multiplier: Higher density = smaller frames = more quantity float density = max(_GridDensity, 0.0001); float2 sizeDivisor = max(_PatternSize.xy, float2(0.0001, 0.0001)) / density; float2 scaledUV = worldUV / sizeDivisor; // Rotate 45 degrees float c = 0.707106; float s = 0.707106; float2 rotatedUV = mul(scaledUV, float2x2(c, -s, s, c)); // Time driven animation float t = _TimeAngle * _TimeParameters.x; // Voronoi mathematical noise float v = VoronoiDistance(rotatedUV, t); // Anti-aliased border mask computation float fw = fwidth(v); float edge1 = smoothstep(_StepA - fw, _StepA + fw, v); float edge2 = smoothstep(_StepB - fw, _StepB + fw, v); float gridAlphaMask = edge2 - edge1; half3 gridColor = _Color0.rgb; half gridAlpha = gridAlphaMask * _Color0.a; // ========================================== // 2. Outer Enclosing Border // ========================================== half3 finalColor = gridColor; half finalAlpha = gridAlpha; #if defined(_OUTER_BORDER_ON) // Calculate distance to nearest UV edge float2 edgeDist = min(input.uv, 1.0 - input.uv); float closestEdge = min(edgeDist.x, edgeDist.y); // Uses fwidth for clean smoothstep transition at the edge float borderfw = fwidth(closestEdge); // Creates a solid border with a smooth antialiased inner falloff float borderMask = 1.0 - smoothstep(_OuterBorderWidth - borderfw, _OuterBorderWidth + borderfw, closestEdge); // Lerp grid to border finalColor = lerp(gridColor, _OuterBorderColor.rgb, borderMask); finalAlpha = lerp(gridAlpha, _OuterBorderColor.a, borderMask); #endif // Apply URP Fog finalColor = MixFog(finalColor, input.fogFactor); return half4(finalColor, finalAlpha); } ENDHLSL } } FallBack "Hidden/Universal Render Pipeline/FallbackError" }