Skip to content

Commit 4a403ab

Browse files
committed
WIP: fix empty-space skipping
1 parent 2461cbc commit 4a403ab

1 file changed

Lines changed: 30 additions & 10 deletions

File tree

Editor/Resources/Shaders/VolumetricClouds.glsl

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -417,19 +417,25 @@ void main()
417417
float firstHitDistance = LUX_CLOUD_MAX_DEPTH;
418418
float lastHitDistance = LUX_CLOUD_MAX_DEPTH;
419419

420-
// Empty-space skipping: when we hit a void, take larger steps until we
421-
// re-enter cloud, then refine.
420+
// Empty-space skipping: stride through voids with large steps; when we
421+
// re-enter cloud while striding, rewind and resume at fine resolution so the
422+
// boundary isn't overshot. 't' is accumulated (NOT derived from the loop
423+
// index) so step lengths can vary, and density is only ever integrated on a
424+
// fine (1x) step — the integration distance therefore always equals the
425+
// sample spacing, keeping the scattering energy-conserving. 'marchSteps' sets
426+
// the fine step length (cloud sampling density); the loop index is only a
427+
// safety bound so a noisy boundary can't spin forever.
428+
const float kEmptyStepScale = 2.0;
422429
int emptySteps = 0;
430+
float t = traceStart + jitter * baseStepLength;
423431

424-
for (uint i = 0u; i < 128u; i++)
432+
for (uint i = 0u; i < 256u; i++)
425433
{
426-
if (i >= marchSteps || transmittance < 0.01)
434+
if (transmittance < 0.01 || t >= traceEnd)
427435
break;
428436

429-
float stepScale = emptySteps > 2 ? 2.0 : 1.0;
430-
float t = traceStart + (float(i) + jitter) * baseStepLength;
431-
if (t >= traceEnd)
432-
break;
437+
float stepScale = emptySteps > 2 ? kEmptyStepScale : 1.0;
438+
float stepLength = baseStepLength * stepScale;
433439

434440
vec3 samplePosition = cameraPosition + viewDirection * t;
435441
float lod = GetCloudLODFactor(t);
@@ -438,6 +444,17 @@ void main()
438444
if (density <= LUX_CLOUD_MIN_DENSITY)
439445
{
440446
emptySteps++;
447+
t += stepLength;
448+
continue;
449+
}
450+
451+
// Re-entered cloud on a coarse stride: rewind to the last empty position
452+
// and re-approach finely instead of integrating the coarse step.
453+
if (stepScale > 1.0)
454+
{
455+
emptySteps = 0;
456+
t -= stepLength; // back to the last known-empty sample
457+
t += baseStepLength; // ...and step in at fine resolution
441458
continue;
442459
}
443460
emptySteps = 0;
@@ -473,13 +490,16 @@ void main()
473490
vec3 ambient = ambientSky * (0.4 + 0.6 * heightFraction);
474491
vec3 luminance = (sunLuminance * powder * scatterMul + ambient) * albedo;
475492

476-
// Energy-conserving scattering integration (Hillaire).
493+
// Energy-conserving scattering integration (Hillaire). Reached only on a
494+
// fine step (stepScale == 1), so stepLength == baseStepLength and the
495+
// integration distance matches the sample spacing.
477496
float sigmaT = density * extinction;
478-
float stepLength = baseStepLength * stepScale;
479497
float stepTransmittance = exp(-sigmaT * stepLength);
480498
vec3 integScatter = (luminance * density - luminance * density * stepTransmittance) / max(sigmaT, 1.0e-5);
481499
scatteredLight += transmittance * integScatter;
482500
transmittance *= stepTransmittance;
501+
502+
t += stepLength;
483503
}
484504

485505
float rawAlpha = clamp((1.0 - transmittance) * distanceFade, 0.0, 1.0);

0 commit comments

Comments
 (0)