17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-28 19:17:28 +01:00

Shade the volumetric clouds by the cloud over each point, not by the density at it

This commit is contained in:
2026-10-17 17:24:51 +02:00
parent 27e5c07837
commit 22bf015939
2 changed files with 26 additions and 4 deletions

View File

@@ -13,7 +13,7 @@ const float CLOUD_EARTH_RADIUS = 6360000.0;
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 = 2.0;
const float CLOUD_EDGE_SHARPNESS = 3.0;
float cloud_remap(float value, float low, float high, float newlow, float newhigh)
{

View File

@@ -30,8 +30,14 @@ const float CLOUD_SUN_SCALE = 1.5;
const float CLOUD_AMBIENT_SCALE = 1.0;
// 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 above (or below) a point
// 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
const float CLOUD_AMBIENT_FADE = 0.05;
// the part of the cloud over a point looked at for the sky light held back (cloud_sky_depth), metres, how fast the light fades
// per optical depth there (less than the extinction: the light scattered many times gets through further), and the share left
// in the darkest places
const float CLOUD_SKY_REACH = 400.0;
const float CLOUD_SKY_FADE = 0.25;
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;
@@ -89,6 +95,20 @@ float cloud_sunlight(int index, vec3 position, float cosangle, int steps, float
return light;
}
// optical depth of the cloud over a point up to Reach above it, from Samples of the coarse density: under a lump and deep in a
// thick cloud the sky light is held back, at the tops and the thin edges it is not, so the shaded sides take the form of the cloud
float cloud_sky_depth(int index, vec3 position, float height, float reach, int samples)
{
float depth = 0.0;
for (int s = 0; s < samples; s++)
{
// up along the vertical: the height grows by the same distance (cloud_height bends only with the horizontal distance)
float up = reach * (float(s) + 0.5) / float(samples);
depth += cloud_layer_density(index, position + vec3(0.0, up, 0.0), height + up, false);
}
return depth * reach / float(samples);
}
float interleaved_noise(vec2 pixel)
{
return fract(52.9829189 * fract(dot(pixel, vec2(0.06711056, 0.00583715))));
@@ -124,6 +144,7 @@ void main()
float maxdistance = quality.z;
int maxsteps = int(quality.x);
int lightsteps = int(quality.y);
int skysteps = (lightsteps >= 4) ? 2 : 1;
bool detail = quality.w > 0.5;
float jitter = fract(interleaved_noise(vec2(texel)) + float(frame) * 0.618034);
@@ -187,9 +208,10 @@ void main()
// 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;
float above = column * (layer.heights.y - height);
float reach = min(layer.heights.y - height, CLOUD_SKY_REACH);
float sky = exp(-CLOUD_SKY_FADE * cloud_sky_depth(index, position, height, reach, skysteps) - CLOUD_AMBIENT_FADE * column * (layer.heights.y - height - reach));
float below = column * (height - layer.heights.x);
vec3 light = sunlight * sunshare + (ambienttop * mix(0.15, 1.0, exp(-CLOUD_AMBIENT_FADE * above)) + ambientbottom * exp(-CLOUD_AMBIENT_FADE * below)) * powder;
vec3 light = sunlight * sunshare + (ambienttop * mix(CLOUD_SKY_FLOOR, 1.0, sky) + ambientbottom * exp(-CLOUD_AMBIENT_FADE * below));
float through = exp(-density * step);
vec3 inscattered = light * (1.0 - through);
scattered += transmittance * inscattered;