Shader "Soullies/RetrowaveSkybox_Mobile" { Properties { [Header(Sky and Horizon)] _SkyColor("Sky Color", Color) = (1, 0.15, 0, 1) _HorizonColor("Horizon Color", Color) = (0.42, 0.10, 0.65, 1) _HorizonStrength("Horizon Strength", Float) = 1.0 _HorizonHeight("Horizon/Sky Height Offset", Range(-1, 1)) = 0.0 [Header(Procedural Sun)] [Toggle(_HAVESUN_ON)] _HaveSun("Have Sun", Float) = 1 _SunSize("Sun Disc Size", Range(0.001, 1)) = 0.05 [HDR]_SunColorOne("Sun Color Top", Color) = (0.95, 0.82, 0.29, 1) [HDR]_SunColorTwo("Sun Color Bottom", Color) = (0.87, 0.39, 0.61, 1) _SunGradStrength("Sun Gradient Strength", Float) = 10 _SunGradHeight("Sun Gradient Height", Range(-1, 5)) = 2 [NoScaleOffset] _SunMask("Sun Mask (Grid Map)", 2D) = "white" {} _SunMaskSize("Sun Mask Size", Range(-5, 1)) = 0 [Header(Fog Equivalent Horizon Blending)] _FogHeight("Fog Height", Range(-10, 10)) = 1.0 _FogPower("Fog Power", Range(0, 5)) = 1.0 _FogContrast("Fog Contrast", Float) = 5.0 [Header(Procedural Stars)] _StarDensity("Star Density", Float) = 150.0 _StarSize("Star Size / Contrast", Range(0, 300)) = 150 [HDR]_StarColor("Star Color", Color) = (0.9, 0.9, 0.9, 1) [Toggle(_PREVENTSTARS_ON)] _PreventStars("Prevent Stars on Sun", Float) = 1 } SubShader { Tags { "RenderType"="Background" "Queue"="Background" "PreviewType"="Skybox" "RenderPipeline" = "UniversalPipeline" } Pass { Name "Skybox" ZWrite Off Cull Off ZTest LEqual HLSLPROGRAM #pragma target 3.5 #pragma prefer_hlslcc gles #pragma vertex vert #pragma fragment frag #pragma shader_feature_local _HAVESUN_ON #pragma shader_feature_local _PREVENTSTARS_ON #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; }; struct Varyings { float4 positionCS : SV_POSITION; float3 viewDirWS : TEXCOORD0; }; CBUFFER_START(UnityPerMaterial) half4 _SkyColor; half4 _HorizonColor; half _HorizonStrength; half _HorizonHeight; half _SunSize; half4 _SunColorOne; half4 _SunColorTwo; half _SunGradStrength; half _SunGradHeight; half _SunMaskSize; half _FogHeight; half _FogPower; half _FogContrast; half _StarDensity; half _StarSize; half4 _StarColor; CBUFFER_END TEXTURE2D(_SunMask); SAMPLER(sampler_SunMask); // [TA Optimize] Fast 3D Hash returning float3 for Star Placement float3 FastHash3D_vec3(float3 p) { p = frac(p * float3(0.1031, 0.1030, 0.0973)); p += dot(p, p.yxz + 33.33); return frac((p.xxy + p.yxx) * p.zyx); } Varyings vert(Attributes input) { Varyings output; // Unity standard skybox space output.positionCS = TransformObjectToHClip(input.positionOS.xyz); output.viewDirWS = input.positionOS.xyz; return output; } half4 frag(Varyings input) : SV_Target { // Must normalize local vertex pos to form spherical ray float3 vDir = normalize(input.viewDirWS); // =================================== // 1. SKY & HORIZON (Restored mapping scale) // =================================== // 恢复使用 asin 以保证与原版天空盒参数的非线性渐变弧度绝对一致 // 半个圆周的 asin 值域映射常数: 1.0 / (PI / 2.0) = 0.63661977 float skyY = asin(clamp(vDir.y, -1.0, 1.0)) * 0.63661977; // 去除此处的 saturate,使得 _HorizonStrength>1 时可以向天空顶部延展色彩 (原版默认行为) float skyMask = skyY * _HorizonStrength + _HorizonHeight; half3 finalColor = lerp(_HorizonColor.rgb, _SkyColor.rgb, skyMask); // =================================== // 2. PROCEDURAL SUN (Zero Acos) // =================================== half3 sunColor = half3(0,0,0); float sunOpacity = 0; #if defined(_HAVESUN_ON) Light mainLight = GetMainLight(); float3 lDir = normalize(mainLight.direction); // [TA Optimize] Replace acos(dot) with raw dot + smoothstep float NdotL = dot(vDir, lDir); // Maps [0.001, 1.0] scale to a reasonable threshold for Dot Product float sunThreshold = lerp(1.0, 0.8, _SunSize); // Anti-aliased disc edge float sunFw = fwidth(NdotL); float sunMask = smoothstep(sunThreshold - sunFw, sunThreshold + sunFw, NdotL); // Vertical Local Gradient float localSunY = saturate(((vDir.y - lDir.y + (1.0 - sunThreshold)) / ((1.0 - sunThreshold) * 2.0)) * _SunGradStrength - _SunGradHeight); half3 rawSunColor = lerp(_SunColorTwo.rgb, _SunColorOne.rgb, localSunY); // [TA Optimize] Planar Projection UV for Sun Mask (Zero Trigo, No Spherical Math) float3 up = abs(lDir.y) > 0.999 ? float3(0,0,1) : float3(0,1,0); // Prevent gimbal lock float3 right = normalize(cross(up, lDir)); float3 sunUp = cross(lDir, right); float2 sunUV = float2(dot(vDir, right), dot(vDir, sunUp)); // 修正点:根据太阳真实的半径跨度进行缩放,映射到完美填充正负1的圆形 float sunRadius = sqrt(max(0.0001, 1.0 - sunThreshold * sunThreshold)); float2 sunUVNorm = sunUV / sunRadius; // 应用暴露出的原生 Mask 控制参数 sunUVNorm = sunUVNorm * (1.0 - _SunMaskSize) * 0.5 + 0.5; half gridMask = SAMPLE_TEXTURE2D(_SunMask, sampler_SunMask, sunUVNorm).r; sunOpacity = gridMask * sunMask; sunColor = rawSunColor * sunOpacity; #endif // =================================== // 3. PROCEDURAL STARS (Single-Tap Cellular Noise) // =================================== half3 starFinal = half3(0,0,0); // [TA Optimize] 用单次计算的 3D Cell Noise 平替 9-Tap Voronoi // 乘以 8 是为了还原老版本在 X轴上乘 8 带来的高密度视觉错觉 float3 scaledPos = vDir * (_StarDensity * 8.0); float3 cell = floor(scaledPos); float3 local = frac(scaledPos); // 获取晶格内随机星星偏移点与亮暗随机种子 float3 randProps = FastHash3D_vec3(cell); // 计算当前像素到该单个星星的距离 float dist = length(local - randProps); // 构造出锐利的星星斑点 (类似 Voronoi 的山峰距离场) float starVal = max(0.0, 1.0 - dist * 1.5); // 1.5 增强锐利度 starVal = pow(starVal, max(1.0, max(75, _StarSize) / 10)); // 随机让 40% 的晶格变空或变亮,使其显得自然参差不齐 float brightness = FastHash3D_vec3(cell + 123.0).x; starVal *= (brightness > 0.4 ? brightness : 0.0); starFinal = starVal * _StarColor.rgb; #if defined(_PREVENTSTARS_ON) starFinal *= (1.0 - sunOpacity); #endif // Add everything up finalColor += starFinal; finalColor += sunColor; // =================================== // 4. GLOBAL FOG BLEND (Restored) // =================================== // 还原原版 Shader Graph 在地平线处覆盖的全局雾气混合机制 float fogVal = saturate(_FogHeight - skyY * _FogContrast) * _FogPower; finalColor = lerp(finalColor, unity_FogColor.rgb, saturate(fogVal)); return half4(finalColor, 1.0); } ENDHLSL } } }