@flighthq/texture 0.2.1-next.841.373388f → 0.3.0-next.1032.e2b99fc

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,13 @@
1
- import type { Matrix3Like, VideoResource, VideoTexture, VideoTextureLike } from '@flighthq/types';
2
- export declare function advanceVideoTexture(videoTexture: VideoTextureLike): number;
3
- export declare function cloneVideoTexture(source: Readonly<VideoTextureLike>): VideoTexture;
4
- export declare function copyVideoTexture(out: VideoTextureLike, source: Readonly<VideoTextureLike>): void;
5
- export declare function createVideoTexture(source: VideoResource, opts?: Readonly<Partial<VideoTextureLike>>): VideoTexture;
6
- export declare function getVideoTextureHeight(videoTexture: Readonly<VideoTextureLike>): number;
7
- export declare function getVideoTextureInverseUvMatrix(out: Matrix3Like, videoTexture: Readonly<VideoTextureLike>): void;
8
- export declare function getVideoTextureUvMatrix(out: Matrix3Like, videoTexture: Readonly<VideoTextureLike>): void;
9
- export declare function getVideoTextureWidth(videoTexture: Readonly<VideoTextureLike>): number;
10
- export declare function isVideoTextureFrameReady(videoTexture: Readonly<VideoTextureLike>): boolean;
11
- export declare function resetVideoTextureFrame(videoTexture: VideoTextureLike): void;
12
- export declare function setVideoTextureSource(videoTexture: VideoTextureLike, source: VideoResource): void;
1
+ import type { Matrix3Like, Texture, TextureLike, VideoResource } from '@flighthq/types/contract';
2
+ export declare function advanceVideoTexture(texture: TextureLike): number;
3
+ export declare function cloneVideoTexture(source: Readonly<TextureLike>): Texture;
4
+ export declare function copyVideoTexture(out: TextureLike, source: Readonly<TextureLike>): void;
5
+ export declare function createVideoTexture(source: VideoResource, opts?: Readonly<Partial<TextureLike>>): Texture;
6
+ export declare function getVideoTextureHeight(texture: Readonly<TextureLike>): number;
7
+ export declare function getVideoTextureInverseUvMatrix(out: Matrix3Like, texture: Readonly<TextureLike>): void;
8
+ export declare function getVideoTextureUvMatrix(out: Matrix3Like, texture: Readonly<TextureLike>): void;
9
+ export declare function getVideoTextureWidth(texture: Readonly<TextureLike>): number;
10
+ export declare function isVideoTextureFrameReady(texture: Readonly<TextureLike>): boolean;
11
+ export declare function resetVideoTextureFrame(texture: TextureLike): void;
12
+ export declare function setVideoTextureSource(texture: TextureLike, source: VideoResource): void;
13
13
  //# sourceMappingURL=videoTexture.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"videoTexture.d.ts","sourceRoot":"","sources":["../src/videoTexture.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AASlG,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,gBAAgB,GAAG,MAAM,CAG1E;AAMD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY,CAYlF;AAKD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,EAAE,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAgBhG;AAKD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,GAAG,YAAY,CAYlH;AAKD,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAGtF;AAKD,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAG/G;AAMD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAExG;AAID,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAGrF;AAKD,wBAAgB,wBAAwB,CAAC,YAAY,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,OAAO,CAK1F;AAID,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAE3E;AAID,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,gBAAgB,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAGjG"}
1
+ {"version":3,"file":"videoTexture.d.ts","sourceRoot":"","sources":["../src/videoTexture.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAOhH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAOhE;AAGD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,OAAO,CAExE;AAGD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,CAEtF;AAKD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,GAAG,OAAO,CAOxG;AAGD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,MAAM,CAG5E;AAGD,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,CAGrG;AAGD,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,CAE9F;AAGD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,MAAM,CAG3E;AAGD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,OAAO,CAKhF;AAGD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAIjE;AAID,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAIvF"}
@@ -1,113 +1,98 @@
1
- import { createEntity } from '@flighthq/entity';
2
- import { cloneVector2, copyVector2, createVector2, inverseMatrix3 } from '@flighthq/geometry';
3
- import { cloneSampler, copySampler, createSampler } from './sampler';
4
- import { getTextureUvMatrix } from './texture';
5
- // Marks a fresh decoded frame as available for upload by bumping `frameId`. A driver calls this once
6
- // per rendered frame when the backing element reports new pixels (readyState advanced, or a
7
- // requestVideoFrameCallback fired); the GPU uploader compares the id against the one it last uploaded
8
- // and re-uploads only on a change, so a paused stream costs no upload. Returns the new id.
9
- export function advanceVideoTexture(videoTexture) {
10
- videoTexture.frameId += 1;
11
- return videoTexture.frameId;
1
+ import { createEntity } from '@flighthq/entity/contract';
2
+ import { inverseMatrix3 } from '@flighthq/geometry/contract';
3
+ import { VideoTextureBackingKind } from '@flighthq/types/contract';
4
+ import { cloneTexture, copyTexture, createTexture, getTextureUvMatrix } from './texture';
5
+ // Marks a fresh decoded frame on a video-backed Texture. The ImageResource is the shared CPU-origin
6
+ // backing and owns the upload revision; Texture.version mirrors it as the sampled object's dirty-bit.
7
+ export function advanceVideoTexture(texture) {
8
+ const image = texture.storage.image;
9
+ if (image == null)
10
+ return texture.version;
11
+ updateVideoImageSize(image);
12
+ image.version = (image.version + 1) >>> 0;
13
+ texture.version = image.version;
14
+ return texture.version;
12
15
  }
13
- // Allocates an independent VideoTexture over the SAME video stream: the VideoResource reference is
14
- // shared (an HTMLVideoElement cannot be duplicated), while the Sampler and uv-transform vectors are
15
- // deep-cloned so two textures over one stream sample independently. `frameId` resets to -1 so the
16
- // clone forces its own first upload.
16
+ // Clones sampling/UV state while sharing the borrowed video ImageResource and its upload cache key.
17
17
  export function cloneVideoTexture(source) {
18
- return createEntity({
19
- colorSpace: source.colorSpace,
20
- flipX: source.flipX,
21
- flipY: source.flipY,
22
- frameId: -1,
23
- sampler: cloneSampler(source.sampler),
24
- source: source.source,
25
- uvOffset: cloneVector2(source.uvOffset),
26
- uvRotation: source.uvRotation,
27
- uvScale: cloneVector2(source.uvScale),
28
- });
18
+ return cloneTexture(source);
29
19
  }
30
- // Copies every VideoTexture field from source into out in place. The VideoResource reference is
31
- // shared; the Sampler and uv-transform vectors are copied into out's existing entities. Safe when out
32
- // aliases source.
20
+ // Copies a video-backed Texture through the universal Texture field copier.
33
21
  export function copyVideoTexture(out, source) {
34
- const colorSpace = source.colorSpace;
35
- const flipX = source.flipX;
36
- const flipY = source.flipY;
37
- const frameId = source.frameId;
38
- const src = source.source;
39
- const uvRotation = source.uvRotation;
40
- copySampler(out.sampler, source.sampler);
41
- copyVector2(out.uvOffset, source.uvOffset);
42
- copyVector2(out.uvScale, source.uvScale);
43
- out.colorSpace = colorSpace;
44
- out.flipX = flipX;
45
- out.flipY = flipY;
46
- out.frameId = frameId;
47
- out.source = src;
48
- out.uvRotation = uvRotation;
22
+ copyTexture(out, source);
49
23
  }
50
- // Builds a VideoTexture over a VideoResource: a default Sampler, 'srgb' color space (video is
51
- // display-referred), an identity KHR_texture_transform, and `frameId` -1 (no frame uploaded yet).
52
- // Pass VideoTextureLike fields to override any of these.
24
+ // Wraps a VideoResource's borrowed host element in an ImageResource backing and returns the same
25
+ // universal Texture type used by still images and render targets. The all-ones initial revision
26
+ // preserves the former first advanceVideoTexture result of 0 after u32 wrap.
53
27
  export function createVideoTexture(source, opts) {
54
- return createEntity({
55
- colorSpace: opts?.colorSpace ?? 'srgb',
56
- flipX: opts?.flipX ?? false,
57
- flipY: opts?.flipY ?? false,
58
- frameId: opts?.frameId ?? -1,
59
- sampler: opts?.sampler ? cloneSampler(opts.sampler) : createSampler(),
60
- source: opts?.source ?? source,
61
- uvOffset: opts?.uvOffset ? cloneVector2(opts.uvOffset) : createVector2(0, 0),
62
- uvRotation: opts?.uvRotation ?? 0,
63
- uvScale: opts?.uvScale ? cloneVector2(opts.uvScale) : createVector2(1, 1),
28
+ const image = createVideoImageResource(source);
29
+ return createTexture({
30
+ ...opts,
31
+ storage: { dimension: '2d', image },
32
+ version: image?.version ?? INITIAL_VIDEO_VERSION,
64
33
  });
65
34
  }
66
- // Returns the pixel height of the current video frame, or -1 when no element is attached or no frame
67
- // has decoded yet (videoHeight is 0). Reads the element directly, so the value tracks a resolution
68
- // change mid-stream.
69
- export function getVideoTextureHeight(videoTexture) {
70
- const element = videoTexture.source.element;
35
+ // Returns the decoded frame height, or -1 while the borrowed host element is absent/unready.
36
+ export function getVideoTextureHeight(texture) {
37
+ const element = getVideoElement(texture);
71
38
  return element !== null && element.videoHeight > 0 ? element.videoHeight : -1;
72
39
  }
73
- // Composes the KHR_texture_transform fields and inverts the result, producing the matrix that maps
74
- // already-transformed uv back to the unit-square source uv. A zero scale is singular, so inverseMatrix3
75
- // fills the matrix with NaN. Out-param form — write into a pre-allocated Matrix3.
76
- export function getVideoTextureInverseUvMatrix(out, videoTexture) {
77
- getVideoTextureUvMatrix(out, videoTexture);
40
+ // Video-named compatibility entry over the universal Texture UV transform.
41
+ export function getVideoTextureInverseUvMatrix(out, texture) {
42
+ getVideoTextureUvMatrix(out, texture);
78
43
  inverseMatrix3(out, out);
79
44
  }
80
- // Composes the KHR_texture_transform fields (flip, uvOffset, uvRotation, uvScale) into the column-major
81
- // 3×3 matrix a shader consumes at sample time. A VideoTexture is a TextureUvTransform, so this delegates
82
- // to getTextureUvMatrix — one uv-transform path (flip → scale → rotate → translate) for both texture
83
- // kinds. Out-param form.
84
- export function getVideoTextureUvMatrix(out, videoTexture) {
85
- getTextureUvMatrix(out, videoTexture);
45
+ // Video-named compatibility entry over the universal Texture UV transform.
46
+ export function getVideoTextureUvMatrix(out, texture) {
47
+ getTextureUvMatrix(out, texture);
86
48
  }
87
- // Returns the pixel width of the current video frame, or -1 when no element is attached or no frame
88
- // has decoded yet.
89
- export function getVideoTextureWidth(videoTexture) {
90
- const element = videoTexture.source.element;
49
+ // Returns the decoded frame width, or -1 while the borrowed host element is absent/unready.
50
+ export function getVideoTextureWidth(texture) {
51
+ const element = getVideoElement(texture);
91
52
  return element !== null && element.videoWidth > 0 ? element.videoWidth : -1;
92
53
  }
93
- // True when the backing element has decoded at least the current frame (readyState >=
94
- // HAVE_CURRENT_DATA) and its dimensions are known — the gate a material samples behind and a driver
95
- // checks before calling advanceVideoTexture. False while metadata/first-frame is still buffering.
96
- export function isVideoTextureFrameReady(videoTexture) {
97
- const element = videoTexture.source.element;
54
+ // True once the borrowed host element exposes a decoded current frame and non-zero dimensions.
55
+ export function isVideoTextureFrameReady(texture) {
56
+ const element = getVideoElement(texture);
98
57
  return (element !== null && element.readyState >= HAVE_CURRENT_DATA && element.videoWidth > 0 && element.videoHeight > 0);
99
58
  }
100
- // Resets `frameId` to -1 so the next upload re-sends the current frame regardless of history. Used
101
- // after a context loss (the GPU texture is gone) or a source swap to force a re-upload.
102
- export function resetVideoTextureFrame(videoTexture) {
103
- videoTexture.frameId = -1;
59
+ // Resets the shared backing revision so its next advance wraps to 0 and every state re-uploads.
60
+ export function resetVideoTextureFrame(texture) {
61
+ const image = texture.storage.image;
62
+ if (image != null)
63
+ image.version = INITIAL_VIDEO_VERSION;
64
+ texture.version = INITIAL_VIDEO_VERSION;
65
+ }
66
+ // Replaces the immutable host-backed identity and resets its upload revision. The VideoResource
67
+ // remains the loader/lifecycle object; Texture stores only its current host handle.
68
+ export function setVideoTextureSource(texture, source) {
69
+ if (texture.storage.dimension !== '2d')
70
+ throw new Error('setVideoTextureSource requires 2d texture storage');
71
+ texture.storage.image = createVideoImageResource(source);
72
+ texture.version = INITIAL_VIDEO_VERSION;
73
+ }
74
+ function createVideoImageResource(source) {
75
+ if (source.element === null)
76
+ return null;
77
+ const image = createEntity({
78
+ height: 0,
79
+ kind: VideoTextureBackingKind,
80
+ source: source.element,
81
+ version: INITIAL_VIDEO_VERSION,
82
+ width: 0,
83
+ });
84
+ updateVideoImageSize(image);
85
+ return image;
86
+ }
87
+ function getVideoElement(texture) {
88
+ return texture.storage.image?.source ?? null;
104
89
  }
105
- // Binds a different video stream and resets `frameId` to -1 so the new stream's first frame uploads.
106
- // Does not touch sampling state or the uv-transform.
107
- export function setVideoTextureSource(videoTexture, source) {
108
- videoTexture.source = source;
109
- videoTexture.frameId = -1;
90
+ function updateVideoImageSize(image) {
91
+ const element = image.source;
92
+ image.width = element.videoWidth || 0;
93
+ image.height = element.videoHeight || 0;
110
94
  }
111
- // HTMLMediaElement.HAVE_CURRENT_DATA — data for the current playback position is available.
95
+ // HTMLMediaElement.HAVE_CURRENT_DATA and the u32 predecessor of the first public frame revision.
112
96
  const HAVE_CURRENT_DATA = 2;
97
+ const INITIAL_VIDEO_VERSION = 0xffffffff;
113
98
  //# sourceMappingURL=videoTexture.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"videoTexture.js","sourceRoot":"","sources":["../src/videoTexture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"videoTexture.js","sourceRoot":"","sources":["../src/videoTexture.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/texture",
3
- "version": "0.2.1-next.841.373388f",
3
+ "version": "0.3.0-next.1032.e2b99fc",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/flighthq/flight.git",
@@ -13,6 +13,10 @@
13
13
  ".": {
14
14
  "types": "./dist/index.d.ts",
15
15
  "default": "./dist/index.js"
16
+ },
17
+ "./contract": {
18
+ "types": "./dist/contract.d.ts",
19
+ "default": "./dist/contract.js"
16
20
  }
17
21
  },
18
22
  "files": [
@@ -32,9 +36,9 @@
32
36
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
33
37
  },
34
38
  "dependencies": {
35
- "@flighthq/entity": "0.2.1-next.841.373388f",
36
- "@flighthq/geometry": "0.2.1-next.841.373388f",
37
- "@flighthq/types": "0.2.1-next.841.373388f"
39
+ "@flighthq/entity": "0.3.0-next.1032.e2b99fc",
40
+ "@flighthq/geometry": "0.3.0-next.1032.e2b99fc",
41
+ "@flighthq/types": "0.3.0-next.1032.e2b99fc"
38
42
  },
39
43
  "devDependencies": {
40
44
  "typescript": "^5.3.0"
@@ -1,5 +1,5 @@
1
- import type { ImageResource } from '@flighthq/types';
2
- import { CubeFaceNegativeX, CubeFacePositiveX, CubeFacePositiveY } from '@flighthq/types';
1
+ import type { CubeTexture, ImageResource, TextureCubeImages } from '@flighthq/types/contract';
2
+ import { CubeFaceNegativeX, CubeFacePositiveX, CubeFacePositiveY } from '@flighthq/types/contract';
3
3
 
4
4
  import {
5
5
  cloneCubeTexture,
@@ -15,27 +15,27 @@ import { createSampler, equalsSampler } from './sampler';
15
15
  const fakeFace = { width: 64, height: 64 } as ImageResource;
16
16
  const fakeFace2 = { width: 128, height: 128 } as ImageResource;
17
17
 
18
- const allFaces: readonly (ImageResource | null)[] = [fakeFace, fakeFace, fakeFace, fakeFace, fakeFace, fakeFace];
18
+ const allFaces: TextureCubeImages = [fakeFace, fakeFace, fakeFace, fakeFace, fakeFace, fakeFace];
19
19
 
20
20
  describe('cloneCubeTexture', () => {
21
21
  it('shares the face references in a fresh array and deep-clones the sampler', () => {
22
22
  const source = createCubeTexture({
23
23
  colorSpace: 'linear',
24
- faces: [fakeFace, null, null, null, null, null],
24
+ images: [fakeFace, null, null, null, null, null],
25
25
  });
26
26
 
27
27
  const copy = cloneCubeTexture(source);
28
28
 
29
29
  expect(copy).not.toBe(source);
30
30
  expect(copy.colorSpace).toStrictEqual('linear');
31
- expect(copy.faces).not.toBe(source.faces);
32
- expect(copy.faces[0]).toBe(fakeFace);
31
+ expect(copy.storage.images).not.toBe(source.storage.images);
32
+ expect(copy.storage.images[0]).toBe(fakeFace);
33
33
  expect(copy.sampler).not.toBe(source.sampler);
34
34
  expect(equalsSampler(copy.sampler, source.sampler)).toBe(true);
35
35
 
36
36
  // A fresh faces array means reassigning a face on the clone cannot reach the source.
37
- expect(copy.faces).not.toBe(source.faces);
38
- expect(source.faces[1]).toBeNull();
37
+ expect(copy.storage.images).not.toBe(source.storage.images);
38
+ expect(source.storage.images[1]).toBeNull();
39
39
  });
40
40
  });
41
41
 
@@ -43,7 +43,7 @@ describe('copyCubeTexture', () => {
43
43
  it('writes every field from source into a distinct out, preserving sampler identity', () => {
44
44
  const source = createCubeTexture({
45
45
  colorSpace: 'linear',
46
- faces: [fakeFace, null, null, null, null, null],
46
+ images: [fakeFace, null, null, null, null, null],
47
47
  });
48
48
  const out = createCubeTexture();
49
49
  const outSampler = out.sampler;
@@ -51,7 +51,7 @@ describe('copyCubeTexture', () => {
51
51
  copyCubeTexture(out, source);
52
52
 
53
53
  expect(out.colorSpace).toStrictEqual('linear');
54
- expect(out.faces[0]).toBe(fakeFace);
54
+ expect(out.storage.images[0]).toBe(fakeFace);
55
55
  expect(out.sampler).toBe(outSampler);
56
56
  expect(equalsSampler(out.sampler, source.sampler)).toBe(true);
57
57
  });
@@ -59,13 +59,13 @@ describe('copyCubeTexture', () => {
59
59
  it('is safe when out aliases source', () => {
60
60
  const cube = createCubeTexture({
61
61
  colorSpace: 'linear',
62
- faces: [fakeFace, null, null, null, null, null],
62
+ images: [fakeFace, null, null, null, null, null],
63
63
  });
64
64
 
65
65
  copyCubeTexture(cube, cube);
66
66
 
67
67
  expect(cube.colorSpace).toStrictEqual('linear');
68
- expect(cube.faces[0]).toBe(fakeFace);
68
+ expect(cube.storage.images[0]).toBe(fakeFace);
69
69
  });
70
70
  });
71
71
 
@@ -73,25 +73,26 @@ describe('createCubeTexture', () => {
73
73
  it('applies the default six unbound faces, srgb, default sampler', () => {
74
74
  const cube = createCubeTexture();
75
75
 
76
- expect(cube.faces).toHaveLength(6);
77
- expect(cube.faces.every((face) => face === null)).toBe(true);
76
+ expectTypeOf(cube).toEqualTypeOf<CubeTexture>();
77
+ expect(cube.storage.images).toHaveLength(6);
78
+ expect(cube.storage.images.every((face) => face === null)).toBe(true);
78
79
  expect(cube.colorSpace).toStrictEqual('srgb');
79
80
  expect(equalsSampler(cube.sampler, createSampler())).toBe(true);
80
81
  });
81
82
 
82
83
  it('copies a supplied faces array rather than aliasing it', () => {
83
- const faces = [fakeFace, null, null, null, null, null];
84
- const cube = createCubeTexture({ faces });
84
+ const images: TextureCubeImages = [fakeFace, null, null, null, null, null];
85
+ const cube = createCubeTexture({ images });
85
86
 
86
- expect(cube.faces).not.toBe(faces);
87
- expect(cube.faces[0]).toBe(fakeFace);
87
+ expect(cube.storage.images).not.toBe(images);
88
+ expect(cube.storage.images[0]).toBe(fakeFace);
88
89
  });
89
90
  });
90
91
 
91
92
  describe('equalsCubeTexture', () => {
92
93
  it('is true for cubes with the same color space, sampler, and face references', () => {
93
- const a = createCubeTexture({ colorSpace: 'linear', faces: allFaces });
94
- const b = createCubeTexture({ colorSpace: 'linear', faces: allFaces });
94
+ const a = createCubeTexture({ colorSpace: 'linear', images: allFaces });
95
+ const b = createCubeTexture({ colorSpace: 'linear', images: allFaces });
95
96
 
96
97
  expect(equalsCubeTexture(a, b)).toBe(true);
97
98
  expect(equalsCubeTexture(a, a)).toBe(true);
@@ -105,9 +106,9 @@ describe('equalsCubeTexture', () => {
105
106
  });
106
107
 
107
108
  it('is false when a face reference differs', () => {
108
- const a = createCubeTexture({ faces: allFaces });
109
- const b = createCubeTexture({ faces: allFaces });
110
- (b.faces as (ImageResource | null)[])[0] = fakeFace2;
109
+ const a = createCubeTexture({ images: allFaces });
110
+ const b = createCubeTexture({ images: allFaces });
111
+ (b.storage.images as unknown as (ImageResource | null)[])[0] = fakeFace2;
111
112
 
112
113
  expect(equalsCubeTexture(a, b)).toBe(false);
113
114
  });
@@ -130,7 +131,7 @@ describe('equalsCubeTexture', () => {
130
131
 
131
132
  describe('getCubeTextureFaceSize', () => {
132
133
  it('returns the width of the first non-null face', () => {
133
- const cube = createCubeTexture({ faces: [null, fakeFace, null, null, null, null] });
134
+ const cube = createCubeTexture({ images: [null, fakeFace, null, null, null, null] });
134
135
 
135
136
  expect(getCubeTextureFaceSize(cube)).toStrictEqual(64);
136
137
  });
@@ -144,13 +145,13 @@ describe('getCubeTextureFaceSize', () => {
144
145
 
145
146
  describe('isCubeTextureComplete', () => {
146
147
  it('is false when any face is null', () => {
147
- const cube = createCubeTexture({ faces: [fakeFace, null, null, null, null, null] });
148
+ const cube = createCubeTexture({ images: [fakeFace, null, null, null, null, null] });
148
149
 
149
150
  expect(isCubeTextureComplete(cube)).toBe(false);
150
151
  });
151
152
 
152
153
  it('is true when all six faces are bound', () => {
153
- const cube = createCubeTexture({ faces: allFaces });
154
+ const cube = createCubeTexture({ images: allFaces });
154
155
 
155
156
  expect(isCubeTextureComplete(cube)).toBe(true);
156
157
  });
@@ -161,14 +162,14 @@ describe('setCubeTextureFace', () => {
161
162
  const cube = createCubeTexture();
162
163
 
163
164
  setCubeTextureFace(cube, CubeFacePositiveX, fakeFace);
164
- expect(cube.faces[CubeFacePositiveX]).toBe(fakeFace);
165
- expect(cube.faces[CubeFaceNegativeX]).toBeNull();
165
+ expect(cube.storage.images[CubeFacePositiveX]).toBe(fakeFace);
166
+ expect(cube.storage.images[CubeFaceNegativeX]).toBeNull();
166
167
  });
167
168
 
168
169
  it('unbinds a face when passed null', () => {
169
- const cube = createCubeTexture({ faces: allFaces });
170
+ const cube = createCubeTexture({ images: allFaces });
170
171
 
171
172
  setCubeTextureFace(cube, CubeFacePositiveY, null);
172
- expect(cube.faces[CubeFacePositiveY]).toBeNull();
173
+ expect(cube.storage.images[CubeFacePositiveY]).toBeNull();
173
174
  });
174
175
  });
@@ -0,0 +1,48 @@
1
+ import type { RenderTexture } from '@flighthq/types/contract';
2
+
3
+ import { createRenderTexture } from './renderTexture';
4
+ import { createSampler } from './sampler';
5
+
6
+ describe('createRenderTexture', () => {
7
+ it('creates a linear render target with identity UVs and no depth by default', () => {
8
+ const texture = createRenderTexture({ height: 32, width: 64 });
9
+
10
+ expectTypeOf(texture).toEqualTypeOf<RenderTexture>();
11
+ expect(texture).toMatchObject({
12
+ colorSpace: 'linear',
13
+ flipX: false,
14
+ flipY: false,
15
+ storage: {
16
+ dimension: '2d',
17
+ image: null,
18
+ target: { colorSpace: 'linear', height: 32, width: 64 },
19
+ },
20
+ uvOffset: { x: 0, y: 0 },
21
+ uvRotation: 0,
22
+ uvScale: { x: 1, y: 1 },
23
+ version: 0,
24
+ });
25
+ });
26
+
27
+ it('applies sampling, depth, color-space, and uv overrides without aliasing mutable values', () => {
28
+ const sampler = createSampler({ magFilter: 'nearest' });
29
+ const uvOffset = { x: 0.25, y: 0.5 };
30
+ const texture = createRenderTexture({
31
+ colorSpace: 'srgb',
32
+ depth: 'depth-stencil',
33
+ flipY: false,
34
+ height: 16,
35
+ sampler,
36
+ uvOffset,
37
+ width: 8,
38
+ });
39
+
40
+ expect(texture.colorSpace).toBe('srgb');
41
+ expect(texture.storage.target.depth).toBe('depth-stencil');
42
+ expect(texture.flipY).toBe(false);
43
+ expect(texture.sampler.magFilter).toBe('nearest');
44
+ expect(texture.sampler).not.toBe(sampler);
45
+ expect(texture.uvOffset).toMatchObject(uvOffset);
46
+ expect(texture.uvOffset).not.toBe(uvOffset);
47
+ });
48
+ });