feat(texture): add 2D texture array creation and image-source population#422
Open
ryantrem wants to merge 4 commits into
Open
feat(texture): add 2D texture array creation and image-source population#422ryantrem wants to merge 4 commits into
ryantrem wants to merge 4 commits into
Conversation
Adds a tree-shakable, zero-side-effect texture-array module — the Lite analog of BJS RawTexture2DArray, with the image-population path both engines lack. Exposes createTexture2DArray, uploadImageToArrayLayer, loadImageToArrayLayer, and createTexture2DArrayFromUrls, backed by WebGPU copyExternalImageToTexture (per-layer origin), so ImageBitmap, ImageData, canvas, and video sources all work with no branching. Covered by 12 unit tests. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ace1149-800d-4bb4-a84d-15780ea0a0d5
Document that consuming a Texture2DArray requires a custom shader and show the full path: build the array, declare a 2d-array sampler on a ShaderMaterial, and sample a chosen layer in WGSL. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ace1149-800d-4bb4-a84d-15780ea0a0d5
API ChangesAPI Extractor detected public API changes for No removed public API lines were detected; this appears to be additive. API Extractor diffdiff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index 0910ad69..76e4b7cd 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -365,6 +365,12 @@ export interface ArcRotateInterpolationOptions {
interpolationFactor?: number;
}
+// @public
+export interface ArrayLayerUploadOptions {
+ invertY?: boolean;
+ premultiplyAlpha?: boolean;
+}
+
// @public
export interface AssetContainer {
animationGroups?: AnimationGroup[];
@@ -1607,6 +1613,12 @@ export function createTextRenderable(data: TextData, options?: TextRenderableOpt
// @public
export function createTextRenderer(surface: SurfaceContext, opts: TextRendererOptions): TextRenderer;
+// @public
+export function createTexture2DArray(engine: EngineContext, width: number, height: number, layers: number, options?: TextureArrayOptions): Texture2DArray;
+
+// @public
+export function createTexture2DArrayFromUrls(engine: EngineContext, urls: readonly [string, ...string[]], options?: TextureArrayOptions): Promise<Texture2DArray>;
+
// @public
export function createTexture2DFromPixels(engine: EngineContext, data: Uint8Array, width: number, height: number, options?: PixelsTexture2DOptions): Texture2D;
@@ -2989,6 +3001,9 @@ export function loadGltf(engine: EngineContext, source: string | ArrayBuffer | B
// @public
export function loadHdrEnvironment(scene: SceneContext, url: string, options?: HdrLoadOptions): Promise<EnvironmentTextures>;
+// @public
+export function loadImageToArrayLayer(engine: EngineContext, tex: Texture2DArray, layer: number, url: string, opts?: ArrayLayerUploadOptions): Promise<void>;
+
// @public
export function loadKtx2Texture2D(engine: EngineContext, url: string, sRGB?: boolean): Promise<Texture2D>;
@@ -5996,6 +6011,12 @@ export interface Texture2D {
width: number;
}
+// @public
+export interface Texture2DArray extends Texture2D {
+ // (undocumented)
+ layers: number;
+}
+
// @public
export interface Texture2DOptions {
addressModeU?: GPUAddressMode;
@@ -6013,6 +6034,16 @@ export type Texture3D = Texture2D & {
depth: number;
};
+// @public
+export interface TextureArrayOptions {
+ addressModeU?: GPUAddressMode;
+ addressModeV?: GPUAddressMode;
+ magFilter?: GPUFilterMode;
+ minFilter?: GPUFilterMode;
+ mipMaps?: boolean;
+ srgb?: boolean;
+}
+
// @public
export interface ThicknessProps {
max?: number;
@@ -6262,6 +6293,9 @@ export function updateTextData(data: TextData, update: TextDataUpdate): void;
// @public
export function updateTexture2DFromPixels(engine: EngineContext, tex: Texture2D, data: Uint8Array, x?: number, y?: number, width?: number, height?: number): void;
+// @public
+export function uploadImageToArrayLayer(engine: EngineContext, tex: Texture2DArray, layer: number, source: GPUCopyExternalImageSource, opts?: ArrayLayerUploadOptions): void;
+
// @public
export interface UtilityLayer {
// (undocumented) |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ace1149-800d-4bb4-a84d-15780ea0a0d5
API ChangesAPI Extractor detected public API changes for No removed public API lines were detected; this appears to be additive. API Extractor diffdiff --git a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
index 0910ad69..76e4b7cd 100644
--- a/home/vsts/work/1/s/test-results/api-report/target/temp/babylon-lite.api.md
+++ b/home/vsts/work/1/s/test-results/api-report/current/temp/babylon-lite.api.md
@@ -365,6 +365,12 @@ export interface ArcRotateInterpolationOptions {
interpolationFactor?: number;
}
+// @public
+export interface ArrayLayerUploadOptions {
+ invertY?: boolean;
+ premultiplyAlpha?: boolean;
+}
+
// @public
export interface AssetContainer {
animationGroups?: AnimationGroup[];
@@ -1607,6 +1613,12 @@ export function createTextRenderable(data: TextData, options?: TextRenderableOpt
// @public
export function createTextRenderer(surface: SurfaceContext, opts: TextRendererOptions): TextRenderer;
+// @public
+export function createTexture2DArray(engine: EngineContext, width: number, height: number, layers: number, options?: TextureArrayOptions): Texture2DArray;
+
+// @public
+export function createTexture2DArrayFromUrls(engine: EngineContext, urls: readonly [string, ...string[]], options?: TextureArrayOptions): Promise<Texture2DArray>;
+
// @public
export function createTexture2DFromPixels(engine: EngineContext, data: Uint8Array, width: number, height: number, options?: PixelsTexture2DOptions): Texture2D;
@@ -2989,6 +3001,9 @@ export function loadGltf(engine: EngineContext, source: string | ArrayBuffer | B
// @public
export function loadHdrEnvironment(scene: SceneContext, url: string, options?: HdrLoadOptions): Promise<EnvironmentTextures>;
+// @public
+export function loadImageToArrayLayer(engine: EngineContext, tex: Texture2DArray, layer: number, url: string, opts?: ArrayLayerUploadOptions): Promise<void>;
+
// @public
export function loadKtx2Texture2D(engine: EngineContext, url: string, sRGB?: boolean): Promise<Texture2D>;
@@ -5996,6 +6011,12 @@ export interface Texture2D {
width: number;
}
+// @public
+export interface Texture2DArray extends Texture2D {
+ // (undocumented)
+ layers: number;
+}
+
// @public
export interface Texture2DOptions {
addressModeU?: GPUAddressMode;
@@ -6013,6 +6034,16 @@ export type Texture3D = Texture2D & {
depth: number;
};
+// @public
+export interface TextureArrayOptions {
+ addressModeU?: GPUAddressMode;
+ addressModeV?: GPUAddressMode;
+ magFilter?: GPUFilterMode;
+ minFilter?: GPUFilterMode;
+ mipMaps?: boolean;
+ srgb?: boolean;
+}
+
// @public
export interface ThicknessProps {
max?: number;
@@ -6262,6 +6293,9 @@ export function updateTextData(data: TextData, update: TextDataUpdate): void;
// @public
export function updateTexture2DFromPixels(engine: EngineContext, tex: Texture2D, data: Uint8Array, x?: number, y?: number, width?: number, height?: number): void;
+// @public
+export function uploadImageToArrayLayer(engine: EngineContext, tex: Texture2DArray, layer: number, source: GPUCopyExternalImageSource, opts?: ArrayLayerUploadOptions): void;
+
// @public
export interface UtilityLayer {
// (undocumented) |
Lite Playground - Static SiteBuild 20260716.11 - merge @ a8a2d0b |
Lab - Static SiteBuild 20260716.11 - merge @ a8a2d0b |
ryantrem
enabled auto-merge (squash)
July 17, 2026 01:57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a tree-shakable convenience layer for 2D texture arrays in Babylon Lite — the missing feature called out in the forum for populating a
texture_2d_arraydirectly from image assets (ImageBitmap,ImageData, canvas, video, or URL), without the "draw to an offscreen canvas and read back raw bytes" workaround.Forum context:
What''s added
New free functions in
packages/babylon-lite/src/texture/texture-array.ts:createTexture2DArray(engine, width, height, layers, options?)— allocate an empty N-layer RGBA8 array.uploadImageToArrayLayer(engine, tex, layer, source, opts?)— fill one layer from any WebGPU external-image source via a singlecopyExternalImageToTexture.loadImageToArrayLayer(engine, tex, layer, url, opts?)— fetch + decode a URL into a layer.createTexture2DArrayFromUrls(engine, urls, options?)— build a full array from image URLs.urlsis a tuplereadonly [string, ...string[]], so at-least-one-URL is enforced at compile time with zero runtime cost.The returned
Texture2DArray extends Texture2D, so it drops straight into existing texture bindings.Tree-shaking
The whole feature is free functions with zero module-level side effects — an app that never touches texture arrays strips it entirely, and one that already holds an
ImageBitmapnever bundles the URL-fetch path.Consuming a texture array
There is no built-in material that samples an array layer, so consumption goes through a custom shader. The
texture-array.tsheader doc includes a full@example: build the array, declare aviewDimension: "2d-array"sampler on aShaderMaterial, and sample a chosen layer in WGSL viatextureSample(atlas, atlasSampler, uv, i32(shaderUniforms.layer)).Testing
tests/lite/unit/texture-array.test.ts(creation, per-layer upload, URL loading, dimension validation, compile-time non-empty tuple guard).packages/babylon-lite/src/index.ts.All agent-allowed tests (build + parity) and lint pass. No bundle-size ceiling, golden-reference, or MAD-parity changes.