{"record":{"id":"b3e3e2f58814c477","repo":"BabylonJS/Babylon.js","slug":"sample2drgbatoref-data-length-data-length-is","errorCode":null,"errorMessage":"Sample2DRgbaToRef: data length (${data.length}) is less than required (${expectedLength}).","messagePattern":"Sample2DRgbaToRef: data length \\((.+?)\\) is less than required \\((.+?)\\)\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/addons/src/atmosphere/sampling.ts","lineNumber":51,"sourceCode":" * @param normalizeFunc - The function to normalize the texel values. Default is to divide by 255. Pass null for no normalization.\r\n * @returns The result color.\r\n */\r\nexport function Sample2DRgbaToRef<T extends IColor4Like>(\r\n    u: number,\r\n    v: number,\r\n    widthPx: number,\r\n    heightPx: number,\r\n    data: Uint8Array | Uint16Array | Float32Array,\r\n    result: T,\r\n    normalizeFunc: ((value: number) => number) | null = DefaultNormalize\r\n): T {\r\n    if (widthPx <= 0 || heightPx <= 0) {\r\n        throw new Error(\"Sample2DRgbaToRef: widthPx and heightPx must be positive.\");\r\n    }\r\n\r\n    const expectedLength = widthPx * heightPx * 4;\r\n    if (data.length < expectedLength) {\r\n        throw new Error(`Sample2DRgbaToRef: data length (${data.length}) is less than required (${expectedLength}).`);\r\n    }\r\n\r\n    // Default to clamping behavior, but could support others.\r\n    u = Clamp(u);\r\n    v = Clamp(v);\r\n\r\n    // Compute 4 nearest neighbor texels.\r\n    const fractionalTexelX = Math.max(u * widthPx - 0.5, 0);\r\n    const fractionalTexelY = Math.max(v * heightPx - 0.5, 0);\r\n    const xLeft = Math.floor(fractionalTexelX);\r\n    const xRight = Math.min(xLeft + 1, widthPx - 1);\r\n    const yBottom = Math.floor(fractionalTexelY);\r\n    const yTop = Math.min(yBottom + 1, heightPx - 1);\r\n\r\n    // Sample nearest neighbor texels.\r\n    const lowerLeftColor = TexelFetch2DRgbaToRef(xLeft, yBottom, widthPx, heightPx, data, TmpColor1, normalizeFunc);\r\n    const upperLeftColor = TexelFetch2DRgbaToRef(xLeft, yTop, widthPx, heightPx, data, TmpColor2, normalizeFunc);\r\n    const lowerRightColor = TexelFetch2DRgbaToRef(xRight, yBottom, widthPx, heightPx, data, TmpColor3, normalizeFunc);\r","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/addons/src/atmosphere/sampling.ts#L33-L69","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst data = new Float32Array(lut.width * lut.height * 3); // wrong: RGB\nsample.Sample2DRgbaToRef(u, v, lut.width, lut.height, data, out);\n// after\nconst data = new Float32Array(lut.width * lut.height * 4); // RGBA\nsample.Sample2DRgbaToRef(u, v, lut.width, lut.height, data, out);","handlingStrategy":"validation","validationCode":"const required = lut.width * lut.height * 4;\nif (data.length < required) {\n  throw new Error(`LUT buffer too small: ${data.length} < ${required}`);\n}","typeGuard":"function isFullLutBuffer(data: ArrayBufferView, w: number, h: number): boolean {\n  return data.byteLength / (data instanceof Float32Array || data instanceof Uint16Array ? (data instanceof Float32Array ? 4 : 2) : 1) >= w * h * 4;\n}","tryCatchPattern":"try {\n  Sample2DRgbaToRef(u, v, w, h, data, out);\n} catch (e) {\n  if (String(e).includes(\"data length\")) {\n    data = new Float32Array(w * h * 4); // reallocate and re-read LUT\n  } else throw e;\n}","preventionTips":["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."],"tags":["sampling","buffer-size","atmosphere","lut","argument-validation"],"backgroundTag":"buffer-size-mismatch","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}