@@ -146,6 +146,37 @@ Shader "Soullies/DTM_RandomGridFloor"
|
||||
return minDist;
|
||||
}
|
||||
|
||||
float DistanceFadeMaskWithEarlyClip(float3 positionWS)
|
||||
{
|
||||
float3 cameraDelta = positionWS - GetCameraPositionWS();
|
||||
float distSq = dot(cameraDelta, cameraDelta);
|
||||
float clipDistance = max(max(_FadeFar, _FadeNear), 0.0001);
|
||||
|
||||
clip(clipDistance * clipDistance - distSq);
|
||||
|
||||
float nearSq = _FadeNear * _FadeNear;
|
||||
float farSq = _FadeFar * _FadeFar;
|
||||
return saturate((distSq - farSq) / (nearSq - farSq + 0.0001));
|
||||
}
|
||||
|
||||
float GridLineMaskCentered(float v)
|
||||
{
|
||||
float lowerStep = min(_StepA, _StepB);
|
||||
float upperStep = max(_StepA, _StepB);
|
||||
float stepWidth = upperStep - lowerStep;
|
||||
float center = (lowerStep + upperStep) * 0.5;
|
||||
float halfWidth = max(stepWidth * 0.5, 0.000001);
|
||||
float fw = max(fwidth(v), 0.000001);
|
||||
float widthMask = step(0.000001, stepWidth);
|
||||
|
||||
float lowerEdge = center - halfWidth;
|
||||
float upperEdge = center + halfWidth;
|
||||
float lowerMask = smoothstep(lowerEdge - fw, lowerEdge + fw, v);
|
||||
float upperMask = smoothstep(upperEdge - fw, upperEdge + fw, v);
|
||||
|
||||
return saturate(lowerMask - upperMask) * widthMask;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Vertex Shader
|
||||
Varyings vert(Attributes input)
|
||||
@@ -174,6 +205,8 @@ Shader "Soullies/DTM_RandomGridFloor"
|
||||
// ==========================================
|
||||
// 1. inner Grid Pattern Calculation
|
||||
// ==========================================
|
||||
float fadeMask = DistanceFadeMaskWithEarlyClip(input.positionWS);
|
||||
|
||||
float2 worldUV = input.positionWS.xz;
|
||||
|
||||
// Density Multiplier: Higher density = smaller frames = more quantity
|
||||
@@ -194,10 +227,7 @@ Shader "Soullies/DTM_RandomGridFloor"
|
||||
float v = VoronoiDistanceFast(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;
|
||||
float gridAlphaMask = GridLineMaskCentered(v);
|
||||
|
||||
half3 gridColor = _Color0.rgb;
|
||||
half gridAlpha = gridAlphaMask * _Color0.a;
|
||||
@@ -227,13 +257,6 @@ Shader "Soullies/DTM_RandomGridFloor"
|
||||
// ==========================================
|
||||
// 3. Distance Fade (Far = Transparent, Near = Opaque)
|
||||
// ==========================================
|
||||
float distToCam = distance(GetCameraPositionWS(), input.positionWS);
|
||||
|
||||
// When dist >= _FadeFar => fadeMask = 0 (Fully Transparent)
|
||||
// When dist <= _FadeNear => fadeMask = 1 (Fully Opaque)
|
||||
float rawFade = (distToCam - _FadeFar) / (_FadeNear - _FadeFar + 0.0001);
|
||||
float fadeMask = saturate(rawFade);
|
||||
|
||||
finalAlpha *= fadeMask;
|
||||
|
||||
// Apply URP Fog
|
||||
|
||||
@@ -23,6 +23,7 @@ Shader "Soullies/DTM_RandomGridTube"
|
||||
_FadeFar("Fade Far (Fully Transparent)", Float) = 100.0
|
||||
_FadeNear("Fade Near (Fully Opaque)", Float) = 20.0
|
||||
_TubeRadius("Virtual Tube Radius", Float) = 10.0
|
||||
[Toggle(_USE_MESH_UV_ON)] _UseMeshUV("Use Mesh UV U Mapping", Float) = 0
|
||||
|
||||
[Header(Render State)]
|
||||
[Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend("Src Blend", Float) = 5 // SrcAlpha
|
||||
@@ -56,6 +57,7 @@ Shader "Soullies/DTM_RandomGridTube"
|
||||
#pragma prefer_hlslcc gles
|
||||
#pragma multi_compile_instancing
|
||||
#pragma multi_compile_fog
|
||||
#pragma shader_feature_local _USE_MESH_UV_ON
|
||||
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
@@ -74,6 +76,7 @@ Shader "Soullies/DTM_RandomGridTube"
|
||||
float4 positionCS : SV_POSITION;
|
||||
float3 positionWS : TEXCOORD0;
|
||||
float3 positionOS : TEXCOORD1;
|
||||
float2 uv : TEXCOORD2;
|
||||
half fogFactor : TEXCOORD3;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
UNITY_VERTEX_OUTPUT_STEREO
|
||||
@@ -144,6 +147,44 @@ Shader "Soullies/DTM_RandomGridTube"
|
||||
return minDist;
|
||||
}
|
||||
|
||||
float WrapAngle(float angle)
|
||||
{
|
||||
if(angle > 3.14159265) angle -= 6.2831853;
|
||||
if(angle < -3.14159265) angle += 6.2831853;
|
||||
return angle;
|
||||
}
|
||||
|
||||
float DistanceFadeMaskWithEarlyClip(float3 positionWS)
|
||||
{
|
||||
float3 cameraDelta = positionWS - GetCameraPositionWS();
|
||||
float distSq = dot(cameraDelta, cameraDelta);
|
||||
float clipDistance = max(max(_FadeFar, _FadeNear), 0.0001);
|
||||
|
||||
clip(clipDistance * clipDistance - distSq);
|
||||
|
||||
float nearSq = _FadeNear * _FadeNear;
|
||||
float farSq = _FadeFar * _FadeFar;
|
||||
return saturate((distSq - farSq) / (nearSq - farSq + 0.0001));
|
||||
}
|
||||
|
||||
float GridLineMaskCentered(float v)
|
||||
{
|
||||
float lowerStep = min(_StepA, _StepB);
|
||||
float upperStep = max(_StepA, _StepB);
|
||||
float stepWidth = upperStep - lowerStep;
|
||||
float center = (lowerStep + upperStep) * 0.5;
|
||||
float halfWidth = max(stepWidth * 0.5, 0.000001);
|
||||
float fw = max(fwidth(v), 0.000001);
|
||||
float widthMask = step(0.000001, stepWidth);
|
||||
|
||||
float lowerEdge = center - halfWidth;
|
||||
float upperEdge = center + halfWidth;
|
||||
float lowerMask = smoothstep(lowerEdge - fw, lowerEdge + fw, v);
|
||||
float upperMask = smoothstep(upperEdge - fw, upperEdge + fw, v);
|
||||
|
||||
return saturate(lowerMask - upperMask) * widthMask;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
// Vertex Shader
|
||||
Varyings vert(Attributes input)
|
||||
@@ -157,6 +198,7 @@ Shader "Soullies/DTM_RandomGridTube"
|
||||
output.positionCS = vertexInput.positionCS;
|
||||
output.positionWS = vertexInput.positionWS;
|
||||
output.positionOS = input.positionOS.xyz;
|
||||
output.uv = input.uv;
|
||||
output.fogFactor = ComputeFogFactor(vertexInput.positionCS.z);
|
||||
|
||||
return output;
|
||||
@@ -172,16 +214,22 @@ Shader "Soullies/DTM_RandomGridTube"
|
||||
// ==========================================
|
||||
// 1. Cylindrical Mapping & Seam Control
|
||||
// ==========================================
|
||||
// Calculate angle around the Z-axis in object space. atan2 returns [-PI, PI].
|
||||
float rawAngle = atan2(input.positionOS.y, input.positionOS.x);
|
||||
float fadeMask = DistanceFadeMaskWithEarlyClip(input.positionWS);
|
||||
|
||||
// Rotate the seam mechanically
|
||||
float angleOffset = _SeamRotation * (3.14159265 / 180.0);
|
||||
|
||||
#if defined(_USE_MESH_UV_ON)
|
||||
float rawAngle = input.uv.x * 6.2831853 - 3.14159265;
|
||||
#else
|
||||
// Calculate angle around the Z-axis in object space. atan2 returns [-PI, PI].
|
||||
float rawAngle = atan2(input.positionOS.y, input.positionOS.x);
|
||||
#endif
|
||||
|
||||
float angle = rawAngle + angleOffset;
|
||||
|
||||
// Wrap angle to [-PI, PI] to keep math bounded
|
||||
if(angle > 3.14159265) angle -= 6.2831853;
|
||||
if(angle < -3.14159265) angle += 6.2831853;
|
||||
angle = WrapAngle(angle);
|
||||
|
||||
// Derive distance to the seam (seam is at absolute PI or -PI)
|
||||
float distToSeam = 3.14159265 - abs(angle);
|
||||
@@ -218,10 +266,7 @@ Shader "Soullies/DTM_RandomGridTube"
|
||||
float voronoiV = VoronoiDistanceFast(rotatedUV, t);
|
||||
|
||||
// Anti-aliased border mask computation
|
||||
float fw = fwidth(voronoiV);
|
||||
float edge1 = smoothstep(_StepA - fw, _StepA + fw, voronoiV);
|
||||
float edge2 = smoothstep(_StepB - fw, _StepB + fw, voronoiV);
|
||||
float gridAlphaMask = edge2 - edge1;
|
||||
float gridAlphaMask = GridLineMaskCentered(voronoiV);
|
||||
|
||||
half3 gridColor = _Color0.rgb;
|
||||
half gridAlpha = gridAlphaMask * _Color0.a;
|
||||
@@ -229,14 +274,6 @@ Shader "Soullies/DTM_RandomGridTube"
|
||||
// ==========================================
|
||||
// 2. Distance Fade (Far = Transparent, Near = Opaque)
|
||||
// ==========================================
|
||||
float distToCam = distance(GetCameraPositionWS(), input.positionWS);
|
||||
|
||||
// If distToCam is between _FadeFar and _FadeNear, smoothly transition
|
||||
// When dist = _FadeFar, fadeMask = 0 (Transparent)
|
||||
// When dist = _FadeNear, fadeMask = 1 (Opaque)
|
||||
float rawFade = (distToCam - _FadeFar) / (_FadeNear - _FadeFar + 0.0001);
|
||||
float fadeMask = saturate(rawFade);
|
||||
|
||||
// Multiply the alpha by our camera distance fade AND seam smooth fade
|
||||
gridAlpha *= fadeMask * seamFadeMask;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user