Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- float3 ViewDir = normalize(Parameters.AbsoluteWorldPosition - ResolvedView.WorldCameraOrigin);
- float3 BoxMin = float3(CloudsPosition.x - CloudsScale.x / 2.0, CloudsPosition.y - CloudsScale.y / 2.0, CloudsPosition.z);
- float3 BoxMax = float3(CloudsPosition.x + CloudsScale.x / 2.0, CloudsPosition.y + CloudsScale.y / 2.0, CloudsPosition.z + CloudsScale.z);
- float3 tMin = (BoxMin - ResolvedView.WorldCameraOrigin) / ViewDir;
- float3 tMax = (BoxMax - ResolvedView.WorldCameraOrigin) / ViewDir;
- float3 t1 = min(tMin, tMax);
- float3 t2 = max(tMin, tMax);
- float NearL = max(max(t1.x, t1.y), t1.z);
- float FarL = min(min(t2.x, t2.y), t2.z);
- float RayLength = FarL - NearL;
- float DensitySamples = MaxSamples;
- float RayOffset = CloudsScale.z / MinSamples;
- if(bStaticOffset == 0)
- {
- DensitySamples = lerp(MinSamples, MaxSamples, (RayLength - CloudsScale.z) / (CloudsScale.x / 2.0));
- RayOffset = RayLength / DensitySamples;
- }
- float3 RayDir = ViewDir * RayOffset;
- if(ResolvedView.WorldCameraOrigin.z < BoxMax.z && ResolvedView.WorldCameraOrigin.z > BoxMin.z && ResolvedView.WorldCameraOrigin.x < BoxMax.x && ResolvedView.WorldCameraOrigin.x > BoxMin.x && ResolvedView.WorldCameraOrigin.y < BoxMax.y && ResolvedView.WorldCameraOrigin.y > BoxMin.y)
- {
- NearL = 0;
- }
- float3 RayPos = ResolvedView.WorldCameraOrigin + ViewDir * NearL;
- float Jitter =float(Rand3DPCG16(int3(Parameters.SvPosition.xy, View.StateFrameIndexMod8)).x) / 0xffff;
- RayPos += RayDir * Jitter;
- static const float3 RandomVectors[] =
- {
- float3( 0.38051305f, 0.92453449f, -0.02111345f),
- float3(-0.50625799f, -0.03590792f, -0.86163418f),
- float3(-0.32509218f, -0.94557439f, 0.01428793f),
- float3( 0.09026238f, -0.27376545f, 0.95755165f),
- float3( 0.28128598f, 0.42443639f, -0.86065785f),
- float3(-0.16852403f, 0.14748697f, 0.97460106f)
- };
- float Transmittance = 1.0;
- float3 LightEnergy = 0.0;
- ///////////////////////////////////////////////////////////////////////// Ray Basis
- float ShadowRayOffset = (CloudsScale.z / 2.0) / ShadowSamples;
- /////////////////////////
- ///////////////////////// FUNCTIONS
- /////////////////////////
- struct Functions
- {
- float WMSize;
- float2 WMOffset;
- Texture2D WeatherMap;
- float BNSize;
- float3 NoiseOffset;
- Texture3D BaseNoise;
- float DistortionMapSize;
- Texture2D DistortionMap;
- float DistortionMapIntensity;
- float DNSize;
- float DetailNoiseOffsetScale;
- Texture3D DetailNoise;
- float ShadowSamples;
- float3 LightVector;
- float ShadowRayOffset;
- float ConeRadius;
- float CloudsPos;
- float CloudsHeight;
- float ConeStepScale;
- float InScatter;
- float SilverLightIntensity;
- float SilverLightExponent;
- float OutScatter;
- float InOutScatterLerp;
- float3 AmbientLightTop;
- float3 AmbientLightBottom;
- float3 SDensity;
- float3 SClamp;
- float CoverageShift;
- ///////////////////////// Remapping function.
- float remap(float V, float L0, float H0, float Ln, float Hn)
- {
- return Ln + (V - L0) * (Hn - Ln) / (H0 - L0);
- }
- float3 remap3(float3 V, float3 L0, float3 H0, float3 Ln, float3 Hn)
- {
- return Ln + (V - L0) * (Hn - Ln) / (H0 - L0);
- }
- ///////////////////////// Height gradient.
- float GetHeightGradient(float3 LocalRayPos)
- {
- return (LocalRayPos.z - CloudsPos) / CloudsHeight;
- }
- /////////////////////////
- ///////////////////////// DENSITY
- /////////////////////////
- float3 GetSimpleDensity(float HeightGradient, float3 LocalRayPos, float Mipmap, SamplerState WeatherMapSampler, SamplerState BaseNoiseSampler)
- {
- //Weather texture.
- float2 WMUV = (LocalRayPos.xy - (WMSize / 2.0)) / (WMSize) + WMOffset;
- float4 WM = WeatherMap.SampleLevel(WeatherMapSampler, WMUV, Mipmap);
- float WMc = WM.r;
- float CloudType = WM.g;
- float CloudMaxHeight = saturate(0.1 + CloudType * 2.0);
- float GlobalCoverage = saturate(0.5 + CloudType * 2.0);
- GlobalCoverage = CoverageShift;
- float CloudAnvilAmount = saturate((CloudType - 0.5) * 2.0);
- float CloudMaxDensity = 0.5;
- //float SA = HeightAlter(HeightGradient, WM);
- float SA = pow(saturate(remap(HeightGradient , 0.0, 0.07, 0.0, 1.0)) * saturate(remap(HeightGradient, saturate(CloudMaxHeight + 0.12) * 0.2, saturate(CloudMaxHeight + 0.12), 1.0, 0.0)), saturate(remap(HeightGradient, 0.65, 0.95, 1.0, (1 - CloudAnvilAmount * GlobalCoverage))));
- float DA = HeightGradient * saturate(remap(HeightGradient, 0.0, 0.2, 0.0, 1.0)) * CloudMaxDensity * 2.0 * lerp(1.0, saturate(remap(pow(HeightGradient, 0.5), 0.4, 0.95, 1.0, 0.2)), CloudAnvilAmount) * saturate(remap(HeightGradient, 0.9, 1.0, 1.0, 0.0));
- //Base noise.
- float3 BNUVW = (LocalRayPos / BNSize + NoiseOffset);
- float4 BN = BaseNoise.SampleLevel(BaseNoiseSampler, BNUVW, Mipmap).xyzw;
- //float SNs = ShapeNoise(BN);
- float SNs = remap(BN.r, -(1 - (BN.g * 0.625 + BN.b * 0.25 + BN.a * 0.125)), 1.0, 0.0, 1.0);
- //SNs = 1.0;
- float SN = saturate(remap(SNs * SA, 1.0 - GlobalCoverage * WMc, 1.0, 0.0, 1.0));
- return float3(SN, DA, GlobalCoverage);
- }
- float GetDetailedDensity(float HeightGradient, float3 LocalRayPos, float Mipmap, float SN, float DA, float GlobalCoverage, SamplerState DistortionMapSampler, SamplerState DetailNoiseSampler)
- {
- //Distortion.
- float2 DMUV = (LocalRayPos.xy) / (DistortionMapSize);
- float3 DM = DistortionMap.SampleLevel(DistortionMapSampler, DMUV, Mipmap).xyz;
- DM = ((DM - 0.5) * DistortionMapIntensity);
- DM *= (1.0 - HeightGradient * 0.5);
- //Detail noise.
- float3 DNUVW = (LocalRayPos / DNSize + NoiseOffset * DetailNoiseOffsetScale) + DM;
- float4 DN = DetailNoise.SampleLevel(DetailNoiseSampler, DNUVW, Mipmap);
- //float SNd = DetailNoise(HeightGradient, DN, SN);
- float DNs = DN.r * 0.625 + DN.g * 0.25 + DN.b * 0.125;
- float SNd = saturate(remap(SN, lerp(DNs, 1.0 - DNs, saturate(HeightGradient * 5.0 + 0.25)) * 0.35 * exp(-GlobalCoverage * 0.75), 1.0, 0.0, 1.0));
- return SNd * DA;
- }
- ///////////////////////// Density to sun.
- float GetDTS(float3 LocalRayPos, int MipmapStart, SamplerState WeatherMapSampler, SamplerState BaseNoiseSampler, SamplerState DistortionMapSampler, SamplerState DetailNoiseSampler)
- {
- float DTS = 0.0;
- float3 ShadowRayPos = 0.0;
- for(int srs = 0; srs < ShadowSamples; srs++)
- {
- int ResultMipmap = MipmapStart + int(srs * 0.5);
- LocalRayPos += LightVector * ShadowRayOffset;
- ShadowRayPos = LocalRayPos + ConeRadius * RandomVectors[floor(frac(srs / 6) * 6)];
- //Height gradient.
- float HeightGradient = GetHeightGradient(ShadowRayPos);
- if(HeightGradient > 1.0 || HeightGradient < 0.0)
- break;
- //Sample simple density.
- float3 SimpleDS = GetSimpleDensity(HeightGradient, ShadowRayPos, ResultMipmap, WeatherMapSampler, BaseNoiseSampler);
- if(SimpleDS.x * SimpleDS.y > 0.0)
- {
- DTS += GetDetailedDensity(HeightGradient, ShadowRayPos, ResultMipmap, SimpleDS.x, SimpleDS.y, SimpleDS.z, DistortionMapSampler, DetailNoiseSampler);
- }
- ConeRadius += ConeStepScale;
- }
- //Last disntaced step.
- LocalRayPos += LightVector * ShadowRayOffset * ShadowSamples * 0.5;
- float HeightGradient = GetHeightGradient(LocalRayPos);
- float3 SimpleDS = GetSimpleDensity(HeightGradient, LocalRayPos, 6, WeatherMapSampler, BaseNoiseSampler);
- if(SimpleDS.x * SimpleDS.y > 0.0)
- {
- DTS += GetDetailedDensity(HeightGradient, LocalRayPos, 6, SimpleDS.x, SimpleDS.y, SimpleDS.z, DistortionMapSampler, DetailNoiseSampler);
- }
- return DTS;
- }
- ///////////////////////// Henyey-Greenstein.
- float HenyeyGreenstein(float Angle, float G)
- {
- return ((1.0 - G*G) / pow(abs(1.0 + G*G - 2.0 * G * Angle), 1.5)) / (4 * 3.1415);
- }
- ///////////////////////// Scattering.
- float GetInOutScatter(float cos_angle)
- {
- float first_hg = HenyeyGreenstein(cos_angle , InScatter);
- float second_hg = SilverLightIntensity * pow(abs(saturate(cos_angle)), SilverLightExponent);
- float in_scatter_hg = max(first_hg , second_hg);
- float out_scatter_hg = HenyeyGreenstein(cos_angle , -OutScatter);
- return lerp(in_scatter_hg ,out_scatter_hg, InOutScatterLerp);
- }
- ///////////////////////// Exponential integral.
- float IntE( float z )
- {
- return 0.5772156649015328606065 + log( 1e-4 + abs(z) ) + z * (1.0 + z * (0.25 + z * ( (1.0/18.0) + z * ( (1.0/96.0) + z * (1.0/600.0) ) ) ) ); // For x!=0
- }
- ///////////////////////// Exponential ambient color.
- float3 GetIsotropicScattering(float HeightGradient, float ExtinctionCoeff)
- {
- float Sample = -ExtinctionCoeff * HeightGradient;
- float3 IsotropicScatteringTop = AmbientLightTop * max(0.0, exp(Sample) - Sample * IntE(Sample));
- Sample = -ExtinctionCoeff * (1.0 - HeightGradient);
- float3 IsotropicScatteringBottom = AmbientLightBottom* max(0.0, exp(Sample) - Sample * IntE(Sample));
- return IsotropicScatteringTop + IsotropicScatteringBottom;
- }
- ///////////////////////// Attenuation.
- float3 GetAttenuation( float DTS, float Angle)
- {
- float3 prim = exp(-SDensity * DTS);
- float3 scnd = exp(-SDensity * SClamp) * 0.7;
- float3 checkval = remap3(Angle, 0.0, 1.0, scnd, scnd * 0.5);
- return max(checkval, prim);
- }
- };
- /////////////////////////
- /////////////////////////FUNCTIONS END
- /////////////////////////
- Functions F;
- /** Rework it, way too slow and bad solution. */
- F.WMSize = WMSize;
- F.WMOffset = WMOffset;
- F.WeatherMap = WeatherMap;
- F.BNSize = BNSize;
- F.NoiseOffset = NoiseOffset;
- F.BaseNoise = BaseNoise;
- F.DistortionMapSize = DistortionMapSize;
- F.DistortionMap = DistortionMap;
- F.DistortionMapIntensity = DistortionMapIntensity;
- F.DNSize = DNSize;
- F.DetailNoiseOffsetScale = DetailNoiseOffsetScale;
- F.DetailNoise = DetailNoise;
- F.ShadowSamples = ShadowSamples;
- F.LightVector = LightVector;
- F.ShadowRayOffset = ShadowRayOffset;
- F.ConeRadius = ConeRadius;
- F.CloudsPos = CloudsPosition.z;
- F.CloudsHeight = CloudsScale.z;
- F.ConeStepScale = ConeStepScale;
- F.InScatter = InScatter;
- F.SilverLightIntensity = SilverLightIntensity;
- F.SilverLightExponent = SilverLightExponent;
- F.OutScatter = OutScatter;
- F.InOutScatterLerp = InOutScatterLerp;
- F.AmbientLightTop = AmbientLightTop;
- F.AmbientLightBottom = AmbientLightBottom;
- F.SDensity = SDensity;
- F.SClamp = SClamp;
- F.CoverageShift = CoverageShift;
- float3 SDSample = 0.0;
- float DSample = 0.0;
- float3 DensitySum = 0.0;
- float DensityToSun = 0.0;
- float3 Attenuation = 0.0;
- float3 Powder = 0.0;
- float InOutScatter = 0.0;
- float3 IsotropicScatter = 0.0;
- float AngleVdL = dot(normalize(RayDir), normalize(LightVector));
- float BaseDensityMip = 0.0;
- int DensityMip = 0;
- float SkyBlendSum = ((NearL * SkyBlendIntensity * Transmittance) / SkyBlendDistance);
- for(int rs = 0; rs<DensitySamples; rs++)
- {
- if(length(RayPos - ResolvedView.WorldCameraOrigin) >= DepthBehind)
- break;
- if(Transmittance > 0.001)
- {
- //Calculate density mip,ap parameter based on distance and density itself.
- BaseDensityMip = length(RayPos.xy - ResolvedView.WorldCameraOrigin.xy) / MipDistance;
- DensityMip = floor(BaseDensityMip);
- if(1 - Transmittance >= 0.3)
- {
- if(1 - Transmittance >= 0.6)
- {
- DensityMip += 2;
- }
- else
- {
- DensityMip += 1;
- }
- }
- //HeightGradient.
- float HeightGradient = F.GetHeightGradient(RayPos);
- if(HeightGradient < 0.0 || HeightGradient > 1.0)
- break;
- SDSample = F.GetSimpleDensity(HeightGradient, RayPos, DensityMip, WeatherMapSampler, BaseNoiseSampler);
- if(SDSample.x * SDSample.y > 0.0)
- {
- DSample = F.GetDetailedDensity(HeightGradient, RayPos, DensityMip, SDSample.x, SDSample.y, SDSample.z, DistortionMapSampler, DetailNoiseSampler);
- if(DSample > 0.001)
- {
- DensitySum = (DSample * CloudsDensity);
- DensityToSun = F.GetDTS(RayPos, DensityMip, WeatherMapSampler, BaseNoiseSampler, DistortionMapSampler, DetailNoiseSampler);
- Powder = 1.0 - exp( -DSample);
- Attenuation = F.GetAttenuation(DensityToSun , AngleVdL) * LightColor;
- InOutScatter = F.GetInOutScatter(AngleVdL);
- IsotropicScatter = F.GetIsotropicScattering(HeightGradient, DSample);
- float3 LightSample = (Attenuation * IsotropicScatter * InOutScatter);
- LightSample = lerp(PColor, 1.0, LightSample);
- LightEnergy += LightSample * DensitySum * Transmittance;
- Transmittance *= exp(-DensitySum.x);
- }//end:if(DSample > 0.001)
- }//end:if(SDSample.x * SDSample.y > 0.0)
- RayPos += RayDir + RayDir * BaseDensityMip;
- if(RayPos.z > BoxMax.z && RayPos.z < BoxMin.z
- && RayPos.x > BoxMax.x && RayPos.x < BoxMin.x
- && RayPos.y > BoxMax.y && RayPos.y < BoxMin.y)
- {
- break;
- }
- SkyBlendSum += (((RayOffset + RayOffset * BaseDensityMip) * SkyBlendIntensity * Transmittance) / SkyBlendDistance) * (1.0 - saturate(RayPos.z / SkyBlendHeight));
- }//end:if(Transmittance > 0.01)
- else
- {
- break;
- }
- }//end: for(int rs = 0; rs<DensitySamples; rs++)
- //LightEnergy = lerp(AmbientLightBottom, AmbientLightTop, LightEnergy) * (1.0 - Transmittance);
- float SkyBlendLerp = saturate(SkyBlendSum - SkyBlendStartDistance);
- float SkyTransmittance = lerp(0.0, 1.0, SkyBlendLerp);
- LightEnergy = lerp(LightEnergy, 0.0, SkyBlendLerp);
- LightEnergy += SkyColor * SkyTransmittance * (1.0 - Transmittance);
- return float4(LightEnergy, saturate(Transmittance - 0.01));
- return 1.0;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement