16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 03:09:18 +02:00

add clouds

This commit is contained in:
Wls50
2025-12-10 19:06:19 +01:00
committed by Hirek
parent 22479671d4
commit 0794a0f621
16 changed files with 258 additions and 50 deletions

View File

@@ -18,6 +18,7 @@ SamplerState g_SamplerPointClamp : register(s1);
#include "cubemap_utils.hlsli"
#include "manul/sky.hlsli"
#include "manul/clouds.hlsli"
struct FilterParameters {
uint3 m_Offset;
@@ -50,6 +51,7 @@ void main(uint3 PixCoord : SV_DispatchThreadID) {
//g_OutCubemap[PixCoord + g_Offset] = g_Skybox.SampleLevel(g_SamplerLinearClamp, normal, 0.);
float3 color = 1.e-7;
CalcAtmosphere(color, normal, g_FilterParams.m_LightVector);
CalcClouds(color, normal, g_FilterParams.m_LightVector);
//CalcAtmosphere(g_OutCubemap[PixCoord + g_Offset], 1., normal, g_LightVector, g_Altitude, SKY_INF, g_LightColor.rgb, 10);
float3 normal_flipped = normal * float3(-1., 1., 1.);
float depth = g_Depth.SampleLevel(g_SamplerPointClamp, normal_flipped, 0.);

View File

@@ -0,0 +1,69 @@
#ifndef CLOUDS_HLSLI
#define CLOUDS_HLSLI
#include "sky.hlsli"
Texture2D<float4> g_Clouds : register(t15);
Texture2D<float> g_HighClouds : register(t16);
SamplerState g_CloudsSampler : register(s15);
float3 desaturate(float3 col, float amount) {
return lerp(col, dot(col, float3(.2126, .7152, .0722)), amount);
}
// https://iquilezles.org/articles/smin/
// sigmoid
float smin( float a, float b, float k )
{
k *= log(2.0);
float x = b-a;
return a + x/(1.0-exp2(x/k));
}
float ComputeTopDown(float value) {
value = -0.9501426 * value * value + 2.09511187 * value + -0.16186117;
return -smin(-value, 0., .045);
}
void CalcClouds(inout float3 color, in float3 viewDir, in float3 sunDir) {
float3 emissive_top = 1.e-7;
float3 emissive_sun = linear_srgb_from_spectral_samples(sun_spectral_irradiance) * exp(-4.);
float3 emissive_view = 1.e-7;
CalcAtmosphere(emissive_top, float3(0., 1., 0.), sunDir);
CalcAtmosphere(emissive_sun, sunDir, sunDir);
CalcAtmosphere(emissive_view, viewDir, sunDir);
float3 cloud_dir = viewDir;
cloud_dir.y = 4. * abs(cloud_dir.y);
cloud_dir = normalize(cloud_dir);
float4 cloud_mask = g_Clouds.SampleLevel(g_CloudsSampler, cloud_dir.xz * .5 + .5, 0.);
float high_cloud_mask = g_HighClouds.SampleLevel(g_CloudsSampler, cloud_dir.xz * .5 + .5, 0.) * .5;
float selector = atan2(sunDir.z, sunDir.x) / TWO_PI;
selector -= floor(selector);
selector *= 3.;
int idx = floor(selector);
float cloud_lit = lerp(cloud_mask[idx], cloud_mask[(idx + 1) % 3], frac(selector));
float topdown = ComputeTopDown(saturate(viewDir.y));
float3 ndotl = saturate(dot(viewDir, sunDir) * .5 + .5);
float shine = pow(ndotl, 17.);
float3 shadow_color = desaturate(lerp(emissive_view, emissive_top, .5), .5);// * lerp(1., .1, shine);
float3 lit_color = lerp(emissive_view, emissive_sun, .5) * lerp(1., 4., shine);
cloud_lit = pow(cloud_lit, lerp(lerp(1.6, 1.2, topdown), 3., shine));
float3 cloud_color = lerp( shadow_color, lit_color, cloud_lit);
cloud_color = lerp(cloud_color, emissive_view, smoothstep(.05, 0., topdown));
float3 high_cloud_color = lit_color;
high_cloud_color = lerp(high_cloud_color, emissive_view, smoothstep(.05, 0., topdown));
color = lerp(color, high_cloud_color, high_cloud_mask * smoothstep(-.025, .025, viewDir.y));
color = lerp(color, cloud_color, cloud_mask.a * smoothstep(-.025, .025, viewDir.y));
}
#endif

View File

@@ -5,6 +5,8 @@
#include "material_common.hlsli"
#include "sky_common.hlsli" // ray_sphere_intersection
#include "view_data.hlsli"
#include "lighting_functions.hlsli"
@@ -16,6 +18,7 @@ TextureCube<float3> g_DiffuseEnvmap : register(t8);
TextureCube<float3> g_SpecularEnvmap : register(t9);
Texture2D<float2> g_BrdfLUT : register(t10);
Texture2D<float4> g_CloudShadowMap : register(t15);
Texture2D<uint2> g_LightGrid : register(t16);
StructuredBuffer<uint> g_LightIndexBuffer : register(t17);
StructuredBuffer<PackedLight> g_LightBuffer : register(t18);
@@ -83,6 +86,15 @@ void ApplyMaterialLighting(out float4 lit, in MaterialData material)
#ifdef GBUFFER_CONTACT_SHADOWS_HLSLI
shadow = min(shadow, GetContactShadows(pixel_position));
#endif
float t = ray_sphere_intersection(view, g_LightDir.xyz, 10000.);
if(t >= 0.) {
float3 cloud_dir = normalize(view + g_LightDir.xyz * t);
cloud_dir.y = 4. * abs(cloud_dir.y);
cloud_dir = normalize(cloud_dir);
float4 cloud_mask = g_CloudShadowMap.SampleLevel(g_SamplerLinearClamp, cloud_dir.xz * .5 + .5, 0.);
shadow = min(shadow, 1. - cloud_mask.a * .6);
}
// Apply IBL cubemap
ApplyIBL(lit.rgb, surface_data);

View File

@@ -22,7 +22,7 @@ void CalcSun(inout float3 color, in float3 viewDir, in float3 sunDir, in float a
{
if (dot(viewDir, sunDir) > 0.99998869014)
{
color = linear_srgb_from_spectral_samples(sun_spectral_irradiance);
color = linear_srgb_from_spectral_samples(sun_spectral_irradiance) * exp(-2.);
}
}
}
@@ -37,7 +37,7 @@ void CalcMoon(inout float3 color, in float3 viewDir, in float3 moonDir, in float
float3 normal = CalcSphereNormal(viewDir, moonDir, 0.99998869014);
if (dot(normal, normal) > 0.)
{
color = .07 * max(dot(normal, sunDir), 0.) * linear_srgb_from_spectral_samples(sun_spectral_irradiance);
color = .07 * max(dot(normal, sunDir), 0.) * linear_srgb_from_spectral_samples(sun_spectral_irradiance) * exp(-2.);
}
}
}

View File

@@ -14,6 +14,7 @@ cbuffer DispatchConstants : register(b0)
RWTexture2DArray<float4> g_AerialLut : register(u0);
RWTexture2D<float4> g_Sky : register(u1);
Texture2D<float4> g_Clouds : register(t15);
Texture2D<float4> g_TransmittanceLut : register(t13);
SamplerState g_TransmittanceLutSampler : register(s13);
@@ -77,8 +78,8 @@ SamplerState g_TransmittanceLutSampler : register(s13);
{
float t = (i + 1.) / (float)texture_size.z;
float end_depth = min(t_d, t * t * g_MaxDepth);
compute_inscattering(g_TransmittanceLut, g_TransmittanceLutSampler, molecular_phase, aerosol_phase, 5, ray_origin, ray_dir, start_depth, end_depth, g_SunDir, L, transmittance);
compute_inscattering(g_TransmittanceLut, g_TransmittanceLutSampler, molecular_phase_moon, aerosol_phase_moon, 5, ray_origin, ray_dir, start_depth, end_depth, g_MoonDir, M, transmittance_m);
compute_inscattering_with_cloud_shadow(g_TransmittanceLut, g_Clouds, g_TransmittanceLutSampler, molecular_phase, aerosol_phase, 5, ray_origin, ray_dir, start_depth, end_depth, g_SunDir, L, transmittance);
compute_inscattering_with_cloud_shadow(g_TransmittanceLut, g_Clouds, g_TransmittanceLutSampler, molecular_phase_moon, aerosol_phase_moon, 5, ray_origin, ray_dir, start_depth, end_depth, g_MoonDir, M, transmittance_m);
g_AerialLut[uint3(pix_coord, i)] = float4(linear_srgb_from_spectral_samples(L + .07 * moon_phase * M) * exp2(EXPOSURE), dot(transmittance, .25));
start_depth = end_depth;
}

View File

@@ -66,6 +66,64 @@ void compute_inscattering(Texture2D transmittance_lut, SamplerState lut_sampler,
}
}
void compute_inscattering_with_cloud_shadow(Texture2D transmittance_lut, Texture2D clouds, SamplerState lut_sampler, in float molecular_phase, in float aerosol_phase, int steps, float3 ray_origin, float3 ray_dir, float t_min, float t_max, float3 sun_dir, inout float4 L_inscattering, inout float4 transmittance)
{
float dt = (t_max - t_min) / float(steps);
for (int i = 0; i < steps; ++i) {
float t = t_min + (float(i) + 0.5) * dt;
float3 x_t = ray_origin + ray_dir * t;
float distance_to_earth_center = length(x_t);
float3 zenith_dir = x_t / distance_to_earth_center;
float altitude = distance_to_earth_center - EARTH_RADIUS;
float normalized_altitude = altitude / ATMOSPHERE_THICKNESS;
float sample_cos_theta = dot(zenith_dir, sun_dir);
float shadow = 1.;
float c_t = ray_sphere_intersection(ray_dir * t, sun_dir, 10000.);
if(c_t >= 0.) {
float3 cloud_dir = normalize(ray_dir * t + sun_dir * c_t);
cloud_dir.y = 4. * cloud_dir.y;
cloud_dir = normalize(cloud_dir);
float4 cloud_mask = clouds.SampleLevel(lut_sampler, cloud_dir.xz * .5 + .5, 0.);
shadow = min(shadow, 1. - cloud_mask.a * smoothstep(-.01, .01, cloud_dir.y));
}
float4 aerosol_absorption, aerosol_scattering;
float4 molecular_absorption, molecular_scattering;
float4 fog_scattering;
float4 extinction;
get_atmosphere_collision_coefficients(
altitude,
aerosol_absorption, aerosol_scattering,
molecular_absorption, molecular_scattering,
fog_scattering,
extinction);
float4 transmittance_to_sun = transmittance_from_lut(
transmittance_lut, lut_sampler, sample_cos_theta, normalized_altitude) * shadow;
float4 ms = get_multiple_scattering(
transmittance_lut, lut_sampler, sample_cos_theta, normalized_altitude,
distance_to_earth_center);
float4 S = sun_spectral_irradiance *
(molecular_scattering * (molecular_phase * transmittance_to_sun + ms) +
(aerosol_scattering + fog_scattering) * (aerosol_phase * transmittance_to_sun + ms));
float4 step_transmittance = exp(-dt * extinction);
// Energy-conserving analytical integration
// "Physically Based Sky, Atmosphere and Cloud Rendering in Frostbite"
// by Sébastien Hillaire
float4 S_int = (S - S * step_transmittance) / max(extinction, 1e-7);
L_inscattering += transmittance * S_int;
transmittance *= step_transmittance;
}
}
float4 get_inscattering(Texture2D transmittance_lut, SamplerState lut_sampler, int steps, float altitude, float3 ray_dir, float t_min, float t_max, float3 sun_dir) {
float cos_theta = dot(-ray_dir, sun_dir);
float molecular_phase = molecular_phase_function(cos_theta);

View File

@@ -24,6 +24,7 @@ sampler g_SkyboxSampler : register(s0);
TextureCube g_Skybox : register(t0);
#include "manul/sky.hlsli"
#include "manul/clouds.hlsli"
PixelOutput main(VertexOutput ps_in) {
PixelOutput result;
@@ -38,6 +39,7 @@ PixelOutput main(VertexOutput ps_in) {
CalcSun(result.m_Emission, viewDir, g_SunDirection, g_Altitude);
CalcMoon(result.m_Emission, viewDir, g_MoonDirection, g_SunDirection, g_Altitude);
CalcAtmosphere(result.m_Emission, viewDir, g_SunDirection);
CalcClouds(result.m_Emission, viewDir, g_SunDirection);
//result.m_Emission = g_Skybox.Sample(g_SkyboxSampler, normalize(mul(g_InverseViewProjection, positionNdc).xyz)).rgb;
//result.m_Emission = 0.; //Sky(normalize(mul(g_InverseViewProjection, positionNdc).xyz), g_SunDirection, g_Altitude);
float4 positionReproject = mul(g_HistoryReproject, positionNdc);