97ac0f71f5
https://assetstore.unity.com/packages/tools/generative-ai/synaptic-ai-pro-natural-language-control-for-unity-336030
571 lines
21 KiB
GLSL
571 lines
21 KiB
GLSL
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
|
|
}
|