2026-06-06 20:12:40 +07:00
parent de84b2bf48
commit 97ac0f71f5
13682 changed files with 1125938 additions and 0 deletions
@@ -0,0 +1,570 @@
Shader "Synaptic/SkyPro"
{
Properties
{
[Header(Atmosphere)]
_AtmosphereColor ("Atmosphere Color", Color) = (0.4, 0.7, 1.0, 1)
_HorizonColor ("Horizon Color", Color) = (0.8, 0.85, 0.9, 1)
_GroundColor ("Ground Color", Color) = (0.3, 0.3, 0.35, 1)
_AtmosphereThickness ("Atmosphere Thickness", Range(0, 5)) = 1
_MieScattering ("Mie Scattering", Range(0, 1)) = 0.1
_RayleighScattering ("Rayleigh Scattering", Range(0, 2)) = 1
[Header(Sun)]
_SunColor ("Sun Color", Color) = (1, 0.95, 0.8, 1)
_SunSize ("Sun Size", Range(0.001, 0.1)) = 0.02
_SunIntensity ("Sun Intensity", Range(0, 10)) = 5
_SunGlowSize ("Sun Glow Size", Range(0, 1)) = 0.3
_SunGlowIntensity ("Sun Glow Intensity", Range(0, 5)) = 1
[Header(Clouds Volumetric)]
[Toggle(_CLOUDS_ON)] _CloudsEnabled ("Enable Clouds", Float) = 1
_CloudColor ("Cloud Color", Color) = (1, 1, 1, 1)
_CloudShadowColor ("Cloud Shadow Color", Color) = (0.6, 0.65, 0.7, 1)
_CloudDensity ("Cloud Density", Range(0, 2)) = 1
_CloudCoverage ("Cloud Coverage", Range(0, 1)) = 0.5
_CloudHeight ("Cloud Height", Float) = 2000
_CloudThickness ("Cloud Thickness", Float) = 500
_CloudSpeed ("Cloud Speed", Float) = 0.01
_CloudDirection ("Cloud Direction", Vector) = (1, 0, 0, 0)
[Header(Cloud Detail)]
_CloudScale ("Cloud Scale", Float) = 0.0001
_CloudDetailScale ("Detail Scale", Float) = 0.0005
_CloudDetailStrength ("Detail Strength", Range(0, 1)) = 0.5
_CloudEdgeSoftness ("Edge Softness", Range(0, 1)) = 0.3
[Header(Cloud Lighting)]
_CloudAmbient ("Cloud Ambient", Range(0, 1)) = 0.3
_CloudSunPenetration ("Sun Penetration", Range(0, 1)) = 0.3
_CloudSilverLining ("Silver Lining", Range(0, 1)) = 0.5
_CloudSilverLiningSpread ("Silver Spread", Range(0.5, 5)) = 2
[Header(Stars)]
[Toggle(_STARS_ON)] _StarsEnabled ("Enable Stars", Float) = 1
_StarsDensity ("Stars Density", Range(0, 1)) = 0.5
_StarsIntensity ("Stars Intensity", Range(0, 3)) = 1
_StarsTwinkleSpeed ("Twinkle Speed", Float) = 2
[Header(Night Sky)]
_NightColor ("Night Sky Color", Color) = (0.02, 0.02, 0.05, 1)
_NightTransition ("Night Transition", Range(0, 1)) = 0.3
[Header(Performance)]
_CloudSteps ("Cloud Ray Steps", Range(4, 64)) = 16
_CloudLightSteps ("Light Ray Steps", Range(2, 16)) = 4
}
SubShader
{
PackageRequirements { "com.unity.render-pipelines.universal" }
Tags
{
"RenderType" = "Background"
"Queue" = "Background"
"PreviewType" = "Skybox"
"RenderPipeline" = "UniversalPipeline"
}
Pass
{
Name "SkyPro"
Cull Off
ZWrite Off
HLSLPROGRAM
#pragma target 4.5
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature_local _CLOUDS_ON
#pragma shader_feature_local _STARS_ON
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
CBUFFER_START(UnityPerMaterial)
// Atmosphere
float4 _AtmosphereColor;
float4 _HorizonColor;
float4 _GroundColor;
float _AtmosphereThickness;
float _MieScattering;
float _RayleighScattering;
// Sun
float4 _SunColor;
float _SunSize;
float _SunIntensity;
float _SunGlowSize;
float _SunGlowIntensity;
// Clouds
float4 _CloudColor;
float4 _CloudShadowColor;
float _CloudDensity;
float _CloudCoverage;
float _CloudHeight;
float _CloudThickness;
float _CloudSpeed;
float4 _CloudDirection;
float _CloudScale;
float _CloudDetailScale;
float _CloudDetailStrength;
float _CloudEdgeSoftness;
float _CloudAmbient;
float _CloudSunPenetration;
float _CloudSilverLining;
float _CloudSilverLiningSpread;
// Stars
float _StarsDensity;
float _StarsIntensity;
float _StarsTwinkleSpeed;
// Night
float4 _NightColor;
float _NightTransition;
// Performance
float _CloudSteps;
float _CloudLightSteps;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 viewDir : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};
// Noise functions
float Hash(float3 p)
{
p = frac(p * 0.3183099 + 0.1);
p *= 17.0;
return frac(p.x * p.y * p.z * (p.x + p.y + p.z));
}
float Noise3D(float3 p)
{
float3 i = floor(p);
float3 f = frac(p);
f = f * f * (3.0 - 2.0 * f);
return lerp(
lerp(lerp(Hash(i + float3(0, 0, 0)), Hash(i + float3(1, 0, 0)), f.x),
lerp(Hash(i + float3(0, 1, 0)), Hash(i + float3(1, 1, 0)), f.x), f.y),
lerp(lerp(Hash(i + float3(0, 0, 1)), Hash(i + float3(1, 0, 1)), f.x),
lerp(Hash(i + float3(0, 1, 1)), Hash(i + float3(1, 1, 1)), f.x), f.y), f.z
);
}
float FBM(float3 p, int octaves)
{
float value = 0;
float amplitude = 0.5;
float frequency = 1;
for (int i = 0; i < octaves; i++)
{
value += amplitude * Noise3D(p * frequency);
frequency *= 2;
amplitude *= 0.5;
}
return value;
}
// Cloud density at a point
float CloudDensity(float3 p)
{
float time = _Time.y * _CloudSpeed;
float3 windOffset = _CloudDirection.xyz * time;
// Main cloud shape
float mainNoise = FBM((p + windOffset) * _CloudScale, 4);
// Detail noise
float detailNoise = FBM((p + windOffset * 2) * _CloudDetailScale, 3);
mainNoise = lerp(mainNoise, mainNoise * detailNoise, _CloudDetailStrength);
// Coverage threshold
float density = mainNoise - (1 - _CloudCoverage);
density = saturate(density / _CloudEdgeSoftness);
return density * _CloudDensity;
}
// Ray-sphere intersection
float2 RaySphereIntersect(float3 rayOrigin, float3 rayDir, float3 sphereCenter, float sphereRadius)
{
float3 oc = rayOrigin - sphereCenter;
float b = dot(oc, rayDir);
float c = dot(oc, oc) - sphereRadius * sphereRadius;
float h = b * b - c;
if (h < 0) return float2(-1, -1);
h = sqrt(h);
return float2(-b - h, -b + h);
}
// Rayleigh phase function
float RayleighPhase(float cosTheta)
{
return 0.75 * (1.0 + cosTheta * cosTheta);
}
// Mie phase function (Henyey-Greenstein)
float MiePhase(float cosTheta, float g)
{
float g2 = g * g;
return (1 - g2) / (4 * PI * pow(1 + g2 - 2 * g * cosTheta, 1.5));
}
Varyings vert(Attributes IN)
{
Varyings OUT;
OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.viewDir = normalize(TransformObjectToWorld(IN.positionOS.xyz));
OUT.worldPos = TransformObjectToWorld(IN.positionOS.xyz);
return OUT;
}
float4 frag(Varyings IN) : SV_Target
{
float3 viewDir = normalize(IN.viewDir);
// Get sun direction
Light mainLight = GetMainLight();
float3 sunDir = mainLight.direction;
float sunDot = dot(viewDir, sunDir);
// Day/night factor based on sun height
float sunHeight = sunDir.y;
float dayFactor = saturate((sunHeight + _NightTransition) / (2 * _NightTransition));
// ==================== ATMOSPHERE ====================
// Vertical gradient
float upDot = viewDir.y;
float horizonFactor = 1 - abs(upDot);
horizonFactor = pow(horizonFactor, 3);
// Rayleigh scattering (blue sky)
float rayleigh = RayleighPhase(sunDot) * _RayleighScattering;
// Mie scattering (sun glow)
float mie = MiePhase(sunDot, 0.76) * _MieScattering;
// Sky color
float3 skyColor = _AtmosphereColor.rgb * _AtmosphereThickness;
skyColor = lerp(skyColor, _HorizonColor.rgb, horizonFactor);
// Apply scattering
float3 scatterColor = skyColor * rayleigh + _SunColor.rgb * mie;
// Ground color (below horizon)
float groundMask = saturate(-upDot * 10);
scatterColor = lerp(scatterColor, _GroundColor.rgb, groundMask);
// ==================== SUN ====================
float sunMask = saturate((sunDot - (1 - _SunSize)) / _SunSize);
sunMask = pow(sunMask, 0.5);
// Sun glow
float sunGlow = pow(saturate(sunDot), 8 / _SunGlowSize) * _SunGlowIntensity;
float3 sunColor = _SunColor.rgb * _SunIntensity * (sunMask + sunGlow);
// ==================== STARS ====================
float3 starsColor = float3(0, 0, 0);
#if defined(_STARS_ON)
if (dayFactor < 0.8)
{
// Star field
float3 starDir = viewDir * 1000;
float starNoise = Hash(floor(starDir));
if (starNoise > 1 - _StarsDensity * 0.01)
{
float twinkle = sin(_Time.y * _StarsTwinkleSpeed + starNoise * 100) * 0.3 + 0.7;
float starBrightness = pow(starNoise, 20) * _StarsIntensity * twinkle;
starsColor = float3(1, 1, 1) * starBrightness * (1 - dayFactor);
}
}
#endif
// ==================== CLOUDS ====================
float3 cloudColor = float3(0, 0, 0);
float cloudAlpha = 0;
#if defined(_CLOUDS_ON)
// Ray march through cloud layer
float3 rayOrigin = float3(0, 0, 0);
float3 rayDir = viewDir;
// Cloud layer bounds
float cloudBottom = _CloudHeight;
float cloudTop = _CloudHeight + _CloudThickness;
// Calculate entry/exit points
float2 tBottom = RaySphereIntersect(rayOrigin, rayDir, float3(0, -6371000, 0), 6371000 + cloudBottom);
float2 tTop = RaySphereIntersect(rayOrigin, rayDir, float3(0, -6371000, 0), 6371000 + cloudTop);
float tStart = max(tBottom.x, 0);
float tEnd = tTop.x > 0 ? tTop.x : tTop.y;
if (tEnd > tStart && viewDir.y > -0.1)
{
float stepSize = (tEnd - tStart) / _CloudSteps;
float transmittance = 1;
float3 lightEnergy = float3(0, 0, 0);
for (int i = 0; i < (int)_CloudSteps; i++)
{
float t = tStart + (i + 0.5) * stepSize;
float3 samplePos = rayOrigin + rayDir * t;
float density = CloudDensity(samplePos);
if (density > 0.001)
{
// Light march toward sun
float lightTransmittance = 1;
float lightStepSize = _CloudThickness / _CloudLightSteps;
for (int j = 0; j < (int)_CloudLightSteps; j++)
{
float3 lightSamplePos = samplePos + sunDir * (j + 0.5) * lightStepSize;
float lightDensity = CloudDensity(lightSamplePos);
lightTransmittance *= exp(-lightDensity * lightStepSize * 0.01);
}
// Beer's law
float extinctionCoeff = density * stepSize * 0.01;
float sampleTransmittance = exp(-extinctionCoeff);
// Lighting
float3 ambient = _CloudColor.rgb * _CloudAmbient;
float3 directLight = _SunColor.rgb * lightTransmittance * _CloudSunPenetration;
// Silver lining (forward scattering)
float silverLining = pow(saturate(sunDot), _CloudSilverLiningSpread) * _CloudSilverLining;
directLight += _SunColor.rgb * silverLining * lightTransmittance;
// Shadow color blend
float3 cloudSample = lerp(_CloudShadowColor.rgb, _CloudColor.rgb, lightTransmittance);
cloudSample *= (ambient + directLight);
lightEnergy += cloudSample * transmittance * (1 - sampleTransmittance);
transmittance *= sampleTransmittance;
if (transmittance < 0.01) break;
}
}
cloudColor = lightEnergy;
cloudAlpha = 1 - transmittance;
}
#endif
// ==================== COMBINE ====================
// Night sky
float3 nightSky = lerp(_NightColor.rgb, scatterColor, dayFactor);
nightSky += starsColor;
// Add sun
float3 finalColor = nightSky + sunColor * dayFactor;
// Blend clouds
finalColor = lerp(finalColor, cloudColor, cloudAlpha);
// Tone mapping (simple Reinhard)
finalColor = finalColor / (finalColor + 1);
return float4(finalColor, 1);
}
ENDHLSL
}
}
// ==================== Built-in Pipeline SubShader ====================
SubShader
{
Tags
{
"RenderType" = "Background"
"Queue" = "Background"
"PreviewType" = "Skybox"
}
Pass
{
Name "SkyProBuiltIn"
Cull Off
ZWrite Off
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#pragma shader_feature_local _CLOUDS_ON
#pragma shader_feature_local _STARS_ON
#include "UnityCG.cginc"
#include "Lighting.cginc"
float4 _AtmosphereColor;
float4 _HorizonColor;
float4 _GroundColor;
float _AtmosphereThickness;
float4 _SunColor;
float _SunSize;
float _SunIntensity;
float _SunGlowSize;
float _SunGlowIntensity;
float4 _NightColor;
float _NightTransition;
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 viewDir : TEXCOORD0;
};
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.viewDir = normalize(mul((float3x3)unity_ObjectToWorld, v.vertex.xyz));
return o;
}
float4 frag(v2f i) : SV_Target
{
float3 viewDir = normalize(i.viewDir);
float3 sunDir = normalize(_WorldSpaceLightPos0.xyz);
float sunDot = dot(viewDir, sunDir);
float sunHeight = sunDir.y;
float dayFactor = saturate((sunHeight + _NightTransition) / (2 * _NightTransition));
float upDot = viewDir.y;
float horizonFactor = 1 - abs(upDot);
horizonFactor = pow(horizonFactor, 3);
float3 skyColor = _AtmosphereColor.rgb * _AtmosphereThickness;
skyColor = lerp(skyColor, _HorizonColor.rgb, horizonFactor);
float groundMask = saturate(-upDot * 10);
skyColor = lerp(skyColor, _GroundColor.rgb, groundMask);
float sunMask = saturate((sunDot - (1 - _SunSize)) / _SunSize);
sunMask = pow(sunMask, 0.5);
float sunGlow = pow(saturate(sunDot), 8 / _SunGlowSize) * _SunGlowIntensity;
float3 sunColor = _SunColor.rgb * _SunIntensity * (sunMask + sunGlow);
float3 nightSky = lerp(_NightColor.rgb, skyColor, dayFactor);
float3 finalColor = nightSky + sunColor * dayFactor;
finalColor = finalColor / (finalColor + 1);
return float4(finalColor, 1);
}
ENDCG
}
}
// ==================== HDRP SubShader ====================
SubShader
{
PackageRequirements { "com.unity.render-pipelines.high-definition" }
Tags
{
"RenderType" = "Background"
"Queue" = "Background"
"PreviewType" = "Skybox"
"RenderPipeline" = "HDRenderPipeline"
}
Pass
{
Name "SkyProHDRP"
Cull Off
ZWrite Off
HLSLPROGRAM
#pragma target 4.5
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
CBUFFER_START(UnityPerMaterial)
float4 _AtmosphereColor;
float4 _HorizonColor;
float4 _GroundColor;
float _AtmosphereThickness;
float4 _SunColor;
float _SunSize;
float _SunIntensity;
float _SunGlowSize;
float _SunGlowIntensity;
float4 _NightColor;
float _NightTransition;
CBUFFER_END
struct Attributes { float4 positionOS : POSITION; };
struct Varyings { float4 positionCS : SV_POSITION; float3 viewDir : TEXCOORD0; };
Varyings vert(Attributes IN)
{
Varyings OUT;
OUT.positionCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.viewDir = normalize(TransformObjectToWorld(IN.positionOS.xyz));
return OUT;
}
float4 frag(Varyings IN) : SV_Target
{
float3 viewDir = normalize(IN.viewDir);
float3 sunDir = float3(0.3, 0.8, 0.5);
float sunDot = dot(viewDir, sunDir);
float dayFactor = saturate((sunDir.y + _NightTransition) / (2 * _NightTransition));
float upDot = viewDir.y;
float horizonFactor = pow(1 - abs(upDot), 3);
float3 skyColor = lerp(_AtmosphereColor.rgb * _AtmosphereThickness, _HorizonColor.rgb, horizonFactor);
skyColor = lerp(skyColor, _GroundColor.rgb, saturate(-upDot * 10));
float sunMask = pow(saturate((sunDot - (1 - _SunSize)) / _SunSize), 0.5);
float sunGlow = pow(saturate(sunDot), 8 / _SunGlowSize) * _SunGlowIntensity;
float3 sunColor = _SunColor.rgb * _SunIntensity * (sunMask + sunGlow);
float3 finalColor = lerp(_NightColor.rgb, skyColor, dayFactor) + sunColor * dayFactor;
return float4(finalColor / (finalColor + 1), 1);
}
ENDHLSL
}
}
FallBack Off
}