221 lines
9.2 KiB
Plaintext
221 lines
9.2 KiB
Plaintext
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
|
||
}
|
||
}
|
||
}
|