@woosh/meep-engine 2.75.2 → 2.75.4

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.
Files changed (37) hide show
  1. package/build/meep.cjs +56 -60
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +56 -60
  4. package/package.json +1 -1
  5. package/src/core/geom/3d/ray/ray_computeNearestPointToPoint.js +7 -1
  6. package/src/core/geom/3d/topology/simplify/compute_face_normal_change_dot_product.js +19 -39
  7. package/src/core/geom/3d/v3_compute_triangle_normal.js +1 -1
  8. package/src/core/geom/Quaternion.js +0 -59
  9. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +2 -1
  10. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshHighlightSystem.js +7 -1
  11. package/src/engine/graphics/geometry/VertexDataSpec.d.ts +10 -0
  12. package/src/engine/graphics/geometry/VertexDataSpec.js +20 -21
  13. package/src/engine/graphics/render/visibility/hiz/buildCanvasViewFromTexture.js +41 -10
  14. package/src/engine/graphics/texture/formatToChannelCount.js +2 -1
  15. package/src/engine/graphics/texture/sampler/filter/sampler2d_scale_down_generic.js +2 -2
  16. package/src/engine/graphics/texture/sampler/prototypeSamplerFiltering.js +20 -19
  17. package/src/engine/graphics/texture/virtual/v2/NOTES.md +93 -1
  18. package/src/engine/graphics/texture/virtual/v2/VirtualTextureMaterial.js +193 -0
  19. package/src/engine/graphics/texture/virtual/v2/VirtualTextureMemoryMapping.js +203 -0
  20. package/src/engine/graphics/texture/virtual/v2/{PageTexture.js → VirtualTexturePage.js} +151 -22
  21. package/src/engine/graphics/texture/virtual/v2/VirtualTextureTileLoader.js +10 -1
  22. package/src/engine/graphics/texture/virtual/v2/VirtualTextureUsage.js +43 -10
  23. package/src/engine/graphics/texture/virtual/v2/VirtualTextureUsageShader.js +3 -3
  24. package/src/engine/graphics/texture/virtual/v2/VirtualTextureUsageUpdater.js +39 -11
  25. package/src/engine/graphics/texture/virtual/v2/debug/ResidencyDebugView.js +20 -5
  26. package/src/engine/graphics/texture/virtual/v2/prototype.js +148 -62
  27. package/src/engine/graphics/texture/virtual/v2/tile/VirtualTextureTile.js +4 -0
  28. package/src/core/bvh2/sah/surfaceAreaHeuristic.js +0 -15
  29. package/src/core/bvh2/sah/surfaceAreaHeuristicFull.js +0 -14
  30. package/src/core/geom/3d/aabb/computeBoundingBoxFromVertexData.js +0 -12
  31. package/src/core/geom/3d/frustum/array_normalize_plane.js +0 -25
  32. package/src/core/geom/3d/plane/lerp_planes_to_array.js +0 -53
  33. package/src/core/geom/3d/plane/planeRayIntersection.js +0 -14
  34. package/src/core/geom/3d/voxel/DenseBitVolume3D.js +0 -87
  35. package/src/core/geom/3d/voxel/buildVolumeFromProjectedGeometry.js +0 -23
  36. package/src/engine/graphics/texture/virtual/v2/ResidentTileTexture.js +0 -46
  37. /package/src/core/math/{bessel_i0.spec.js → bessel_j0.spec.js} +0 -0
@@ -1,4 +1,5 @@
1
- import { WebGLRenderTarget } from "three";
1
+ import { ClampToEdgeWrapping, DataTexture, LinearFilter, NearestFilter, Vector2 } from "three";
2
+ import { assert } from "../../../../../core/assert.js";
2
3
  import { BitSet } from "../../../../../core/binary/BitSet.js";
3
4
  import { Cache } from "../../../../../core/cache/Cache.js";
4
5
  import { array_copy } from "../../../../../core/collection/array/array_copy.js";
@@ -6,20 +7,36 @@ import { HashMap } from "../../../../../core/collection/map/HashMap.js";
6
7
  import { passThrough, strictEquals } from "../../../../../core/function/Functions.js";
7
8
  import { max2 } from "../../../../../core/math/max2.js";
8
9
  import { min2 } from "../../../../../core/math/min2.js";
10
+ import { Sampler2D } from "../../sampler/Sampler2D.js";
11
+ import { writeSample2DDataToDataTexture } from "../../sampler/writeSampler2DDataToDataTexture.js";
9
12
  import { tile_address_to_finger_print } from "./tile/tile_address_to_finger_print.js";
10
13
  import { VirtualTextureTileLoader } from "./VirtualTextureTileLoader.js";
11
14
 
12
15
  /**
13
16
  * How much extra data to store in cache (in bytes)
17
+ * IMPORTANT: MAKE SURE THAT THE CACHE CAN HOLD AT LEAST 1 TILE!
14
18
  * @type {number}
15
19
  */
16
- const DEFAULT_CACHE_SIZE = 16 * 1024 * 1024;
20
+ const DEFAULT_CACHE_SIZE = 256 * 1024 * 1024;
17
21
 
18
- export class PageTexture {
19
- #page_texture = new WebGLRenderTarget(1, 1);
22
+ export class VirtualTexturePage {
23
+ #page_texture = new DataTexture(new Uint8Array(4), 1, 1);
24
+
25
+ #tile_copy_sampler = Sampler2D.uint8(4, 1, 1);
26
+ #tile_copy_texture = new DataTexture(this.#tile_copy_sampler.data, 1, 1);
20
27
 
21
28
  #page_texture_size = [1, 1];
22
29
 
30
+ /**
31
+ *
32
+ * @type {number[]}
33
+ */
34
+ #page_texture_resolution_in_tiles = [1, 1];
35
+
36
+ get page_texture_resolution_in_tiles() {
37
+ return this.#page_texture_resolution_in_tiles;
38
+ }
39
+
23
40
  /**
24
41
  * Used internally to track number of times `update` method was called
25
42
  * @type {number}
@@ -37,19 +54,37 @@ export class PageTexture {
37
54
  * This helps prevent thrashing and keep performance overhead of updating pages predictable
38
55
  * @type {number}
39
56
  */
40
- #cycle_assignment_limit = 2;
57
+ #cycle_assignment_limit = 4;
58
+
59
+ /**
60
+ *
61
+ * @type {THREE.WebGLRenderer|null}
62
+ */
63
+ #renderer = null;
64
+
65
+ set renderer(v) {
66
+ this.#renderer = v;
67
+ }
41
68
 
42
69
 
43
70
  get page_texture_resolution() {
44
71
  return this.#page_texture_size;
45
72
  }
46
73
 
74
+ get texture() {
75
+ return this.#page_texture;
76
+ }
77
+
47
78
  /**
48
79
  *
49
80
  * @type {VirtualTextureTile[]}
50
81
  */
51
82
  #resident_tiles = [];
52
83
 
84
+ /**
85
+ *
86
+ * @returns {VirtualTextureTile[]}
87
+ */
53
88
  get resident_tiles() {
54
89
  return this.#resident_tiles;
55
90
  }
@@ -71,6 +106,34 @@ export class PageTexture {
71
106
  return this.#tile_resolution;
72
107
  }
73
108
 
109
+ /**
110
+ *
111
+ * @param {number} v
112
+ */
113
+ set tile_resolution(v) {
114
+ this.#tile_resolution = v;
115
+
116
+ this.#update_tile_slot_resolution();
117
+ this.clear_resident();
118
+ }
119
+
120
+ /**
121
+ * Extra padding on repeated pixels around each tile on each side (top, left, right, bottom)
122
+ * Used to enable texture filtering
123
+ * @type {number}
124
+ */
125
+ #tile_margin = 4;
126
+
127
+ get tile_margin() {
128
+ return this.#tile_margin;
129
+ }
130
+
131
+ #tile_slot_resolution = this.#tile_resolution + this.#tile_margin * 2;
132
+
133
+ #update_tile_slot_resolution() {
134
+ this.#tile_slot_resolution = this.#tile_resolution + this.#tile_margin * 2;
135
+ }
136
+
74
137
  #residency_tile_capacity = 0;
75
138
 
76
139
  /**
@@ -90,6 +153,17 @@ export class PageTexture {
90
153
  #asset_manager = null;
91
154
 
92
155
  constructor() {
156
+ const texture = this.#page_texture;
157
+
158
+ texture.generateMipmaps = false;
159
+ texture.minFilter = NearestFilter;
160
+ texture.magFilter = LinearFilter;
161
+ // texture.magFilter = NearestFilter;
162
+ texture.anisotropy = this.#tile_margin*2;
163
+
164
+ this.#tile_copy_texture.wrapT = ClampToEdgeWrapping;
165
+ this.#tile_copy_texture.wrapS = ClampToEdgeWrapping;
166
+
93
167
  this.#loader.on.loaded.add(this.#handle_tile_loaded, this);
94
168
  }
95
169
 
@@ -100,6 +174,10 @@ export class PageTexture {
100
174
  #handle_tile_loaded(tile) {
101
175
  const finderPrint = tile.finder_print;
102
176
 
177
+ assert.notNull(tile.data, 'tile.data');
178
+ assert.equal(tile.data.width, this.#tile_slot_resolution);
179
+ assert.equal(tile.data.height, this.#tile_slot_resolution);
180
+
103
181
  if (this.#tile_cache.has(finderPrint)) {
104
182
  // already loaded
105
183
  return;
@@ -124,11 +202,14 @@ export class PageTexture {
124
202
  }
125
203
 
126
204
  #update_residency_capacity() {
127
- const tile_resolution = this.#tile_resolution;
205
+ const slot_resolution = this.#tile_slot_resolution;
128
206
  const size = this.#page_texture_size;
129
207
 
130
- const x = size[0] / tile_resolution;
131
- const y = size[1] / tile_resolution;
208
+ const x = Math.floor(size[0] / slot_resolution);
209
+ const y = Math.floor(size[1] / slot_resolution);
210
+
211
+ this.#page_texture_resolution_in_tiles[0] = x;
212
+ this.#page_texture_resolution_in_tiles[1] = y;
132
213
 
133
214
  this.#residency_tile_capacity = x * y;
134
215
 
@@ -138,17 +219,7 @@ export class PageTexture {
138
219
 
139
220
 
140
221
  /**
141
- *
142
- * @param {number} v
143
- */
144
- set tile_resolution(v) {
145
- this.#tile_resolution = v;
146
-
147
- this.#update_residency_capacity();
148
- }
149
-
150
- /**
151
- * Tiles that are not currently resident live here
222
+ * Tiles that are not currently resident live here, this is essentially a second level cache
152
223
  * key is the tile's "fingerprint"
153
224
  * @type {Cache<number,VirtualTextureTile>}
154
225
  */
@@ -241,6 +312,42 @@ export class PageTexture {
241
312
  this.#resident_tiles.push(tile);
242
313
  this.#resident_tile_lookup.set(tile.finder_print, tile);
243
314
 
315
+ const res_x = this.#page_texture_resolution_in_tiles[0];
316
+
317
+ const position_tile_x = slot % res_x;
318
+ const position_tile_y = (slot - position_tile_x) / res_x;
319
+
320
+ const slot_resolution = this.#tile_slot_resolution;
321
+
322
+ const copy_sampler = this.#tile_copy_sampler;
323
+ if (copy_sampler.width !== slot_resolution || copy_sampler.height !== slot_resolution) {
324
+ copy_sampler.resize(slot_resolution, slot_resolution);
325
+
326
+ writeSample2DDataToDataTexture(copy_sampler, this.#tile_copy_texture);
327
+ }
328
+
329
+ //
330
+ // const tile_margin = this.#tile_margin;
331
+ //
332
+ // copy_sampler.copyWithMargin(
333
+ // tile.data, 0, 0,
334
+ // tile_margin, tile_margin,
335
+ // this.#tile_resolution, this.#tile_resolution,
336
+ // tile_margin, tile_margin, tile_margin, tile_margin
337
+ // );
338
+
339
+ this.#tile_copy_texture.image.data.set(tile.data.data);
340
+ this.#tile_copy_texture.needsUpdate = true;
341
+
342
+ const write_position = new Vector2(
343
+ position_tile_x * slot_resolution,
344
+ position_tile_y * slot_resolution,
345
+ );
346
+
347
+ this.#renderer.copyTextureToTexture(
348
+ write_position, this.#tile_copy_texture, this.#page_texture
349
+ );
350
+
244
351
  this.version++;
245
352
 
246
353
  return true;
@@ -257,12 +364,26 @@ export class PageTexture {
257
364
  2
258
365
  );
259
366
 
367
+ this.clear_resident();
368
+
260
369
  this.#page_texture.dispose();
261
- this.#page_texture.setSize(this.#page_texture_size[0], this.#page_texture_size[1]);
370
+
371
+ const width = this.#page_texture_size[0];
372
+ const height = this.#page_texture_size[1];
373
+
374
+ this.#page_texture.image.data = new Uint8Array(width * height * 4);
375
+ this.#page_texture.image.width = width;
376
+ this.#page_texture.image.height = height;
377
+
378
+ this.#page_texture.needsUpdate = true;
262
379
 
263
380
  this.#update_residency_capacity();
264
381
  }
265
382
 
383
+ get page_texture_size() {
384
+ return this.#page_texture_size;
385
+ }
386
+
266
387
  /**
267
388
  *
268
389
  * @param {VirtualTextureUsage} usage
@@ -324,12 +445,20 @@ export class PageTexture {
324
445
  this.update_count++;
325
446
  }
326
447
 
448
+ clear_resident() {
449
+
450
+ while (this.#resident_tiles.length > 0) {
451
+ this.#evict_one();
452
+ }
453
+
454
+ }
455
+
327
456
  dispose() {
457
+ this.clear_resident();
458
+
328
459
  this.#page_texture.dispose();
329
460
  this.#tile_cache.clear();
330
461
  this.#page_slot_occupancy.reset();
331
462
 
332
- this.#resident_tiles.splice(0, this.#resident_tiles.length);
333
- this.#resident_tile_lookup.clear();
334
463
  }
335
464
  }
@@ -3,6 +3,8 @@ import { arrayQuickSort } from "../../../../../core/collection/array/arrayQuickS
3
3
  import Signal from "../../../../../core/events/signal/Signal.js";
4
4
  import { AssetManager } from "../../../../asset/AssetManager.js";
5
5
  import { GameAssetType } from "../../../../asset/GameAssetType.js";
6
+ import { Sampler2D } from "../../sampler/Sampler2D.js";
7
+ import { sampler2d_to_uint8_RGBA } from "../../sampler/sampler2d_to_uint8_RGBA.js";
6
8
  import { compose_finger_print } from "./tile/compose_finger_print.js";
7
9
  import { decompose_finger_print } from "./tile/decompose_finger_print.js";
8
10
  import { VirtualTextureTile } from "./tile/VirtualTextureTile.js";
@@ -211,8 +213,15 @@ export class VirtualTextureTileLoader {
211
213
 
212
214
  const tile = new VirtualTextureTile();
213
215
 
216
+ let rgba = sampler;
214
217
 
215
- tile.data = sampler;
218
+ if (rgba.itemSize !== 4) {
219
+ rgba = Sampler2D.uint8(4, sampler.width, sampler.height);
220
+
221
+ sampler2d_to_uint8_RGBA(rgba, sampler);
222
+ }
223
+
224
+ tile.data = rgba;
216
225
  tile.finder_print = finger_print;
217
226
 
218
227
  this.on.loaded.send1(tile);
@@ -1,6 +1,8 @@
1
- import { arrayQuickSort } from "../../../../../core/collection/array/arrayQuickSort.js";
1
+ import { array_quick_sort_by_comparator, arrayQuickSort } from "../../../../../core/collection/array/arrayQuickSort.js";
2
2
  import { compose_tile_address } from "./tile/compose_tile_address.js";
3
+ import { decompose_finger_print } from "./tile/decompose_finger_print.js";
3
4
  import { finger_print_to_tile_address } from "./tile/finger_print_to_tile_address.js";
5
+ import { tile_address_to_finger_print } from "./tile/tile_address_to_finger_print.js";
4
6
 
5
7
 
6
8
  export class VirtualTextureUsage {
@@ -96,7 +98,8 @@ export class VirtualTextureUsage {
96
98
  promoteAncestors(bias = 1) {
97
99
 
98
100
  // traverse mip pyramid in reverse, so we can push counts to parents one level at a time
99
- for (let mip = this.#max_mip_level; mip > 0; mip--) {
101
+ const max_mip = this.#max_mip_level;
102
+ for (let mip = max_mip; mip > 0; mip--) {
100
103
 
101
104
  const mip_resolution = 1 << mip;
102
105
 
@@ -118,14 +121,10 @@ export class VirtualTextureUsage {
118
121
 
119
122
  const parent_count = this.#counts_intrinsic[parent_index];
120
123
 
121
- const expected_count = count + bias;
124
+ this.#counts_intrinsic[parent_index] = parent_count + count + bias;
122
125
 
123
- if (parent_count < expected_count) {
124
- this.#counts_intrinsic[parent_index] = expected_count;
125
-
126
- if (parent_count === 0) {
127
- this.#append_to_occupancy(parent_index);
128
- }
126
+ if (parent_count === 0) {
127
+ this.#append_to_occupancy(parent_index);
129
128
  }
130
129
 
131
130
  }
@@ -147,13 +146,47 @@ export class VirtualTextureUsage {
147
146
  * Sort occupancy list in descending order
148
147
  */
149
148
  sortOccupancy() {
149
+ // array_quick_sort_by_comparator(this.#occupancy, (a, b) => {
150
+ //
151
+ // return a-b;
152
+ //
153
+ //
154
+ // }, null, 0, this.#occupancy_cursor - 1);
155
+
156
+ //
157
+ // arrayQuickSort(this.#occupancy, v => -v, null, 0, this.#occupancy_cursor - 1);
150
158
  arrayQuickSort(
151
159
  this.#occupancy,
152
- (index) => -this.#counts_intrinsic[index], null,
160
+ (index) => {
161
+ return -this.#counts_intrinsic[index]
162
+ }, null,
153
163
  0, this.#occupancy_cursor - 1
154
164
  );
155
165
  }
156
166
 
167
+ sortOccupancyByLOD() {
168
+ array_quick_sort_by_comparator(this.#occupancy, (a, b) => {
169
+
170
+ const fingerprint_a = tile_address_to_finger_print(a);
171
+ const fingerprint_b = tile_address_to_finger_print(b);
172
+
173
+ const { mip: mip_a } = decompose_finger_print(fingerprint_a);
174
+ const { mip: mip_b } = decompose_finger_print(fingerprint_b);
175
+
176
+ const mip_delta = mip_a - mip_b;
177
+
178
+ if (mip_delta !== 0) {
179
+ return mip_delta;
180
+ }
181
+
182
+ const count_a = this.#counts_intrinsic[a];
183
+ const count_b = this.#counts_intrinsic[b];
184
+ return count_b - count_a;
185
+
186
+ }, null, 0, this.#occupancy_cursor - 1);
187
+
188
+ }
189
+
157
190
 
158
191
  /**
159
192
  *
@@ -27,7 +27,7 @@ function fragment() {
27
27
 
28
28
  uniform uvec4 u_mt_tex; // [ width, height, tileSize, id ]
29
29
  uniform vec2 u_mt_params; // [ bias, maxLevel ]
30
- uniform vec2 u_mt_viewport_size;
30
+ uniform vec2 u_mt_viewport_scale;
31
31
  in vec2 vUv;
32
32
 
33
33
  out uvec4 out_decoded;
@@ -37,8 +37,8 @@ function fragment() {
37
37
  float scale_x = float(u_mt_tex.x) ;
38
38
  float scale_y = float(u_mt_tex.y) ;
39
39
 
40
- vec2 dx = dFdx( uv * scale_x)/ u_mt_viewport_size.x;
41
- vec2 dy = dFdy( uv * scale_y)/ u_mt_viewport_size.y;
40
+ vec2 dx = dFdx( uv * scale_x ) * u_mt_viewport_scale.x;
41
+ vec2 dy = dFdy( uv * scale_y ) * u_mt_viewport_scale.y;
42
42
 
43
43
  float d = max( dot( dx, dx ), dot( dy, dy ) );
44
44
 
@@ -23,7 +23,7 @@ import { VirtualTextureUsage } from "./VirtualTextureUsage.js";
23
23
  import { fragment, vertex } from "./VirtualTextureUsageShader.js";
24
24
 
25
25
  const usage_material_uniforms = {
26
- "u_mt_params": { value: new Vector2(0.1, 1) },
26
+ "u_mt_params": { value: new Vector2(0, 1) },
27
27
  /**
28
28
  * Format: VT_WIDTH, VT_HEIGHT, VT_TILE_SIZE, VT_ID
29
29
  * - VT_WIDTH : width of the virtual texture
@@ -32,7 +32,7 @@ const usage_material_uniforms = {
32
32
  * - VT_ID : multiple different virtual textures may be used, this identifies current texture
33
33
  */
34
34
  "u_mt_tex": { value: new Vector4(1, 1, 1, 3) },
35
- "u_mt_viewport_size": { value: new Vector2(1, 1) },
35
+ "u_mt_viewport_scale": { value: new Vector2(1, 1) },
36
36
  "modelViewMatrix": { value: new Matrix4() },
37
37
  "projectionMatrix": { value: new Matrix4() }
38
38
  };
@@ -49,6 +49,8 @@ usage_material.blending = NoBlending;
49
49
 
50
50
 
51
51
  const clear_usage_material = new RawShaderMaterial({
52
+ depthTest: false,
53
+ depthWrite: false,
52
54
  vertexShader: `
53
55
  precision mediump float;
54
56
  in vec2 uv;
@@ -83,6 +85,18 @@ export class VirtualTextureUsageUpdater {
83
85
  #frame_jitter_samples = 1;
84
86
  #frame_jitter_enabled = false;
85
87
 
88
+ get frame_jitter_enabled() {
89
+ return this.#frame_jitter_enabled;
90
+ }
91
+
92
+ /**
93
+ *
94
+ * @param {boolean} v
95
+ */
96
+ set frame_jitter_enabled(v) {
97
+ this.#frame_jitter_enabled = v;
98
+ }
99
+
86
100
  #initialize_frame_jitter() {
87
101
  this.#frame_jitter_samples = this.#usage_resolution_scale;
88
102
  this.#frame_jitter_offsets = generate_halton_jitter(this.#frame_jitter_samples);
@@ -91,14 +105,15 @@ export class VirtualTextureUsageUpdater {
91
105
  #usage_buffer = new WebGLRenderTarget(1, 1, {
92
106
  wrapT: ClampToEdgeWrapping,
93
107
  wrapS: ClampToEdgeWrapping,
94
- generateMipmaps: false,
95
108
  minFilter: NearestFilter,
96
109
  magFilter: NearestFilter,
97
110
  format: RGBAIntegerFormat,
111
+ type: UnsignedByteType,
112
+ internalFormat: "RGBA8UI",
113
+ anisotropy: 1,
98
114
  depthBuffer: true,
99
115
  stencilBuffer: false,
100
- type: UnsignedByteType,
101
- internalFormat: "RGBA8UI"
116
+ generateMipmaps: false,
102
117
  });
103
118
 
104
119
  #usage_pixel_data = Sampler2D.uint8(4, 1, 1);
@@ -131,10 +146,10 @@ export class VirtualTextureUsageUpdater {
131
146
  }
132
147
 
133
148
  /**
134
- * Used to fetch higher resolution tiles
149
+ * Used to fetch higher/lower resolution tiles, negative value will fetch higher resolution tiles, and vice-versa
135
150
  * @type {number}
136
151
  */
137
- #usage_texture_bias = 0.1;
152
+ #usage_texture_bias = 0;
138
153
 
139
154
 
140
155
  /**
@@ -148,6 +163,8 @@ export class VirtualTextureUsageUpdater {
148
163
  tile_size,
149
164
  texture_id
150
165
  ) {
166
+ assert.lessThanOrEqual(tile_size, resolution, `tile_size(=${tile_size}) must be <= than the overall texture resolution(=${resolution})`);
167
+
151
168
  this.#texture_id = texture_id;
152
169
  this.#texture_resolution = resolution;
153
170
  this.#tile_resolution = tile_size;
@@ -171,8 +188,14 @@ export class VirtualTextureUsageUpdater {
171
188
  }
172
189
 
173
190
  constructor() {
191
+
192
+ const target = this.#usage_buffer;
193
+ target.scissorTest = false;
194
+
195
+
174
196
  this.#initialize_usage_uniforms();
175
197
  this.#initialize_frame_jitter();
198
+
176
199
  }
177
200
 
178
201
  #initialize_usage_uniforms() {
@@ -227,7 +250,7 @@ export class VirtualTextureUsageUpdater {
227
250
  this.#usage_pixel_data.resize(usage_resolution_x, usage_resolution_y, true);
228
251
 
229
252
  const usage_material_uniforms = usage_material.uniforms;
230
- usage_material_uniforms.u_mt_viewport_size.value.set(_x / usage_resolution_x, _y / usage_resolution_y);
253
+ usage_material_uniforms.u_mt_viewport_scale.value.set(usage_resolution_x / _x, usage_resolution_y / _y);
231
254
 
232
255
  }
233
256
 
@@ -289,11 +312,16 @@ export class VirtualTextureUsageUpdater {
289
312
 
290
313
  renderer.render(scene, camera);
291
314
 
292
- scene.overrideMaterial = _old_material;
293
315
 
294
- renderer.readRenderTargetPixels(usage_buffer, 0, 0, usage_buffer.width, usage_buffer.height, this.#usage_pixel_data.data);
316
+ renderer.readRenderTargetPixels(
317
+ usage_buffer, 0, 0,
318
+ usage_buffer.width, usage_buffer.height,
319
+ this.#usage_pixel_data.data
320
+ );
295
321
 
296
322
  // restore state
323
+ scene.overrideMaterial = _old_material;
324
+
297
325
  renderer.setRenderTarget(_old_render_target);
298
326
  renderer.autoClear = _auto_clear;
299
327
  array_copy(scratch_matrix, 0, camera_projection_matrix, 0, 16);
@@ -303,7 +331,7 @@ export class VirtualTextureUsageUpdater {
303
331
  //
304
332
  this.#usage_metadata.fromTexture(this.#usage_pixel_data.data);
305
333
  this.#usage_metadata.promoteAncestors(1);
306
- this.#usage_metadata.sortOccupancy();
334
+ this.#usage_metadata.sortOccupancyByLOD();
307
335
 
308
336
  this.#frame_index++;
309
337
  }
@@ -6,7 +6,7 @@ import { sampler2d_write_to_canvas_raw } from "../../../sampler/sampler2d_write_
6
6
  export class ResidencyDebugView extends EmptyView {
7
7
  /**
8
8
  *
9
- * @type {PageTexture|null}
9
+ * @type {VirtualTexturePage|null}
10
10
  */
11
11
  texture = null;
12
12
 
@@ -14,15 +14,21 @@ export class ResidencyDebugView extends EmptyView {
14
14
 
15
15
  #previous_residency = new Uint32Array(1024);
16
16
 
17
- constructor() {
17
+ #scale =1;
18
+
19
+ constructor({
20
+ scale = 1
21
+ } = {}) {
22
+
18
23
  super({
19
24
  css: {
20
25
  position: "absolute",
21
26
  boxShadow: "0 0 8px black",
22
27
  background: "black"
23
- }
28
+ },
24
29
  });
25
30
 
31
+ this.#scale = scale;
26
32
  this.#canvas.css(CSS_ABSOLUTE_POSITIONING);
27
33
 
28
34
  this.addChild(this.#canvas);
@@ -38,7 +44,12 @@ export class ResidencyDebugView extends EmptyView {
38
44
  }
39
45
 
40
46
  const canvas = this.#canvas;
41
- canvas.size.readFromArray(t.page_texture_resolution);
47
+ const scale = this.#scale;
48
+
49
+ canvas.size.set(
50
+ t.page_texture_resolution[0] * scale,
51
+ t.page_texture_resolution[1] * scale,
52
+ );
42
53
 
43
54
  this.size.copy(canvas.size);
44
55
 
@@ -62,7 +73,11 @@ export class ResidencyDebugView extends EmptyView {
62
73
  const column = page_slot % tile_columns;
63
74
  const row = (page_slot / tile_columns) | 0;
64
75
 
65
- canvas.context2d.drawImage(temp.el, 0, 0, tile_resolution, tile_resolution, tile_resolution * column, tile_resolution * row, tile_resolution, tile_resolution);
76
+ canvas.context2d.drawImage(
77
+ temp.el, 0, 0, tile_resolution, tile_resolution,
78
+ tile_resolution * column * scale, tile_resolution * row * scale,
79
+ tile_resolution * scale, tile_resolution * scale
80
+ );
66
81
 
67
82
  this.#previous_residency[page_slot] = tile.finder_print;
68
83
  }