stride3d/stride · error · ArgumentOutOfRangeException
BoundingVolumeBufferDownsampleLevel
Error message
BoundingVolumeBufferDownsampleLevel
What it means
LightShafts validates that the bounding-volume buffer downsample level is at least 1 before using it as a divisor for render target dimensions. A value of 0 (or negative) would produce a zero/negative buffer size or division by zero, so the renderer throws ArgumentOutOfRangeException in DrawCore.
Solutions
- Set BoundingVolumeBufferDownsampleLevel to 1 (full resolution) or higher
- Clamp the value with Math.Max(1, value) when configuring the component
- Check any serialized/UI code that can write 0 into this property
Example fix
// before lightShafts.BoundingVolumeBufferDownsampleLevel = 0; // after lightShafts.BoundingVolumeBufferDownsampleLevel = Math.Max(1, requestedLevel);
Defensive patterns
Strategy: validation
Validate before calling
if (lightShafts.BoundingVolumeBufferDownsampleLevel < 1)
throw new ArgumentException("BoundingVolumeBufferDownsampleLevel must be >= 1"); Prevention
- Never use 0 as a 'disabled' sentinel for downsample levels
- Clamp serialized values on load with Math.Max(1, v)
- Test rendering with freshly added LightShaft components
When it happens
Trigger: Setting LightShaftsComponent.BoundingVolumeBufferDownsampleLevel to 0 or a negative value (e.g. defaulting it from a serialized 0 int field) and then rendering a frame with light shafts enabled.
Common situations: A newly added component whose downsample property was never initialized, or a user setting the level to 0 believing it means 'no downsampling' when 1 actually means full resolution.
Related errors
- lightShaft.SampleCount
- Unsupported format [ ] (must be not none, compressed…
- ArgumentOutOfRangeException
- ArgumentOutOfRangeException
- Asked for " + i + " but no more than 10 default textures…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/f54ad90f84d53a74.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Rendering/Rendering/Images/LightShafts/LightShafts.cs:139
{
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;
lightShaftsParameters.Set(DepthBaseKeys.DepthStencil, depthInput); // Bind scene depth
View on GitHub (pinned to 96fad776d2)