mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-18 03:19:19 +02:00
Fray the edges of the volumetric clouds with a finer noise and let their billows shade one another
This commit is contained in:
@@ -299,7 +299,7 @@ void opengl46_weather::update(opengl46_sky const &Sky, glm::vec3 const &Keylight
|
||||
auto const velocity{weather.cloud_velocity()};
|
||||
auto const speed{glm::length(velocity)};
|
||||
auto const wind{speed > 1e-3f ? glm::dvec2{velocity / speed} : glm::dvec2{1.0, 0.0}};
|
||||
m_weather.cloud_wind = glm::vec4{static_cast<float>(wind.x), static_cast<float>(wind.y), speed, 0.f};
|
||||
m_weather.cloud_wind = glm::vec4{static_cast<float>(wind.x), static_cast<float>(wind.y), speed, m_cloud_detail_scale};
|
||||
for (std::size_t i = 0; i < gl::MAX_CLOUD_LAYERS; ++i)
|
||||
{
|
||||
auto &target{m_weather.cloud_layers[i]};
|
||||
@@ -332,8 +332,8 @@ void opengl46_weather::update(opengl46_sky const &Sky, glm::vec3 const &Keylight
|
||||
m_weather.fog_light = glm::vec4{m_sun_share, m_average_transmittance, 0.6f, fog_density()};
|
||||
m_weather.weather_camera = glm::vec4{height, static_cast<float>(std::fmod(time, 100000.0)), m_clouds_drawn ? 1.f : 0.f, m_clouds_drawn ? static_cast<float>(layers) : 0.f};
|
||||
m_weather.weather_sun_direction = glm::vec4{sun, sun.y > -0.02f ? 1.f : 0.f};
|
||||
m_weather.weather_sun_color = glm::vec4{Keycolor, 0.f};
|
||||
m_weather.weather_ambient = glm::vec4{Ambient * 1.3f, 0.f};
|
||||
m_weather.weather_sun_color = glm::vec4{Keycolor, m_cloud_sun_scale};
|
||||
m_weather.weather_ambient = glm::vec4{Ambient * 1.3f, m_cloud_sky_scale};
|
||||
m_weather.fog_volume_params = glm::vec4{0.f, FOG_VOLUME_NEAR, 1.f, 1.f};
|
||||
m_weather.fog_volume_target = glm::vec4{1.f, 1.f, Global.gfx_fog_range, 1.f - Sky.atmosphere_weight()};
|
||||
|
||||
@@ -688,6 +688,9 @@ void opengl46_weather::draw_debug_ui()
|
||||
ImGui::SliderFloat("cloud distance, m (gfx.clouds.distance)", &Global.gfx_clouds_distance, 5000.f, 200000.f, "%.0f", ImGuiSliderFlags_Logarithmic);
|
||||
ImGui::Checkbox("cloud shadows (gfx.clouds.shadows)", &Global.gfx_clouds_shadows);
|
||||
ImGui::SliderFloat("cloud shadow map, m (gfx.clouds.shadows.range)", &Global.gfx_clouds_shadows_range, 1000.f, 100000.f, "%.0f", ImGuiSliderFlags_Logarithmic);
|
||||
ImGui::SliderFloat("cloud sunlight (tuning, not saved)", &m_cloud_sun_scale, 0.25f, 3.f);
|
||||
ImGui::SliderFloat("cloud sky light (tuning, not saved)", &m_cloud_sky_scale, 0.f, 3.f);
|
||||
ImGui::SliderFloat("cloud edge detail (tuning, not saved)", &m_cloud_detail_scale, 0.f, 3.f);
|
||||
ImGui::Checkbox("stars (gfx.stars)", &Global.gfx_stars);
|
||||
ImGui::SliderFloat("star brightness", &Global.gfx_stars_brightness, 0.f, 8.f);
|
||||
ImGui::Text("fog range %.0f m, sun share of the fog light %.2f, clouds let through %.2f on average", m_fog_range, m_sun_share, m_average_transmittance);
|
||||
|
||||
@@ -177,6 +177,11 @@ class opengl46_weather
|
||||
std::optional<gl::buffer> m_stars_buffer;
|
||||
int m_stars_count{0};
|
||||
|
||||
// tuning of the look of the clouds in the debug window, not saved: scales of their sunlight, of their sky light and of the
|
||||
// erosion of their edges by the detail noise (weather_sun_color.w, weather_ambient.w, cloud_wind.w)
|
||||
float m_cloud_sun_scale{1.f};
|
||||
float m_cloud_sky_scale{1.f};
|
||||
float m_cloud_detail_scale{1.f};
|
||||
// what the debug window shows
|
||||
float m_sun_share{0.f};
|
||||
float m_average_transmittance{1.f};
|
||||
|
||||
@@ -14,6 +14,14 @@ const float CLOUD_FILL_EDGE = 0.45;
|
||||
const float CLOUD_FILL_CORE = 0.85;
|
||||
// how fast the density rises inside the edge of a cloud: above 1 the edges are crisper, the inside keeps its density
|
||||
const float CLOUD_EDGE_SHARPNESS = 3.0;
|
||||
// the detail noise: its tile against the tile of the shape noise and how deep it eats into the edges (times the erosion of the
|
||||
// genus and the tuning of the debug window, cloud_wind.w); the finer octave of the thin edges: its tile against the detail tile,
|
||||
// how far the coarser octave pushes its lookup about (in its tiles), and the density below which it is used
|
||||
const float CLOUD_DETAIL_SCALE = 6.0;
|
||||
const float CLOUD_EROSION = 2.0;
|
||||
const float CLOUD_FINE_SCALE = 3.7;
|
||||
const float CLOUD_FINE_PUSH = 0.6;
|
||||
const float CLOUD_FINE_BELOW = 0.6;
|
||||
|
||||
float cloud_remap(float value, float low, float high, float newlow, float newhigh)
|
||||
{
|
||||
@@ -152,12 +160,23 @@ float cloud_layer_density(int index, vec3 position, float height, bool detail)
|
||||
float density = clamp(cloud_remap(base * gradient, 1.0 - fill, 1.0, 0.0, 1.0), 0.0, 1.0) * coverage.x;
|
||||
if (detail && density > 0.0 && layer.shape.w > 0.0)
|
||||
{
|
||||
vec4 small = textureLod(cloud_detail_noise, coords * 6.0, 0.0);
|
||||
vec3 detailcoords = coords * CLOUD_DETAIL_SCALE;
|
||||
vec4 small = textureLod(cloud_detail_noise, detailcoords, 0.0);
|
||||
// spread over 0-1 as the worley octaves of the shape; left in their narrow band they would only thin the cloud evenly
|
||||
float fbm = clamp((small.r * 0.625 + small.g * 0.25 + small.b * 0.125 - 0.30) / 0.35, 0.0, 1.0);
|
||||
// the thin outer part of a cloud gets a finer octave too, its lookup pushed about by the coarser one, so the edges are frayed
|
||||
// into small billows and torn bits rather than evenly rounded. the dense inside is never eaten into, so it is skipped there
|
||||
float fineshare = 1.0 - smoothstep(CLOUD_FINE_BELOW * 0.5, CLOUD_FINE_BELOW, density);
|
||||
if (fineshare > 0.0)
|
||||
{
|
||||
vec3 push = (small.gbr - 0.5) * CLOUD_FINE_PUSH;
|
||||
vec4 fine = textureLod(cloud_detail_noise, detailcoords * CLOUD_FINE_SCALE + push, 0.0);
|
||||
float finefbm = clamp((fine.r * 0.625 + fine.g * 0.25 + fine.b * 0.125 - 0.30) / 0.35, 0.0, 1.0);
|
||||
fbm = clamp(mix(fbm, fbm * 0.65 + finefbm * 0.35, fineshare), 0.0, 1.0);
|
||||
}
|
||||
// wispy at the base, billowing at the top
|
||||
float erosion = mix(fbm, 1.0 - fbm, clamp(h * 4.0, 0.0, 1.0));
|
||||
density = clamp(cloud_remap(density, erosion * layer.shape.w * 0.7, 1.0, 0.0, 1.0), 0.0, 1.0);
|
||||
density = clamp(cloud_remap(density, erosion * layer.shape.w * CLOUD_EROSION * cloud_wind.w, 1.0, 0.0, 1.0), 0.0, 1.0);
|
||||
}
|
||||
return min(density * CLOUD_EDGE_SHARPNESS, 1.0) * layer.shape.y;
|
||||
}
|
||||
|
||||
@@ -25,9 +25,11 @@ layout(location = 6) uniform ivec2 rows;
|
||||
|
||||
// lowest elevation of the panorama (radians); its rows go with the square of the height, denser at the horizon
|
||||
const float PANORAMA_LOW = -0.1;
|
||||
// scales of the light of the clouds against the shading of the surfaces (light_common.glsl: SUN_DIFFUSE_SCALE, AMBIENT_SCALE)
|
||||
// scales of the light of the clouds against the shading of the surfaces (light_common.glsl: SUN_DIFFUSE_SCALE, AMBIENT_SCALE),
|
||||
// times the tuning of the debug window (weather_sun_color.w, weather_ambient.w). the sky light about as the shaded faces get it:
|
||||
// more of it greys the shaded sides of the clouds into a flat pastel
|
||||
const float CLOUD_SUN_SCALE = 1.5;
|
||||
const float CLOUD_AMBIENT_SCALE = 1.0;
|
||||
const float CLOUD_AMBIENT_SCALE = 0.6;
|
||||
// the ground under the clouds lights their bases back with this share of the light falling on it
|
||||
const float CLOUD_GROUND_ALBEDO = 0.2;
|
||||
// how fast the light of the sky fades into a cloud, per optical depth of the cloud below a point, or above it past CLOUD_SKY_REACH
|
||||
@@ -41,6 +43,8 @@ const float CLOUD_SKY_FLOOR = 0.15;
|
||||
// how dense a cloud has to be to scatter the sunlight back at full: the thin edges and wisps of the side lit by the sun, seen with the
|
||||
// sun behind, are darker than its bulk (the "powder" effect: the light takes a few scatterings to turn back towards the view)
|
||||
const float CLOUD_POWDER = 6.0;
|
||||
// how many of the nearest steps towards the sun see the detail noise
|
||||
const int CLOUD_LIGHT_DETAIL_STEPS = 1;
|
||||
|
||||
float henyey_greenstein(float cosangle, float g)
|
||||
{
|
||||
@@ -60,12 +64,12 @@ float cloud_phase(float cosangle, float scale)
|
||||
vec3 cloud_sky_light(float up)
|
||||
{
|
||||
vec3 directional = sky_ambient_sh[1].rgb * (0.488603 * up) - sky_ambient_sh[6].rgb * 0.315392 - sky_ambient_sh[8].rgb * 0.546274;
|
||||
return max(weather_ambient.rgb + directional * 1.3, vec3(0.0)) * CLOUD_AMBIENT_SCALE;
|
||||
return max(weather_ambient.rgb + directional * 1.3, vec3(0.0)) * (CLOUD_AMBIENT_SCALE * weather_ambient.w);
|
||||
}
|
||||
|
||||
// light of the sun reaching a point inside a layer through the cloud towards it, with the light scattered many times
|
||||
// (octaves after Wrenninge), and the phase of the view
|
||||
float cloud_sunlight(int index, vec3 position, float cosangle, int steps, float powder)
|
||||
float cloud_sunlight(int index, vec3 position, float cosangle, int steps, float powder, bool detail)
|
||||
{
|
||||
vec3 sun = weather_sun_direction.xyz;
|
||||
cloud_layer_s layer = cloud_layers[index];
|
||||
@@ -79,7 +83,8 @@ float cloud_sunlight(int index, vec3 position, float cosangle, int steps, float
|
||||
float step = reach * (float(s) + 1.0) / float(steps * (steps + 1) / 2);
|
||||
vec3 point = position + sun * (travelled + 0.5 * step);
|
||||
travelled += step;
|
||||
depth += cloud_layer_density(index, point, cloud_height(point), false) * step;
|
||||
// the nearest steps with the detail noise: the small billows shade one another, lit on top and grey beneath
|
||||
depth += cloud_layer_density(index, point, cloud_height(point), detail && (s < CLOUD_LIGHT_DETAIL_STEPS)) * step;
|
||||
}
|
||||
float light = 0.0;
|
||||
float amount = 1.0;
|
||||
@@ -181,7 +186,7 @@ void main()
|
||||
}
|
||||
|
||||
vec3 ambienttop = cloud_sky_light(1.0);
|
||||
vec3 sunlight = weather_sun_color.rgb * CLOUD_SUN_SCALE * sunup;
|
||||
vec3 sunlight = weather_sun_color.rgb * (CLOUD_SUN_SCALE * weather_sun_color.w) * sunup;
|
||||
// the bases are lit from below by the ground, which the sun lights through the gaps between the clouds
|
||||
vec3 ambientbottom = (weather_sun_color.rgb * max(weather_sun_direction.y, 0.0) * sunup * fog_light.y + ambienttop) * CLOUD_GROUND_ALBEDO;
|
||||
// seen against the sun the thin edges glow (the forward scattering); seen with the sun behind, they are dark
|
||||
@@ -204,7 +209,7 @@ void main()
|
||||
if (density <= 0.0)
|
||||
continue;
|
||||
float powder = mix(1.0, 1.0 - exp(-density / max(layer.shape.y, 1e-6) * CLOUD_POWDER), powderview);
|
||||
float sunshare = (sunup > 0.0) ? cloud_sunlight(index, position, cosangle, lightsteps, powder) : 0.0;
|
||||
float sunshare = (sunup > 0.0) ? cloud_sunlight(index, position, cosangle, lightsteps, powder, detail) : 0.0;
|
||||
// the light of the sky reaches inside through the cloud above, that of the ground through the cloud below: the base of a
|
||||
// thick cloud is darker than its top, and greyer, lit only by the ground and the sky at its sides
|
||||
float column = layer.shape.y * layer.shape.x;
|
||||
|
||||
@@ -44,13 +44,14 @@ layout(std140, binding = WEATHER_UBO_BINDING) uniform weather_ubo
|
||||
vec4 weather_camera;
|
||||
// xyz: world space direction towards the key light (the sun, or the moon at night), w: 1 when it is above the horizon
|
||||
vec4 weather_sun_direction;
|
||||
// rgb: colour of the key light as the shading gets it, without the shadow of the clouds; w: unused
|
||||
// rgb: colour of the key light as the shading gets it, without the shadow of the clouds; w: scale of the sunlight of the clouds
|
||||
vec4 weather_sun_color;
|
||||
// rgb: ambient light of the sky above; w: unused
|
||||
// rgb: ambient light of the sky above; w: scale of the sky light of the clouds
|
||||
vec4 weather_ambient;
|
||||
// xy: centre of the cloud shadow map (world x and z relative to the camera), z: 1 / its size (metres), w: 1 when it holds shadows
|
||||
vec4 cloud_shadow_params;
|
||||
// xy: world x and z of the direction the wind at the clouds blows to (unit), z: its speed, m/s
|
||||
// xy: world x and z of the direction the wind at the clouds blows to (unit), z: its speed, m/s, w: scale of the erosion of the
|
||||
// edges of the clouds by the detail noise
|
||||
vec4 cloud_wind;
|
||||
cloud_layer_s cloud_layers[MAX_CLOUD_LAYERS];
|
||||
// colour of the fog towards the horizon by the angle from the azimuth of the sun, 0 to 180 degrees, in the units of the
|
||||
|
||||
Reference in New Issue
Block a user