stride3d/stride · error · ArgumentOutOfRangeException

LightBufferDownsampleLevel

Error message

LightBufferDownsampleLevel

What it means

In DrawCore, LightShafts validates that both LightBufferDownsampleLevel and BoundingVolumeBufferDownsampleLevel are at least 1, throwing ArgumentOutOfRangeException with the property name when not. Downsample levels of 0 or below would produce degenerate buffers and divide-by-zero scaling, so the renderer fails fast each draw.

Solutions

  1. Set LightBufferDownsampleLevel (and BoundingVolumeBufferDownsampleLevel) to a value >= 1; use 1 for full resolution.
  2. Clamp loaded/configured values: Math.Max(1, level) before assignment.
  3. Note the thrown argument name in the message to identify exactly which of the two properties is invalid.

Example fix

// before
lightShafts.LightBufferDownsampleLevel = 0; // throws on draw
// after
lightShafts.LightBufferDownsampleLevel = Math.Max(1, configuredLevel);
Defensive patterns

Strategy: validation

Validate before calling

if (lightShafts.LightBufferDownsampleLevel < 1) lightShafts.LightBufferDownsampleLevel = 1;
if (lightShafts.BoundingVolumeBufferDownsampleLevel < 1) lightShafts.BoundingVolumeBufferDownsampleLevel = 1;

Type guard

static bool IsValidDownsampleLevel(int v) => v >= 1;

Try / catch

try { DrawLightShafts(context); }
catch (ArgumentOutOfRangeException) { lightShafts.LightBufferDownsampleLevel = 1; }

Prevention

When it happens

Trigger: Setting LightBufferDownsampleLevel to 0 (or negative) on the LightShafts component/renderer — directly in code, in the editor property grid, or via serialization — then rendering a frame where light shafts are collected (lightShafts != null).

Common situations: Assuming 0 means 'no downsampling' (the minimum is 1, meaning full resolution); resetting a component to default int 0 in scripts or factory code before rendering.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/68a49418b49a505a. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Rendering/Rendering/Images/LightShafts/LightShafts.cs:137

        protected override void Destroy()
        {
            base.Destroy();
            minmaxVolumeEffectShader.Dispose();
        }

        public void Collect(RenderContext context)
        {
            lightShafts = context.VisibilityGroup.Tags.Get(CurrentLightShafts);
        }

        protected override void DrawCore(RenderDrawContext context)
        {
            if (lightShafts == null)
                return; // Not collected

            if (LightBufferDownsampleLevel < 1)
                throw new ArgumentOutOfRangeException(nameof(LightBufferDownsampleLevel));
            if (BoundingVolumeBufferDownsampleLevel < 1)
                throw new ArgumentOutOfRangeException(nameof(BoundingVolumeBufferDownsampleLevel));

            var depthInput = GetSafeInput(0);

            // Create a min/max buffer generated from scene bounding volumes
            var targetBoundingBoxBufferSize = new Size2(Math.Max(1, depthInput.Width / BoundingVolumeBufferDownsampleLevel), Math.Max(1, depthInput.Height / BoundingVolumeBufferDownsampleLevel));
            var boundingBoxBuffer = NewScopedRenderTarget2D(targetBoundingBoxBufferSize.Width, targetBoundingBoxBufferSize.Height, PixelFormat.R32G32_Float);

            // Buffer that holds the minimum distance in case of being inside the bounding box
            var backSideRaycastBuffer = NewScopedRenderTarget2D(1, 1, PixelFormat.R32G32_Float);

            // Create a single channel light buffer
            PixelFormat lightBufferPixelFormat = needsColorLightBuffer ? PixelFormat.R16G16B16A16_Float : PixelFormat.R16_Float;
            var targetLightBufferSize = new Size2(Math.Max(1, depthInput.Width / LightBufferDownsampleLevel), Math.Max(1, depthInput.Height / LightBufferDownsampleLevel));
            var lightBuffer = NewScopedRenderTarget2D(targetLightBufferSize.Width, targetLightBufferSize.Height, lightBufferPixelFormat);
            lightShaftsEffectShader.SetOutput(lightBuffer);
            var lightShaftsParameters = lightShaftsEffectShader.Parameters;

View on GitHub (pinned to 96fad776d2)