fix:代码提初始化
This commit is contained in:
@@ -0,0 +1,883 @@
|
||||
#ifndef PI
|
||||
#define PI 3.14159265
|
||||
#endif
|
||||
|
||||
#ifndef TWO_PI
|
||||
#define TWO_PI 6.28318530
|
||||
#endif
|
||||
|
||||
#ifndef INV_PI
|
||||
#define INV_PI 0.31830989
|
||||
#endif
|
||||
|
||||
uniform Texture3D _Noise;
|
||||
SamplerState sampler_Noise;
|
||||
uniform Texture3D _DetailNoise;
|
||||
SamplerState sampler_DetailNoise;
|
||||
uniform Texture2D _WeatherMap;
|
||||
SamplerState sampler_WeatherMap;
|
||||
uniform Texture2D _CurlNoise;
|
||||
SamplerState sampler_CurlNoise;
|
||||
|
||||
uniform sampler2D _BottomsOffsetNoise;
|
||||
uniform sampler2D _BlueNoise;
|
||||
|
||||
float4 _BlueNoise_TexelSize;
|
||||
float3 _WorldOffset;
|
||||
|
||||
uniform float4x4 _InverseProjection;
|
||||
uniform float4x4 _InverseRotation;
|
||||
uniform float4x4 _InverseProjectionRight;
|
||||
uniform float4x4 _InverseRotationRight;
|
||||
|
||||
float4x4 _LeftWorldFromView;
|
||||
float4x4 _RightWorldFromView;
|
||||
float4x4 _LeftViewFromScreen;
|
||||
float4x4 _RightViewFromScreen;
|
||||
|
||||
uniform float4 _CloudsParameter;
|
||||
uniform float4 _CloudsParameter2;
|
||||
|
||||
uniform float4 _Steps;
|
||||
uniform float4 _CloudsLighting;
|
||||
uniform float4 _CloudsLighting2;
|
||||
uniform float4 _CloudsLightingExtended;
|
||||
uniform float4 _CloudsLightingExtended2;
|
||||
|
||||
uniform float4 _CloudsMultiScattering;
|
||||
uniform float4 _CloudsMultiScattering2;
|
||||
|
||||
uniform float4 _CloudsErosionIntensity; //x = Base, y = Detail
|
||||
uniform float4 _CloudsNoiseSettings; //x = Base, y = Detail
|
||||
|
||||
uniform float4 _CloudsShape1;
|
||||
uniform float4 _CloudsShape2;
|
||||
|
||||
uniform float4 _CloudDensityScale;
|
||||
uniform float4 _CloudsCoverageSettings; //x = _GlobalCoverage, y = Bottom Coverage Mod, z = Top coverage mod, w = Clouds Up Morph Intensity
|
||||
uniform float _GlobalCoverage;
|
||||
uniform float4 _CloudsAnimation;
|
||||
uniform float4 _CloudsWindDirection;
|
||||
|
||||
uniform float3 _LightDir;
|
||||
uniform float _stepsInDepth;
|
||||
uniform float _LODDistance;
|
||||
uniform float3 _CameraPosition;
|
||||
uniform float4 _Resolution;
|
||||
uniform float4 _Randomness;
|
||||
uniform float _EnviroDepthTest;
|
||||
uniform float _SolarTime;
|
||||
////
|
||||
const float env_inf = 1e10;
|
||||
|
||||
struct RaymarchParameters
|
||||
{
|
||||
//Lighting
|
||||
float scatteringCoef;
|
||||
float silverLiningIntensity;
|
||||
float silverLiningSpread;
|
||||
float edgeHighlightStrength;
|
||||
float directIndirectBalance;
|
||||
float exposure;
|
||||
float attenuation;
|
||||
float lightStep;
|
||||
float lightAbsorb;
|
||||
float multiScatterStrength;
|
||||
float multiScatterFalloff;
|
||||
float ambientFloor;
|
||||
|
||||
//Height
|
||||
float4 cloudsParameter;
|
||||
|
||||
//Density
|
||||
float density;
|
||||
float densitySmoothness;
|
||||
|
||||
//Erosion
|
||||
float baseErosion;
|
||||
float detailErosion;
|
||||
|
||||
int minSteps, maxSteps;
|
||||
|
||||
float baseNoiseUV;
|
||||
float detailNoiseUV;
|
||||
|
||||
float baseErosionIntensity;
|
||||
float detailErosionIntensity;
|
||||
|
||||
float baseNoiseMultiplier;
|
||||
float detailNoiseMultiplier;
|
||||
|
||||
float bottomShape;
|
||||
float midShape;
|
||||
float topShape;
|
||||
float topLayer;
|
||||
float rampShape;
|
||||
float cloudTypeShaping;
|
||||
};
|
||||
|
||||
void InitRaymarchParameters(inout RaymarchParameters parameters)
|
||||
{
|
||||
parameters.scatteringCoef = _CloudsLighting.x;
|
||||
parameters.silverLiningIntensity = _CloudsLighting.y;
|
||||
parameters.silverLiningSpread = _CloudsLighting.w;
|
||||
|
||||
parameters.multiScatterStrength = _CloudsMultiScattering.x;
|
||||
parameters.multiScatterFalloff = _CloudsMultiScattering.y;
|
||||
parameters.ambientFloor = _CloudsMultiScattering.z;
|
||||
parameters.exposure = _CloudsMultiScattering.w;
|
||||
|
||||
parameters.directIndirectBalance = _CloudsLightingExtended.x;
|
||||
parameters.attenuation = _CloudsLightingExtended.y;
|
||||
parameters.lightStep = _CloudsLightingExtended.z;
|
||||
parameters.lightAbsorb = _CloudsLightingExtended.w;
|
||||
|
||||
parameters.edgeHighlightStrength = _CloudsLighting.z;
|
||||
|
||||
parameters.cloudsParameter = _CloudsParameter;
|
||||
|
||||
parameters.density = _CloudDensityScale.x;
|
||||
parameters.densitySmoothness = _CloudDensityScale.z;
|
||||
|
||||
parameters.baseErosion = _CloudsErosionIntensity.x;
|
||||
parameters.detailErosion = _CloudsErosionIntensity.y;
|
||||
|
||||
parameters.baseNoiseMultiplier = _CloudsNoiseSettings.z;
|
||||
parameters.detailNoiseMultiplier = _CloudsNoiseSettings.w;
|
||||
|
||||
parameters.minSteps = _Steps.x;
|
||||
parameters.maxSteps = _Steps.y;
|
||||
|
||||
parameters.baseNoiseUV = _CloudsNoiseSettings.x;
|
||||
parameters.detailNoiseUV = _CloudsNoiseSettings.y;
|
||||
|
||||
parameters.baseErosionIntensity = _CloudsErosionIntensity.x;
|
||||
parameters.detailErosionIntensity = _CloudsErosionIntensity.y;
|
||||
|
||||
parameters.bottomShape = _CloudsShape1.x;
|
||||
parameters.midShape = _CloudsShape1.y;
|
||||
parameters.topShape = _CloudsShape1.z;
|
||||
parameters.topLayer = _CloudsShape1.w;
|
||||
|
||||
parameters.rampShape = _CloudsCoverageSettings.w;
|
||||
|
||||
parameters.cloudTypeShaping = _CloudsCoverageSettings.z;
|
||||
}
|
||||
|
||||
float HenryGreensteinNorm(float cosTheta, float g)
|
||||
{
|
||||
float g2 = g * g;
|
||||
return (1.0 - g2) / (4.0 * PI * pow(1.0 + g2 - 2.0 * g * cosTheta, 1.5));
|
||||
}
|
||||
|
||||
float RemapEnviro(float org_val, float org_min, float org_max, float new_min, float new_max)
|
||||
{
|
||||
return new_min + saturate(((org_val - org_min) / (org_max - org_min))*(new_max - new_min));
|
||||
}
|
||||
|
||||
float4 GetWeather(float3 pos)
|
||||
{
|
||||
float2 uv = pos.xz * 0.0000025;
|
||||
return _WeatherMap.SampleLevel(sampler_WeatherMap,uv, 0);
|
||||
}
|
||||
|
||||
float GetSamplingHeight(float3 pos, float3 center, float4 parameters)
|
||||
{
|
||||
return (length(pos - center) - (parameters.w + parameters.x)) * parameters.z;
|
||||
}
|
||||
|
||||
float3 ScreenSpaceDither(float2 vScreenPos, float lum)
|
||||
{
|
||||
float d = dot(float2(131.0, 312.0), vScreenPos.xy); //+ _Time TODO
|
||||
float3 vDither = float3(d, d, d);
|
||||
vDither.rgb = frac(vDither.rgb / float3(103.0, 71.0, 97.0)) - float3(0.5, 0.5, 0.5);
|
||||
return (vDither.rgb / 15.0) * 1.0 * lum;
|
||||
}
|
||||
|
||||
float GetRaymarchEndFromSceneDepth(float sceneDepth, float maxRange)
|
||||
{
|
||||
float raymarchEnd = 0.0f;
|
||||
#if ENVIRO_DEPTH_BLENDING
|
||||
if (sceneDepth >= 0.99f)
|
||||
{
|
||||
raymarchEnd = maxRange;
|
||||
}
|
||||
else
|
||||
{
|
||||
raymarchEnd = sceneDepth * _ProjectionParams.z;
|
||||
}
|
||||
#else
|
||||
if(_EnviroDepthTest > 0 )
|
||||
{
|
||||
if (sceneDepth >= 0.99f)
|
||||
{
|
||||
raymarchEnd = maxRange;
|
||||
}
|
||||
else
|
||||
{
|
||||
raymarchEnd = sceneDepth * _ProjectionParams.z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
raymarchEnd = maxRange;
|
||||
}
|
||||
#endif
|
||||
return raymarchEnd;
|
||||
}
|
||||
|
||||
float4 GetHeightGradient(float cloudType)
|
||||
{
|
||||
// x,y = bottom smoothstep, z,w = top smoothstep
|
||||
const float4 CloudGradient1 = float4(0.0, 0.07, 0.08, 0.15); // Strato
|
||||
const float4 CloudGradient2 = float4(0.0, 0.20, 0.42, 0.60); // Cumulus
|
||||
const float4 CloudGradient3 = float4(0.0, 0.08, 0.75, 0.98); // Nimbus
|
||||
|
||||
float a = 1.0 - saturate(cloudType * 2.0); // 0→0.5 strato
|
||||
float b = 1.0 - abs(cloudType - 0.5) * 2.0; // around 0.5 cumulus
|
||||
float c = saturate(cloudType - 0.5) * 2.0; // 0.5→1 nimbus
|
||||
|
||||
return CloudGradient1 * a + CloudGradient2 * b + CloudGradient3 * c;
|
||||
}
|
||||
|
||||
float GradientStep(float a, float4 g)
|
||||
{
|
||||
return smoothstep(g.x, g.y, a) - smoothstep(g.z, g.w, a);
|
||||
}
|
||||
|
||||
// ---------- Final profile with varying bottom ----------
|
||||
float CloudTypeShaping(float3 worldPos, float cloudType, RaymarchParameters p)
|
||||
{
|
||||
float _BottomVariation = 1000; // e.g. 500.0 m of random variation
|
||||
float _NoiseScale = 0.000025; // e.g. 0.001 for slow world-scale noise
|
||||
|
||||
// noise-based base variation
|
||||
float baseOffset = 0;
|
||||
#if ENVIRO_VARIABLE_BOTTOM
|
||||
baseOffset = tex2Dlod(_BottomsOffsetNoise, float4(worldPos.xz * _NoiseScale,0,0)).r * _BottomVariation;
|
||||
#endif
|
||||
float bottom = p.cloudsParameter.x + baseOffset;
|
||||
float top = bottom + (p.cloudsParameter.y - p.cloudsParameter.x);
|
||||
|
||||
// normalized height
|
||||
float h = saturate((worldPos.y - bottom) / (top - bottom));
|
||||
|
||||
// choose gradient band based on type
|
||||
float4 gradient = GetHeightGradient(cloudType);
|
||||
|
||||
// final vertical profile
|
||||
return GradientStep(h, gradient);
|
||||
}
|
||||
|
||||
|
||||
float CloudVerticalShaping(float heightNorm,
|
||||
float bottomCtrl,
|
||||
float midCtrl,
|
||||
float topCtrl,
|
||||
float ramp)
|
||||
{
|
||||
// --- Define segments ---
|
||||
float2 bottomRange = float2(-0.1, 0.25);
|
||||
float2 midRange = float2(0.20, 0.45);
|
||||
float2 topRange = float2(0.40, 0.8); // top segment fades before 1.0
|
||||
|
||||
// --- Compute smooth ramps ---
|
||||
float bottom = smoothstep(bottomRange.x, bottomRange.y, heightNorm) *
|
||||
(1.0 - smoothstep(bottomRange.x + ramp, bottomRange.y + ramp, heightNorm));
|
||||
|
||||
float mid = smoothstep(midRange.x, midRange.y, heightNorm) *
|
||||
(1.0 - smoothstep(midRange.x + ramp, midRange.y + ramp, heightNorm));
|
||||
|
||||
float top = smoothstep(topRange.x, topRange.y, heightNorm) *
|
||||
(1.0 - smoothstep(topRange.x + ramp, topRange.y + ramp, heightNorm));
|
||||
|
||||
// --- Fade top influence out at absolute top ---
|
||||
//top *= 1.0 - smoothstep(0.95, 1.0, heightNorm);
|
||||
|
||||
// --- Normalize weights so controls are balanced ---
|
||||
float sum = bottom + mid + top + 1e-5;
|
||||
bottom /= sum;
|
||||
mid /= sum;
|
||||
top /= sum;
|
||||
|
||||
// --- Apply coverage controls ---
|
||||
float bias = bottomCtrl * bottom + midCtrl * mid + topCtrl * top;
|
||||
|
||||
// --- Map to envelope multiplier ---
|
||||
// center at 1.0 = no change, limit to avoid full fill
|
||||
float envelope = 1.0 + bias * 0.5; // adjust scale as needed
|
||||
//envelope = envelope;
|
||||
|
||||
//Bottom Round
|
||||
float edgeRound = 1.0 - exp(-heightNorm * 8.0);
|
||||
envelope *= lerp(1.0, edgeRound, 0.9 * bottom);
|
||||
|
||||
|
||||
|
||||
// --- Subtle round-top modifier ---
|
||||
float edgeRoundTop = 1.0 - exp(-(1.0 - heightNorm) * 8.0); // only affects highest ~0.8–1.0
|
||||
envelope *= lerp(1.0, edgeRoundTop, 1.5 * top);
|
||||
|
||||
if(heightNorm > 0.90)
|
||||
envelope = 0;
|
||||
|
||||
return envelope;
|
||||
}
|
||||
|
||||
float CloudTopLayer(float heightNorm, float baseNoise, float topLayerAdd)
|
||||
{
|
||||
const float topMin = 0.90;
|
||||
const float topMax = 0.94;
|
||||
float verticalFalloff = smoothstep(topMin, topMax, heightNorm) - smoothstep(topMax, 1.0, heightNorm);
|
||||
|
||||
float coverage = baseNoise;
|
||||
return verticalFalloff * coverage * topLayerAdd;
|
||||
}
|
||||
|
||||
// Sample Cloud Density
|
||||
float CalculateCloudDensity(float3 pos, float3 PlanetCenter, RaymarchParameters parameters, float4 weather, float mip, float lod, bool details)
|
||||
{
|
||||
const float baseFreq = 1e-5;
|
||||
|
||||
// Get Height fraction
|
||||
float height = GetSamplingHeight(pos, PlanetCenter, parameters.cloudsParameter);
|
||||
|
||||
// wind settings
|
||||
float cloud_top_offset = 2000.0;
|
||||
float3 wind_direction = float3(_CloudsWindDirection.x, 0.0, _CloudsWindDirection.y);
|
||||
|
||||
// skew in wind direction
|
||||
pos += height * wind_direction * cloud_top_offset;
|
||||
|
||||
float mip1 = mip + lod;
|
||||
float4 coord = float4(pos * baseFreq * parameters.baseNoiseUV, mip1);
|
||||
|
||||
// Animate Wind
|
||||
coord.xyz += float3(_CloudsWindDirection.z, 0.0f, _CloudsWindDirection.w) * 14;
|
||||
|
||||
float4 baseNoise = _Noise.SampleLevel(sampler_Noise, coord.xyz,coord.w) * parameters.baseNoiseMultiplier;
|
||||
float low_freq_fBm = (baseNoise.g * 0.625) + (baseNoise.b * 0.25) + (baseNoise.a * 0.125);
|
||||
float base_cloud = RemapEnviro(baseNoise.r, -(1.0 - low_freq_fBm) * (parameters.baseErosionIntensity), 1.0, 0.0, 1.0) ;
|
||||
|
||||
float targetShape = CloudVerticalShaping(height,parameters.bottomShape,parameters.midShape,parameters.topShape,parameters.rampShape);
|
||||
float heightGradient = CloudTypeShaping(pos,saturate(weather.g + 0.1), parameters);
|
||||
float shapedCloud = base_cloud * targetShape;
|
||||
|
||||
shapedCloud *= lerp(1.0, heightGradient, parameters.cloudTypeShaping);
|
||||
shapedCloud += CloudTopLayer(height, base_cloud, parameters.topLayer);
|
||||
|
||||
|
||||
float cloud_coverage = saturate(1-weather.r);
|
||||
|
||||
if(height > 0.90)
|
||||
cloud_coverage = saturate(1-weather.b);
|
||||
|
||||
float cloudDensity = RemapEnviro(shapedCloud, cloud_coverage, 1.0, 0.0, 1.0);
|
||||
|
||||
//DETAIL
|
||||
[branch]
|
||||
if (details)
|
||||
{
|
||||
float mip2 = mip + lod;
|
||||
coord = float4(pos * baseFreq * parameters.detailNoiseUV, mip2);
|
||||
|
||||
//Curl
|
||||
float distToCam = distance(pos, _WorldSpaceCameraPos);
|
||||
float curlFade = saturate(1.0 - distToCam / 20000.0f);
|
||||
|
||||
float2 curlA = _CurlNoise.SampleLevel(sampler_CurlNoise, coord.xz * 2, 0).rg * 2 - 1;
|
||||
float2 curlB = _CurlNoise.SampleLevel(sampler_CurlNoise, coord.xy * 3, 0).rg * 2 - 1;
|
||||
float2 curl = lerp(curlA, curlB, 0.5);
|
||||
|
||||
float curlAmp = 0.5 * parameters.attenuation * curlFade;
|
||||
curl *= curlAmp * saturate(height * 2);
|
||||
|
||||
coord.xy += curl;
|
||||
coord.xz += curl * 0.5;
|
||||
|
||||
coord.xyz += float3(_CloudsWindDirection.z * 14, _CloudsAnimation.z, _CloudsWindDirection.w * 14);
|
||||
|
||||
float3 detailNoise = _DetailNoise.SampleLevel(sampler_DetailNoise, coord.xyz, coord.w).rgb * parameters.detailNoiseMultiplier;
|
||||
float high_freq_fBm = (detailNoise.r * 0.625) + (detailNoise.g * 0.25) + (detailNoise.b * 0.125);
|
||||
float high_freq_noise_modifier = lerp(high_freq_fBm, 1.0f - high_freq_fBm, saturate(height * 8));
|
||||
cloudDensity = RemapEnviro(cloudDensity, saturate(high_freq_noise_modifier * parameters.detailErosionIntensity), 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
if(height > 0.9)
|
||||
cloudDensity *= 0.2;
|
||||
|
||||
return cloudDensity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const float shadowSampleDistance[5] = {0.5, 2, 8, 12, 32};
|
||||
static const float LightingInfluence[5] = {5, 4, 3, 2, 1};
|
||||
|
||||
float GetDensityAlongRay(float3 pos,float3 PlanetCenter,RaymarchParameters parameters,float3 LightDirection,float4 weather,float lod)
|
||||
{
|
||||
float mipBiasScale = 0.1;
|
||||
float opticalDepth = 0.0;
|
||||
float mipOffset = 0.0;
|
||||
float distanceTraveled = 0.0;
|
||||
|
||||
[loop]
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
// Base step size from shadowSampleDistance
|
||||
float baseStep = shadowSampleDistance[i] * (512.0 * _CloudsLightingExtended.z);
|
||||
|
||||
distanceTraveled += baseStep;
|
||||
|
||||
// Sample cloud density
|
||||
float3 samplePos = pos + LightDirection * distanceTraveled;
|
||||
float density = 0;
|
||||
if(i < 4)
|
||||
density = CalculateCloudDensity(samplePos, PlanetCenter, parameters, weather, mipOffset, lod, true) * 0.75;
|
||||
else
|
||||
density = CalculateCloudDensity(samplePos, PlanetCenter, parameters, weather, mipOffset, lod, false) * 0.75;
|
||||
|
||||
|
||||
|
||||
opticalDepth += LightingInfluence[i] * density * baseStep;
|
||||
|
||||
// Update mip offset proportionally
|
||||
mipOffset += saturate(baseStep * mipBiasScale);
|
||||
}
|
||||
|
||||
return opticalDepth;
|
||||
}
|
||||
|
||||
|
||||
float3 _LightningCenter;
|
||||
float _LightningRadius;
|
||||
float _LightningStart;
|
||||
float _LightningDuration;
|
||||
float _GlobalTime;
|
||||
|
||||
float LightningIntensity(float t)
|
||||
{
|
||||
if (t < 0 || t > _LightningDuration) return 0;
|
||||
|
||||
// ---- Parameters ----
|
||||
float flickerStrength = 0.25; // 0..1 amplitude of flicker
|
||||
float flickerCycles = 3; // number of flickers across duration
|
||||
float endBoost = 2; // 1 = none, 2 = double brightness at end
|
||||
|
||||
// ---- Duration-based scaling ----
|
||||
float riseRate = 1.0 / max(0.15 * _LightningDuration, 0.001);
|
||||
float decayRate = 1.0 / max(_LightningDuration, 0.001);
|
||||
|
||||
float rise = saturate(t * riseRate);
|
||||
float decay = exp(-t * decayRate * _LightningDuration);
|
||||
float envelope = rise * decay;
|
||||
|
||||
// ---- Flicker ----
|
||||
float flickerFreq = flickerCycles / max(_LightningDuration, 0.001);
|
||||
float flicker = 1.0 + flickerStrength * sin(t * flickerFreq * 6.2831853);
|
||||
|
||||
// ---- Late-time boost ----
|
||||
// Progress through flash (0 → 1)
|
||||
float progress = saturate(t / _LightningDuration);
|
||||
// Stronger near the end (ease-in curve)
|
||||
float lateBoost = 1.0 + (endBoost - 1.0) * pow(progress, 3.0);
|
||||
|
||||
return envelope * flicker * lateBoost;
|
||||
}
|
||||
|
||||
|
||||
float SampleEnergy(
|
||||
float3 pos, float cosTheta, float3 center,
|
||||
RaymarchParameters p, float3 LightDirection,
|
||||
float height, float ds_lod, float step_size,
|
||||
float4 weather, float lod, float gradApprox)
|
||||
{
|
||||
//--------------------------------
|
||||
// 1. Optical depth along light
|
||||
//--------------------------------
|
||||
float tau = GetDensityAlongRay(pos, center, p, LightDirection, weather, lod);
|
||||
float sigma_t = max(p.lightAbsorb, 0.0005);
|
||||
float opticalD = sigma_t * tau;
|
||||
|
||||
//--------------------------------
|
||||
// 2. Direct scattering (HG + edge highlight coupled)
|
||||
//--------------------------------
|
||||
float T = exp(-opticalD);
|
||||
float g = 0.85 - p.silverLiningSpread;
|
||||
float hgForward = HenryGreensteinNorm(cosTheta, g);
|
||||
float hgIso = 0.25 * INV_PI * p.edgeHighlightStrength;
|
||||
float phase = hgIso + hgForward;
|
||||
float direct = T * phase * p.scatteringCoef * 20.0 * max(_SolarTime,0.25) * p.silverLiningIntensity;
|
||||
|
||||
//--------------------------------
|
||||
// 3. Multi-scattering (indirect)
|
||||
//--------------------------------
|
||||
float msEnergy = p.multiScatterStrength * (1.0 - T) * exp(-opticalD * p.multiScatterFalloff);
|
||||
float phaseMS = 0.25 * INV_PI;
|
||||
float indirect = msEnergy * phaseMS * p.scatteringCoef * 20.0;
|
||||
|
||||
//--------------------------------
|
||||
// 3a Distance Clouds Tweaks
|
||||
//--------------------------------
|
||||
float distToCam = length(pos - _WorldSpaceCameraPos);
|
||||
float distFactor = saturate(distToCam / 7000);
|
||||
|
||||
// Push balance toward indirect at distance
|
||||
float indirectBoost = lerp(1.0, 1.5, distFactor); // 1.0 near, 1.5 far
|
||||
float directFade = lerp(1.0, 0.7, distFactor); // keep direct a bit weaker far
|
||||
|
||||
direct *= directFade;
|
||||
indirect *= indirectBoost;
|
||||
|
||||
//--------------------------------
|
||||
// 4. Ambient floor
|
||||
//--------------------------------
|
||||
float ambientFloor = p.ambientFloor * (1.0 - exp(-opticalD * 0.1));
|
||||
|
||||
//--------------------------------
|
||||
// 5. Lightning
|
||||
//--------------------------------
|
||||
float lightning = 0.0;
|
||||
#if ENVIRO_LIGHTNING
|
||||
float dist = length(pos - _LightningCenter);
|
||||
float softness = 0.5;
|
||||
float falloff = exp(-pow(dist / _LightningRadius, 2.0) * softness);
|
||||
float flash = LightningIntensity(_Time.y - _LightningStart);
|
||||
float densityAtten = exp(-tau * 0.004);
|
||||
lightning = flash * falloff * densityAtten * 100.0 * (10 * saturate(1 - _SolarTime));
|
||||
#endif
|
||||
|
||||
//--------------------------------
|
||||
// 6. Combine total energy
|
||||
//--------------------------------
|
||||
float energy = direct + indirect + ambientFloor + lightning;
|
||||
|
||||
return max(energy * p.exposure, 0.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
float2 squareUV(float2 uv)
|
||||
{
|
||||
float width = _Resolution.x;
|
||||
float height = _Resolution.y;
|
||||
float scale = 400;
|
||||
float x = uv.x * width;
|
||||
float y = uv.y * height;
|
||||
return float2 (x/scale, y/scale);
|
||||
}
|
||||
|
||||
|
||||
bool ray_trace_sphere(float3 center, float3 rd, float3 offset, float radius, out float t1, out float t2) {
|
||||
float3 p = center - offset;
|
||||
float b = dot(p, rd);
|
||||
float c = dot(p, p) - (radius * radius);
|
||||
|
||||
float f = b * b - c;
|
||||
if (f >= 0.0) {
|
||||
float dem = sqrt(f);
|
||||
t1 = -b - dem;
|
||||
t2 = -b + dem;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool resolve_ray_start_end(float3 ws_origin, float3 ws_ray, float3 center, RaymarchParameters parameter, out float start, out float end)
|
||||
{
|
||||
start = 0;
|
||||
end = 0;
|
||||
//case includes on ground, inside atm, above atm.
|
||||
float ot1, ot2, it1, it2;
|
||||
bool outIntersected = ray_trace_sphere(ws_origin, ws_ray, center, parameter.cloudsParameter.w + parameter.cloudsParameter.y, ot1, ot2);
|
||||
if (!outIntersected || ot2 < 0.0f)
|
||||
return false; //you see nothing.
|
||||
|
||||
bool inIntersected = ray_trace_sphere(ws_origin, ws_ray, center, parameter.cloudsParameter.w + parameter.cloudsParameter.x, it1, it2);
|
||||
|
||||
if (inIntersected)
|
||||
{
|
||||
if (it1 * it2 < 0)
|
||||
{
|
||||
//we're on ground.
|
||||
start = max(it2, 0);
|
||||
end = ot2;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = 0.0f;
|
||||
//we're inside atm, or above atm.
|
||||
if (ot1 * ot2 < 0.0)
|
||||
{
|
||||
//Inside atm.
|
||||
if (it2 > 0.0)
|
||||
{
|
||||
//Look down.
|
||||
end = it1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Look up.
|
||||
end = ot2;
|
||||
}
|
||||
|
||||
start = 0.0f;
|
||||
}
|
||||
else
|
||||
{ //Outside atm
|
||||
if (ot1 < 0.0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
start = ot1;
|
||||
end = it1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
end = ot2;
|
||||
start = max(ot1, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int inside = 0;
|
||||
|
||||
float2 ResolveRay(float3 pos, float3 ray, float3 center, float raymarchEnd, RaymarchParameters parameter)
|
||||
{
|
||||
float sampleStart = 0;
|
||||
float sampleEnd = 0;
|
||||
|
||||
if (!resolve_ray_start_end(pos, ray,center, parameter, sampleStart, sampleEnd))
|
||||
{
|
||||
return float2(0,0);
|
||||
}
|
||||
|
||||
float3 sampleStartPos = pos + (ray * sampleStart);
|
||||
if (sampleEnd <= sampleStart)
|
||||
{
|
||||
return float2(0,0);
|
||||
}
|
||||
|
||||
float ch = length(pos - center) - parameter.cloudsParameter.w;
|
||||
//float height = RemapEnviro(pos.y, parameter.cloudsParameter.x, parameter.cloudsParameter.y * 0.75, 0, 1);
|
||||
//float end = lerp(_CloudsCoverageSettings.y * 0.85,_CloudsCoverageSettings.y * 1.25,height);
|
||||
|
||||
raymarchEnd = min(raymarchEnd, _CloudsCoverageSettings.y);
|
||||
|
||||
if (ch < parameter.cloudsParameter.x)
|
||||
{
|
||||
sampleEnd = min(raymarchEnd, sampleEnd);
|
||||
inside = 0;
|
||||
|
||||
if(ray.y < 0)
|
||||
return float2(0,0);
|
||||
}
|
||||
else if (ch > parameter.cloudsParameter.y)
|
||||
{
|
||||
sampleEnd = min(raymarchEnd, sampleEnd);
|
||||
inside = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sampleEnd = min(raymarchEnd, sampleEnd);
|
||||
inside = 0;
|
||||
}
|
||||
|
||||
return float2(max(0.0f,sampleStart), min(raymarchEnd, sampleEnd));
|
||||
}
|
||||
|
||||
float CalculateLodMips(float distanceToCamera)
|
||||
{
|
||||
return lerp(0.0, lerp(5.0,0.0,_LODDistance), saturate((distanceToCamera - 3000.0) / (100000.0 - 3000.0)));
|
||||
}
|
||||
|
||||
|
||||
float3 Raymarch (float3 cameraPos, float3 ray, float2 hitDistance, float3 center, RaymarchParameters parameters, float offset)
|
||||
{
|
||||
float cloud_test = 0.0;
|
||||
int zero_density_sample_count = 0;
|
||||
float sampled_density_previous = -1.0;
|
||||
|
||||
float alpha = 1.0;
|
||||
float intensity = 0.0;
|
||||
float depth = 0.0;
|
||||
float depthWeightSum = 0.000001;
|
||||
float trans = 1.0f;
|
||||
|
||||
int steps = (int)lerp(parameters.minSteps, parameters.maxSteps, ray.y);
|
||||
|
||||
//int steps = parameters.maxSteps;
|
||||
float rayStepLength = (hitDistance.y - hitDistance.x) / steps;
|
||||
float3 rayStep = ray * rayStepLength;
|
||||
|
||||
float3 pos = (cameraPos + (hitDistance.x) * ray);
|
||||
pos += (offset * rayStepLength) * ray;
|
||||
//pos += rayStep;
|
||||
pos += rayStep;
|
||||
float3 sampleEndPos = cameraPos + ray * hitDistance.y;
|
||||
float eyeToEnd = distance(cameraPos, sampleEndPos);
|
||||
float cosTheta = dot(ray, normalize(_LightDir));
|
||||
|
||||
[loop]
|
||||
for (int i = 0; i < steps; i++)
|
||||
{
|
||||
|
||||
//Calculate projection height
|
||||
float height = GetSamplingHeight(pos, center, parameters.cloudsParameter);
|
||||
|
||||
//Get out of expensive raymarching
|
||||
if (alpha <= 0.01 || height > 1.0 || height < 0.0 || _CloudsCoverageSettings.x <= -0.9)
|
||||
break;
|
||||
|
||||
// Get Weather Data
|
||||
float4 weather = GetWeather(pos);
|
||||
|
||||
float distanceToCamera = length(pos - cameraPos);
|
||||
float lod = CalculateLodMips(distanceToCamera);
|
||||
|
||||
if (cloud_test > 0.0)
|
||||
{
|
||||
float sampled_density = CalculateCloudDensity(pos, center, parameters, weather, 0, lod, true);
|
||||
|
||||
if (sampled_density == 0.0 && sampled_density_previous == 0.0)
|
||||
{
|
||||
zero_density_sample_count++;
|
||||
}
|
||||
|
||||
if (zero_density_sample_count < 8 && sampled_density != 0.0)
|
||||
{
|
||||
float extinction = pow(max(parameters.density * sampled_density,0.001),parameters.densitySmoothness);
|
||||
float clampedExtinction = max(extinction, 1e-7);
|
||||
|
||||
float transmittance = exp(-extinction * rayStepLength);
|
||||
|
||||
float gradApprox = abs(sampled_density - sampled_density_previous);
|
||||
|
||||
// edge-sensitive ds_lod
|
||||
float ds_lod_local = sampled_density * (1.0 + lod * 0.8);
|
||||
|
||||
float luminance = SampleEnergy(pos, cosTheta, center, parameters, _LightDir, height, sampled_density, rayStepLength,weather,lod,gradApprox);
|
||||
|
||||
float integScatt = (luminance - luminance * transmittance);
|
||||
|
||||
float depthWeight = trans;
|
||||
depth += depthWeight * distanceToCamera;
|
||||
depthWeightSum += depthWeight;
|
||||
|
||||
intensity += trans * integScatt;
|
||||
|
||||
trans *= transmittance;
|
||||
alpha *= max(transmittance, 0.0);
|
||||
|
||||
if (alpha <= 0.01)
|
||||
alpha = 0.0;
|
||||
}
|
||||
// if not, then set cloud_test to zero so that we go back to the cheap sample case
|
||||
else if(zero_density_sample_count >= 8)
|
||||
{
|
||||
cloud_test = 0.0;
|
||||
zero_density_sample_count = 0;
|
||||
}
|
||||
|
||||
sampled_density_previous = sampled_density;
|
||||
pos += rayStep;
|
||||
}
|
||||
else
|
||||
{
|
||||
// sample density the cheap way, only using the low frequency noise
|
||||
cloud_test = CalculateCloudDensity(pos, center, parameters, weather, 0, lod, (bool)inside);
|
||||
|
||||
if (cloud_test == 0.0)
|
||||
{
|
||||
pos += rayStep * 2;
|
||||
}
|
||||
else //take a step back and capture area we skipped.
|
||||
{
|
||||
pos -= rayStep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
float distance = depth / depthWeightSum;
|
||||
|
||||
if (distance <= 0.0)
|
||||
{
|
||||
distance = length(sampleEndPos - cameraPos);
|
||||
}
|
||||
|
||||
alpha = saturate(1.0f - alpha);
|
||||
|
||||
return float3(intensity,distance,alpha);
|
||||
|
||||
}
|
||||
|
||||
float3 CalculateWorldPosition (float2 uv, float depth)
|
||||
{
|
||||
float4x4 proj, eyeToWorld;
|
||||
|
||||
if (unity_StereoEyeIndex == 0)
|
||||
{
|
||||
proj = _LeftViewFromScreen;
|
||||
eyeToWorld = _LeftWorldFromView;
|
||||
}
|
||||
else
|
||||
{
|
||||
proj = _RightViewFromScreen;
|
||||
eyeToWorld = _RightWorldFromView;
|
||||
}
|
||||
|
||||
//bit of matrix math to take the screen space coord (u,v,depth) and transform to world space
|
||||
float2 uvClip = uv * 2.0 - 1.0;
|
||||
float clipDepth = depth; // Fix for OpenGl Core thanks to Lars Bertram
|
||||
clipDepth = (UNITY_NEAR_CLIP_VALUE < 0) ? clipDepth * 2 - 1 : clipDepth;
|
||||
float4 clipPos = float4(uvClip, clipDepth, 1.0);
|
||||
float4 viewPos = mul(proj, clipPos); // inverse projection by clip position
|
||||
viewPos /= viewPos.w; // perspective division
|
||||
return float3(mul(eyeToWorld, viewPos).xyz);
|
||||
}
|
||||
|
||||
float RaymarchShadows (float3 cameraPos, float3 worldPos,float3 ray,float3 center, RaymarchParameters parameters, float offset,float depth)
|
||||
{
|
||||
if(depth == 0.0f)
|
||||
return 0.0;
|
||||
|
||||
int steps = 16;
|
||||
float worldDotLight = saturate(dot(float3(0, 1, 0), _LightDir));
|
||||
float bottomDist = max(0, parameters.cloudsParameter.x ) / worldDotLight;
|
||||
float topDist = max(0, parameters.cloudsParameter.y ) / worldDotLight;
|
||||
|
||||
float rayStepLength = (topDist - bottomDist) / steps;
|
||||
float3 rayStep = _LightDir * rayStepLength;
|
||||
|
||||
float3 pos = worldPos + bottomDist * _LightDir;
|
||||
|
||||
float4 weather = GetWeather(pos);
|
||||
float intensity = 0.05;
|
||||
|
||||
float shadowIntensity = 0.0;
|
||||
|
||||
float _Softness = 2.0f;
|
||||
|
||||
[unroll]
|
||||
for (int i = 0; i < steps; i++)
|
||||
{
|
||||
float3 samplePos = rayStepLength * i * _LightDir + pos;
|
||||
float sampleResult = CalculateCloudDensity(samplePos, center, parameters, weather, 0, 0, true) * intensity;
|
||||
float result = sampleResult * (rayStepLength / (i + 1));
|
||||
shadowIntensity += result;
|
||||
|
||||
// if (shadowIntensity > 0.99)
|
||||
// break;
|
||||
}
|
||||
return (shadowIntensity);
|
||||
}
|
||||
Reference in New Issue
Block a user