BabylonJS/Babylon.js · error · Error
Sample2DRgbaToRef: data length (${data.length}) is less than
Error message
Sample2DRgbaToRef: data length (${data.length}) is less than required (${expectedLength}). What it means
After validating dimensions, Sample2DRgbaToRef checks that the supplied pixel buffer holds at least widthPx*heightPx*4 elements (RGBA, 4 components per pixel). A shorter array would cause out-of-bounds reads, so it throws. This indicates the data array does not match the declared LUT size.
Source
Thrown at packages/dev/addons/src/atmosphere/sampling.ts:51
* @param normalizeFunc - The function to normalize the texel values. Default is to divide by 255. Pass null for no normalization.
* @returns The result color.
*/
export function Sample2DRgbaToRef<T extends IColor4Like>(
u: number,
v: number,
widthPx: number,
heightPx: number,
data: Uint8Array | Uint16Array | Float32Array,
result: T,
normalizeFunc: ((value: number) => number) | null = DefaultNormalize
): T {
if (widthPx <= 0 || heightPx <= 0) {
throw new Error("Sample2DRgbaToRef: widthPx and heightPx must be positive.");
}
const expectedLength = widthPx * heightPx * 4;
if (data.length < expectedLength) {
throw new Error(`Sample2DRgbaToRef: data length (${data.length}) is less than required (${expectedLength}).`);
}
// Default to clamping behavior, but could support others.
u = Clamp(u);
v = Clamp(v);
// Compute 4 nearest neighbor texels.
const fractionalTexelX = Math.max(u * widthPx - 0.5, 0);
const fractionalTexelY = Math.max(v * heightPx - 0.5, 0);
const xLeft = Math.floor(fractionalTexelX);
const xRight = Math.min(xLeft + 1, widthPx - 1);
const yBottom = Math.floor(fractionalTexelY);
const yTop = Math.min(yBottom + 1, heightPx - 1);
// Sample nearest neighbor texels.
const lowerLeftColor = TexelFetch2DRgbaToRef(xLeft, yBottom, widthPx, heightPx, data, TmpColor1, normalizeFunc);
const upperLeftColor = TexelFetch2DRgbaToRef(xLeft, yTop, widthPx, heightPx, data, TmpColor2, normalizeFunc);
const lowerRightColor = TexelFetch2DRgbaToRef(xRight, yBottom, widthPx, heightPx, data, TmpColor3, normalizeFunc);
View on GitHub (pinned to 0592b347b8)
Solutions
- Ensure the buffer is allocated as widthPx*heightPx*4 with the same component count (RGBA) as the texture format.
- Re-read/regenerate the LUT data after changing resolution; never reuse a stale buffer across size changes.
- Pre-check `data.length >= width*height*4` at the call site and reallocate if too small.
Example fix
// before const data = new Float32Array(lut.width * lut.height * 3); // wrong: RGB sample.Sample2DRgbaToRef(u, v, lut.width, lut.height, data, out); // after const data = new Float32Array(lut.width * lut.height * 4); // RGBA sample.Sample2DRgbaToRef(u, v, lut.width, lut.height, data, out);
Defensive patterns
Strategy: validation
Validate before calling
const required = lut.width * lut.height * 4;
if (data.length < required) {
throw new Error(`LUT buffer too small: ${data.length} < ${required}`);
} Type guard
function isFullLutBuffer(data: ArrayBufferView, w: number, h: number): boolean {
return data.byteLength / (data instanceof Float32Array || data instanceof Uint16Array ? (data instanceof Float32Array ? 4 : 2) : 1) >= w * h * 4;
} Try / catch
try {
Sample2DRgbaToRef(u, v, w, h, data, out);
} catch (e) {
if (String(e).includes("data length")) {
data = new Float32Array(w * h * 4); // reallocate and re-read LUT
} else throw e;
} Prevention
- Allocate LUT readback buffers with RGBA (x4) sizing matching the texture format.
- Regenerate buffers whenever LUT resolution changes.
- Centralize buffer allocation in one helper so format and size stay in sync.
When it happens
Trigger: Calling Sample2DRgbaToRef (or the LUT helpers using it) with a Uint8Array/Uint16Array/Float32Array shorter than widthPx*heightPx*4 — e.g. reading back a partial texture buffer, wrong texture type (RGB instead of RGBA), or mismatched width/height values.
Common situations: Downloading LUT data with the wrong format (RGB instead of RGBA), reusing a buffer from a differently sized LUT after changing transmittance/multiscattering resolution, slicing a texture readback buffer.
Related errors
- Sample2DRgbaToRef: widthPx and heightPx must be positive.
- Atmosphere is not supported on WebGL ${engine.version}.
- Atmosphere only supports one light source currently.
- Depth texture is required for aerial perspective compositor.
- The provided canvas is null or undefined.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/b3e3e2f58814c477.
Report an issue: GitHub.