Files
ichni_Official/Assets/ThemeBundles/DepartureToMultiverse/Shaders/DTM_RandomGridTube.shader
SoulliesOfficial f4068baf4a GPU优化
2026-04-06 09:32:56 -04:00

253 lines
10 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Shader "Soullies/DTM_RandomGridTube"
{
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
_BaseSpeed("Base Speed (Static)", Float) = 1.0
_TimeAngle("Time Angle / Offset (Dynamic)", Float) = 0.0
[Header(Edge Settings)]
_StepA("Step A", Range(0, 1)) = 0.293
_StepB("Step B", Range(0, 1)) = 0.345
[Header(Seam Hiding)]
_SeamRotation("Seam Angle Offset", Range(-180, 180)) = -90.0
_SeamFadeWidth("Seam Cut Width", Range(0.0, 1.0)) = 0.2
_SeamFadeSmoothness("Seam Softness", Range(0.0, 1.0)) = 1.0
[Header(Tube Specific Settings)]
_FadeFar("Fade Far (Fully Transparent)", Float) = 100.0
_FadeNear("Fade Near (Fully Opaque)", Float) = 20.0
_TubeRadius("Virtual Tube Radius", Float) = 10.0
[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, 0, Back, 1, Off, 2)] _CullMode("Cull Mode", Float) = 1 // Front (Inside)
}
SubShader
{
Tags
{
"RenderPipeline" = "UniversalPipeline"
"RenderType" = "Transparent"
"Queue" = "Transparent-300"
"UniversalMaterialType" = "Unlit"
"IgnoreProjector" = "True"
}
Blend [_SrcBlend] [_DstBlend]
ZWrite [_ZWrite]
Cull [_CullMode] // Default Cull Front to see inside the tube
Pass
{
Name "ForwardOnly"
Tags { "LightMode" = "UniversalForwardOnly" }
HLSLPROGRAM
#pragma target 4.5
#pragma prefer_hlslcc gles
#pragma multi_compile_instancing
#pragma multi_compile_fog
#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;
float3 positionOS : TEXCOORD1;
half fogFactor : TEXCOORD3;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
CBUFFER_START(UnityPerMaterial)
half4 _Color0;
float4 _PatternSize;
float _GridDensity;
float _BaseSpeed;
float _TimeAngle;
float _StepA;
float _StepB;
float _SeamRotation;
float _SeamFadeWidth;
float _SeamFadeSmoothness;
float _FadeFar;
float _FadeNear;
float _TubeRadius;
CBUFFER_END
// -------------------------------------
// 极限优化工具库组 (无三角函数全MAD指令)
// Fast 2D Hash (纯乘加与小数截断,干掉 sin)
float2 FastHash22(float2 p)
{
float3 p3 = frac(float3(p.xyx) * float3(0.1031, 0.1030, 0.0973));
p3 += dot(p3, p3.yzx + 33.33);
return frac((p3.xx + p3.yz) * p3.zy);
}
// Extreme Optimized 4-Tap Voronoi for Mobile (从9次循环砍至4次)
float VoronoiDistanceFast(float2 v, float t)
{
float2 n = floor(v);
float2 f = frac(v);
// 象限锚定算出像素所处方格的偏向完美剔除背面5个不可能相邻的远格
float2 mg = step(0.5, f);
float minDist = 8.0;
UNITY_UNROLL
for (int j = 0; j <= 1; j++)
{
UNITY_UNROLL
for (int i = 0; i <= 1; i++)
{
// 检索偏向象限的核心 4 个格子
float2 g = mg + float2(i - 1.0, j - 1.0);
float2 hash = FastHash22(n + g);
// 剔除昂贵的 sin 并换用平滑三角波:
// t * 0.1591549 即相当于 t / (2*PI) 把时间归一化到周期
float2 phase = frac(t * 0.1591549 + hash);
float2 tri = abs(phase * 2.0 - 1.0); // 线性三角波 1 -> 0 -> 1
float2 o = tri * tri * (3.0 - 2.0 * tri); // 光滑三次曲线,模拟 sin 的柔顺运动
float2 r = f - g - o;
// Manhattan 曼哈顿距离
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.positionOS = input.positionOS.xyz;
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. 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);
// Rotate the seam mechanically
float angleOffset = _SeamRotation * (3.14159265 / 180.0);
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;
// Derive distance to the seam (seam is at absolute PI or -PI)
float distToSeam = 3.14159265 - abs(angle);
// Seam alpha fading calculation
float endFade = _SeamFadeWidth * 3.14159265;
float startFade = endFade * (1.0 - _SeamFadeSmoothness);
float seamFadeMask = smoothstep(startFade, endFade + 0.0001, distToSeam);
// Convert adjusted angle to U coordinate
float u = angle * _TubeRadius;
// V is driven by Object Z scaled by World Scale to maintain seamless tiling and resist rotation stretching
float scaleZ = length(float3(unity_ObjectToWorld[0].z, unity_ObjectToWorld[1].z, unity_ObjectToWorld[2].z));
float v = input.positionOS.z * scaleZ;
float2 cylindricalUV = float2(u, v);
// Density Multiplier
float density = max(_GridDensity, 0.0001);
float2 sizeDivisor = max(_PatternSize.xy, float2(0.0001, 0.0001)) / density;
float2 scaledUV = cylindricalUV / sizeDivisor;
// Rotate 45 degrees
float c = 0.707106;
float s = 0.707106;
float2 rotatedUV = mul(scaledUV, float2x2(c, -s, s, c));
// Time driven animation (Base Time + Phase Offset)
float t = _TimeParameters.x * _BaseSpeed + _TimeAngle;
// [TA 极限计算压缩] 使用 4-Tap、零三角函数的极简数学方法保持无限分辨率。
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;
half3 gridColor = _Color0.rgb;
half gridAlpha = gridAlphaMask * _Color0.a;
// ==========================================
// 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;
// Apply URP Fog
gridColor = MixFog(gridColor, input.fogFactor);
return half4(gridColor, gridAlpha);
}
ENDHLSL
}
}
FallBack "Hidden/Universal Render Pipeline/FallbackError"
}