@woosh/meep-engine 2.73.0 → 2.75.0
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.
- package/build/bundle-worker-image-decoder.js +1 -1
- package/build/meep.cjs +185 -189
- package/build/meep.min.js +1 -1
- package/build/meep.module.js +185 -189
- package/package.json +1 -1
- package/src/core/binary/UINT32_MAX.js +5 -0
- package/src/core/bvh2/bvh3/BVH.js +44 -2
- package/src/core/bvh2/bvh3/BVH.spec.js +45 -0
- package/src/core/bvh2/bvh3/build_triangle_morton_codes.js +73 -0
- package/src/core/bvh2/bvh3/ebvh_build_for_geometry_morton.js +5 -101
- package/src/core/bvh2/bvh3/ebvh_build_hierarchy.js +59 -0
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_nearest_to_point.js +31 -32
- package/src/core/bvh2/bvh3/query/bvh_query_user_data_nearest_to_point.spec.js +64 -0
- package/src/core/collection/SCRATCH_UINT32_TRAVERSAL_STACK.js +1 -0
- package/src/core/geom/3d/aabb/aabb3_signed_distance_sqr_to_point.js +1 -0
- package/src/core/geom/3d/aabb/aabb3_unsigned_distance_sqr_to_point.js +36 -0
- package/src/core/process/worker/OnDemandWorkerManager.js +5 -1
- package/src/engine/asset/loaders/ArrayBufferLoader.js +13 -15
- package/src/engine/asset/loaders/image/ImageDecoderWorker.js +1 -1
- package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +5 -7
- package/src/engine/asset/loaders/image/codec/NativeImageDecoder.js +2 -1
- package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +5 -6
- package/src/engine/asset/loaders/image/png/PNG.js +339 -332
- package/src/engine/asset/loaders/image/png/PNGReader.js +77 -30
- package/src/engine/asset/loaders/image/png/prototypePNG.js +13 -4
- package/src/engine/graphics/generate_halton_jitter.js +21 -0
- package/src/engine/graphics/render/buffer/simple-fx/taa/TemporalSupersamplingRenderPlugin.js +3 -20
- package/src/engine/graphics/texture/virtual/v2/PageTexture.js +335 -0
- package/src/engine/graphics/texture/virtual/v2/ResidentTileTexture.js +46 -0
- package/src/engine/graphics/texture/virtual/v2/{TileLoader.js → VirtualTextureTileLoader.js} +33 -13
- package/src/engine/graphics/texture/virtual/v2/{UsageMetadata.js → VirtualTextureUsage.js} +68 -22
- package/src/engine/graphics/texture/virtual/v2/{VirtualTextureManager.js → VirtualTextureUsageUpdater.js} +66 -9
- package/src/engine/graphics/texture/virtual/v2/debug/ResidencyDebugView.js +70 -0
- package/src/engine/graphics/texture/virtual/v2/debug/UsageDebugView.js +63 -0
- package/src/engine/graphics/texture/virtual/v2/{UsagePyramidDebugView.js → debug/UsagePyramidDebugView.js} +31 -40
- package/src/engine/graphics/texture/virtual/v2/prototype.js +98 -54
- package/src/engine/graphics/texture/virtual/v2/{TextureTile.js → tile/VirtualTextureTile.js} +3 -3
- package/src/engine/graphics/texture/virtual/v2/tile/compose_finger_print.js +23 -0
- package/src/engine/graphics/texture/virtual/v2/tile/compose_tile_address.js +26 -0
- package/src/engine/graphics/texture/virtual/v2/tile/decompose_finger_print.js +12 -0
- package/src/engine/graphics/texture/virtual/v2/tile/finger_print_to_tile_address.js +16 -0
- package/src/engine/graphics/texture/virtual/v2/{tile_index_to_finger_print.js → tile/tile_address_to_finger_print.js} +7 -3
- package/src/view/CSS_ABSOLUTE_POSITIONING.js +5 -0
- package/src/engine/graphics/texture/virtual/v2/SparseTexture.js +0 -182
- package/src/engine/graphics/texture/virtual/v2/UsageDebugView.js +0 -64
- package/src/engine/graphics/texture/virtual/v2/compose_finger_print.js +0 -13
- package/src/engine/graphics/texture/virtual/v2/finger_print_to_tile_index.js +0 -37
- /package/src/engine/graphics/texture/virtual/v2/{ShaderUsage.js → VirtualTextureUsageShader.js} +0 -0
package/src/engine/graphics/texture/virtual/v2/{TileLoader.js → VirtualTextureTileLoader.js}
RENAMED
|
@@ -3,24 +3,37 @@ 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 { compose_finger_print } from "./compose_finger_print.js";
|
|
7
|
-
import { decompose_finger_print } from "./
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
import { compose_finger_print } from "./tile/compose_finger_print.js";
|
|
7
|
+
import { decompose_finger_print } from "./tile/decompose_finger_print.js";
|
|
8
|
+
import { VirtualTextureTile } from "./tile/VirtualTextureTile.js";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Facilitates prioritized queueing and loading of individual texture tiles
|
|
12
|
+
*/
|
|
13
|
+
export class VirtualTextureTileLoader {
|
|
11
14
|
/**
|
|
12
15
|
* Where the tiles are stored
|
|
13
16
|
* @type {string}
|
|
14
17
|
*/
|
|
15
18
|
#root_path = "";
|
|
16
19
|
|
|
20
|
+
set path(v) {
|
|
21
|
+
this.#root_path = v;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* When queue gets larger than this, we start discarding elements
|
|
26
|
+
* @type {number}
|
|
27
|
+
*/
|
|
28
|
+
queue_limit = Infinity;
|
|
29
|
+
|
|
17
30
|
/**
|
|
18
31
|
*
|
|
19
32
|
* @type {AssetManager}
|
|
20
33
|
*/
|
|
21
34
|
#asset_manager = null;
|
|
22
35
|
|
|
23
|
-
set asset_manager(v){
|
|
36
|
+
set asset_manager(v) {
|
|
24
37
|
this.#asset_manager = v;
|
|
25
38
|
}
|
|
26
39
|
|
|
@@ -49,7 +62,7 @@ export class TileLoader {
|
|
|
49
62
|
*/
|
|
50
63
|
on = {
|
|
51
64
|
/**
|
|
52
|
-
* @type {Signal<
|
|
65
|
+
* @type {Signal<VirtualTextureTile>}
|
|
53
66
|
*/
|
|
54
67
|
loaded: new Signal()
|
|
55
68
|
};
|
|
@@ -95,7 +108,6 @@ export class TileLoader {
|
|
|
95
108
|
return false;
|
|
96
109
|
}
|
|
97
110
|
|
|
98
|
-
// TODO limit queue size, if the queue grows too large we may end up with completely irrelevant tiles being loaded minutes after they were actually relevant
|
|
99
111
|
if (this.#queue_add(fingerprint) === false) {
|
|
100
112
|
return false;
|
|
101
113
|
}
|
|
@@ -118,7 +130,7 @@ export class TileLoader {
|
|
|
118
130
|
|
|
119
131
|
/**
|
|
120
132
|
*
|
|
121
|
-
* @param {
|
|
133
|
+
* @param {VirtualTextureUsage} usage
|
|
122
134
|
*/
|
|
123
135
|
#sort_queue_by_usage(usage) {
|
|
124
136
|
|
|
@@ -138,10 +150,16 @@ export class TileLoader {
|
|
|
138
150
|
|
|
139
151
|
/**
|
|
140
152
|
*
|
|
141
|
-
* @param {
|
|
153
|
+
* @param {VirtualTextureUsage} usage
|
|
142
154
|
*/
|
|
143
155
|
update_usage(usage) {
|
|
144
156
|
this.#sort_queue_by_usage(usage);
|
|
157
|
+
|
|
158
|
+
// truncate the queue if necessary
|
|
159
|
+
const queue_overflow = this.#queue.length - this.queue_limit;
|
|
160
|
+
if (queue_overflow > 0) {
|
|
161
|
+
this.#queue.splice(this.queue_limit, queue_overflow);
|
|
162
|
+
}
|
|
145
163
|
}
|
|
146
164
|
|
|
147
165
|
/**
|
|
@@ -165,7 +183,7 @@ export class TileLoader {
|
|
|
165
183
|
*/
|
|
166
184
|
#prod() {
|
|
167
185
|
while (this.#in_flight.length < this.#concurrency && this.#queue.length > 0) {
|
|
168
|
-
const fingerprint = this.#queue
|
|
186
|
+
const fingerprint = this.#queue[0];
|
|
169
187
|
const { mip, x, y } = decompose_finger_print(fingerprint);
|
|
170
188
|
|
|
171
189
|
this.#load(mip, x, y);
|
|
@@ -177,7 +195,7 @@ export class TileLoader {
|
|
|
177
195
|
* @param {number} mip
|
|
178
196
|
* @param {number} x
|
|
179
197
|
* @param {number} y
|
|
180
|
-
* @returns {Promise<
|
|
198
|
+
* @returns {Promise<VirtualTextureTile>}
|
|
181
199
|
*/
|
|
182
200
|
#load(mip, x, y) {
|
|
183
201
|
const file_name = this.#build_file_name(mip, x, y);
|
|
@@ -191,7 +209,7 @@ export class TileLoader {
|
|
|
191
209
|
|
|
192
210
|
const sampler = asset.create();
|
|
193
211
|
|
|
194
|
-
const tile = new
|
|
212
|
+
const tile = new VirtualTextureTile();
|
|
195
213
|
|
|
196
214
|
|
|
197
215
|
tile.data = sampler;
|
|
@@ -201,6 +219,8 @@ export class TileLoader {
|
|
|
201
219
|
|
|
202
220
|
|
|
203
221
|
return tile;
|
|
222
|
+
}, (reason) => {
|
|
223
|
+
console.error(`Failed to load tile ${file_name}, reason:${reason}`);
|
|
204
224
|
})
|
|
205
225
|
.finally(() => {
|
|
206
226
|
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { arrayQuickSort } from "../../../../../core/collection/array/arrayQuickSort.js";
|
|
2
|
+
import { compose_tile_address } from "./tile/compose_tile_address.js";
|
|
3
|
+
import { finger_print_to_tile_address } from "./tile/finger_print_to_tile_address.js";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
export class VirtualTextureUsage {
|
|
5
7
|
|
|
6
8
|
#counts_intrinsic = new Uint32Array(0);
|
|
9
|
+
/**
|
|
10
|
+
* Stores indices of tiles with usage > 0
|
|
11
|
+
* @type {Uint32Array}
|
|
12
|
+
*/
|
|
13
|
+
#occupancy = new Uint32Array(0);
|
|
14
|
+
/**
|
|
15
|
+
* Points at the end of the occupancy list
|
|
16
|
+
* @type {number}
|
|
17
|
+
*/
|
|
18
|
+
#occupancy_cursor = 0;
|
|
7
19
|
|
|
8
20
|
get counts() {
|
|
9
21
|
return this.#counts_intrinsic;
|
|
@@ -11,6 +23,7 @@ export class UsageMetadata {
|
|
|
11
23
|
|
|
12
24
|
#max_mip_level = 0;
|
|
13
25
|
|
|
26
|
+
|
|
14
27
|
set max_mip_level(v) {
|
|
15
28
|
this.#max_mip_level = v;
|
|
16
29
|
|
|
@@ -21,14 +34,21 @@ export class UsageMetadata {
|
|
|
21
34
|
return this.#max_mip_level;
|
|
22
35
|
}
|
|
23
36
|
|
|
37
|
+
|
|
38
|
+
get occupancy() {
|
|
39
|
+
return this.#occupancy;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get occupancy_count() {
|
|
43
|
+
return this.#occupancy_cursor;
|
|
44
|
+
}
|
|
45
|
+
|
|
24
46
|
/**
|
|
25
47
|
*
|
|
26
48
|
*/
|
|
27
49
|
#ensureCapacity() {
|
|
28
50
|
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
const size = finger_print_to_tile_index(finger_print);
|
|
51
|
+
const size = compose_tile_address(this.#max_mip_level + 1, 0, 0);
|
|
32
52
|
|
|
33
53
|
if (this.#counts_intrinsic.length >= size) {
|
|
34
54
|
// already large enough
|
|
@@ -36,12 +56,7 @@ export class UsageMetadata {
|
|
|
36
56
|
}
|
|
37
57
|
|
|
38
58
|
this.#counts_intrinsic = new Uint32Array(size);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
#getIndexBy(mip, x, y) {
|
|
42
|
-
const finger_print = compose_finger_print(mip, x, y);
|
|
43
|
-
|
|
44
|
-
return finger_print_to_tile_index(finger_print);
|
|
59
|
+
this.#occupancy = new Uint32Array(size);
|
|
45
60
|
}
|
|
46
61
|
|
|
47
62
|
/**
|
|
@@ -50,8 +65,7 @@ export class UsageMetadata {
|
|
|
50
65
|
* @returns {number}
|
|
51
66
|
*/
|
|
52
67
|
getCountByFingerprint(fingerprint) {
|
|
53
|
-
const index =
|
|
54
|
-
|
|
68
|
+
const index = finger_print_to_tile_address(fingerprint);
|
|
55
69
|
|
|
56
70
|
return this.#counts_intrinsic[index];
|
|
57
71
|
}
|
|
@@ -64,13 +78,14 @@ export class UsageMetadata {
|
|
|
64
78
|
* @returns {number}
|
|
65
79
|
*/
|
|
66
80
|
getCountBy(mip, x, y) {
|
|
67
|
-
const
|
|
81
|
+
const address = compose_tile_address(mip, x, y);
|
|
68
82
|
|
|
69
|
-
return this
|
|
83
|
+
return this.#counts_intrinsic[address];
|
|
70
84
|
}
|
|
71
85
|
|
|
72
86
|
clear() {
|
|
73
87
|
this.#counts_intrinsic.fill(0);
|
|
88
|
+
this.#occupancy_cursor = 0;
|
|
74
89
|
}
|
|
75
90
|
|
|
76
91
|
/**
|
|
@@ -81,7 +96,7 @@ export class UsageMetadata {
|
|
|
81
96
|
promoteAncestors(bias = 1) {
|
|
82
97
|
|
|
83
98
|
// traverse mip pyramid in reverse, so we can push counts to parents one level at a time
|
|
84
|
-
for (let mip = this.#max_mip_level
|
|
99
|
+
for (let mip = this.#max_mip_level; mip > 0; mip--) {
|
|
85
100
|
|
|
86
101
|
const mip_resolution = 1 << mip;
|
|
87
102
|
|
|
@@ -99,7 +114,7 @@ export class UsageMetadata {
|
|
|
99
114
|
const parent_x = x >>> 1;
|
|
100
115
|
const parent_y = y >>> 1;
|
|
101
116
|
|
|
102
|
-
const parent_index =
|
|
117
|
+
const parent_index = compose_tile_address(parent_level, parent_x, parent_y);
|
|
103
118
|
|
|
104
119
|
const parent_count = this.#counts_intrinsic[parent_index];
|
|
105
120
|
|
|
@@ -107,6 +122,10 @@ export class UsageMetadata {
|
|
|
107
122
|
|
|
108
123
|
if (parent_count < expected_count) {
|
|
109
124
|
this.#counts_intrinsic[parent_index] = expected_count;
|
|
125
|
+
|
|
126
|
+
if (parent_count === 0) {
|
|
127
|
+
this.#append_to_occupancy(parent_index);
|
|
128
|
+
}
|
|
110
129
|
}
|
|
111
130
|
|
|
112
131
|
}
|
|
@@ -115,6 +134,26 @@ export class UsageMetadata {
|
|
|
115
134
|
}
|
|
116
135
|
}
|
|
117
136
|
|
|
137
|
+
/**
|
|
138
|
+
*
|
|
139
|
+
* @param {number} address
|
|
140
|
+
*/
|
|
141
|
+
#append_to_occupancy(address) {
|
|
142
|
+
this.#occupancy[this.#occupancy_cursor] = address;
|
|
143
|
+
this.#occupancy_cursor++;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Sort occupancy list in descending order
|
|
148
|
+
*/
|
|
149
|
+
sortOccupancy() {
|
|
150
|
+
arrayQuickSort(
|
|
151
|
+
this.#occupancy,
|
|
152
|
+
(index) => -this.#counts_intrinsic[index], null,
|
|
153
|
+
0, this.#occupancy_cursor - 1
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
118
157
|
|
|
119
158
|
/**
|
|
120
159
|
*
|
|
@@ -125,7 +164,9 @@ export class UsageMetadata {
|
|
|
125
164
|
|
|
126
165
|
const data_size = data.length;
|
|
127
166
|
|
|
128
|
-
this.#ensureCapacity(
|
|
167
|
+
this.#ensureCapacity();
|
|
168
|
+
|
|
169
|
+
const counts = this.#counts_intrinsic;
|
|
129
170
|
|
|
130
171
|
for (let offset = 0; offset < data_size; offset += 4) {
|
|
131
172
|
|
|
@@ -142,11 +183,16 @@ export class UsageMetadata {
|
|
|
142
183
|
const tile_x = data[offset + 1] & max_tile_value;
|
|
143
184
|
const tile_y = data[offset + 2] & max_tile_value;
|
|
144
185
|
|
|
145
|
-
const
|
|
186
|
+
const tile_address = compose_tile_address(mip_level, tile_x, tile_y);
|
|
187
|
+
|
|
188
|
+
const previous_count = counts[tile_address];
|
|
146
189
|
|
|
147
|
-
|
|
190
|
+
if (previous_count === 0) {
|
|
191
|
+
// first occurrence, mark occupancy
|
|
192
|
+
this.#append_to_occupancy(tile_address);
|
|
193
|
+
}
|
|
148
194
|
|
|
149
|
-
|
|
195
|
+
counts[tile_address] = previous_count + 1;
|
|
150
196
|
}
|
|
151
197
|
|
|
152
198
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ClampToEdgeWrapping,
|
|
3
|
+
DoubleSide,
|
|
3
4
|
GLSL3,
|
|
4
5
|
Matrix4,
|
|
5
6
|
NearestFilter,
|
|
@@ -12,12 +13,14 @@ import {
|
|
|
12
13
|
WebGLRenderTarget
|
|
13
14
|
} from "three";
|
|
14
15
|
import { assert } from "../../../../../core/assert.js";
|
|
16
|
+
import { array_copy } from "../../../../../core/collection/array/array_copy.js";
|
|
15
17
|
import { clamp } from "../../../../../core/math/clamp.js";
|
|
16
18
|
import { max2 } from "../../../../../core/math/max2.js";
|
|
19
|
+
import { generate_halton_jitter } from "../../../generate_halton_jitter.js";
|
|
17
20
|
import { renderScreenSpace } from "../../../render/utils/renderScreenSpace.js";
|
|
18
21
|
import { Sampler2D } from "../../sampler/Sampler2D.js";
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
22
|
+
import { VirtualTextureUsage } from "./VirtualTextureUsage.js";
|
|
23
|
+
import { fragment, vertex } from "./VirtualTextureUsageShader.js";
|
|
21
24
|
|
|
22
25
|
const usage_material_uniforms = {
|
|
23
26
|
"u_mt_params": { value: new Vector2(0.1, 1) },
|
|
@@ -38,6 +41,7 @@ const usage_material = new RawShaderMaterial({
|
|
|
38
41
|
uniforms: usage_material_uniforms,
|
|
39
42
|
vertexShader: vertex(),
|
|
40
43
|
fragmentShader: fragment(),
|
|
44
|
+
side: DoubleSide,
|
|
41
45
|
glslVersion: GLSL3
|
|
42
46
|
|
|
43
47
|
});
|
|
@@ -65,7 +69,24 @@ const clear_usage_material = new RawShaderMaterial({
|
|
|
65
69
|
glslVersion: GLSL3
|
|
66
70
|
});
|
|
67
71
|
|
|
68
|
-
|
|
72
|
+
const scratch_matrix = new Float32Array(16);
|
|
73
|
+
|
|
74
|
+
export class VirtualTextureUsageUpdater {
|
|
75
|
+
|
|
76
|
+
#frame_index = 0;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* In order to avoid aliasing due to the fact that we render at a lower resolution, we move the camera slightly each frame to sweep across texels in-between
|
|
80
|
+
* @type {Float32Array}
|
|
81
|
+
*/
|
|
82
|
+
#frame_jitter_offsets = new Float32Array([0, 0]);
|
|
83
|
+
#frame_jitter_samples = 1;
|
|
84
|
+
#frame_jitter_enabled = false;
|
|
85
|
+
|
|
86
|
+
#initialize_frame_jitter() {
|
|
87
|
+
this.#frame_jitter_samples = this.#usage_resolution_scale;
|
|
88
|
+
this.#frame_jitter_offsets = generate_halton_jitter(this.#frame_jitter_samples);
|
|
89
|
+
}
|
|
69
90
|
|
|
70
91
|
#usage_buffer = new WebGLRenderTarget(1, 1, {
|
|
71
92
|
wrapT: ClampToEdgeWrapping,
|
|
@@ -90,7 +111,7 @@ export class VirtualTextureManager {
|
|
|
90
111
|
*/
|
|
91
112
|
#usage_resolution_scale = 32;
|
|
92
113
|
|
|
93
|
-
#usage_metadata = new
|
|
114
|
+
#usage_metadata = new VirtualTextureUsage();
|
|
94
115
|
|
|
95
116
|
#texture_id = 3;
|
|
96
117
|
#texture_resolution = 65536;
|
|
@@ -115,6 +136,7 @@ export class VirtualTextureManager {
|
|
|
115
136
|
*/
|
|
116
137
|
#usage_texture_bias = 0.1;
|
|
117
138
|
|
|
139
|
+
|
|
118
140
|
/**
|
|
119
141
|
*
|
|
120
142
|
* @param {number} resolution
|
|
@@ -150,6 +172,7 @@ export class VirtualTextureManager {
|
|
|
150
172
|
|
|
151
173
|
constructor() {
|
|
152
174
|
this.#initialize_usage_uniforms();
|
|
175
|
+
this.#initialize_frame_jitter();
|
|
153
176
|
}
|
|
154
177
|
|
|
155
178
|
#initialize_usage_uniforms() {
|
|
@@ -208,6 +231,28 @@ export class VirtualTextureManager {
|
|
|
208
231
|
|
|
209
232
|
}
|
|
210
233
|
|
|
234
|
+
#prepareUsageUniforms(camera) {
|
|
235
|
+
|
|
236
|
+
const uniforms = usage_material.uniforms;
|
|
237
|
+
const usage_buffer = this.#usage_buffer;
|
|
238
|
+
const camera_projection_matrix = camera.projectionMatrix.elements;
|
|
239
|
+
|
|
240
|
+
if (this.#frame_jitter_enabled) {
|
|
241
|
+
// apply jitter to projection matrix
|
|
242
|
+
const jitter_index = this.#frame_index % this.#frame_jitter_samples;
|
|
243
|
+
|
|
244
|
+
const jitter_offset_x = this.#frame_jitter_offsets[jitter_index * 2];
|
|
245
|
+
const jitter_offset_y = this.#frame_jitter_offsets[jitter_index * 2 + 1];
|
|
246
|
+
|
|
247
|
+
camera_projection_matrix[8] = jitter_offset_x / usage_buffer.width;
|
|
248
|
+
camera_projection_matrix[9] = jitter_offset_y / usage_buffer.height;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
uniforms.modelViewMatrix.value.multiplyMatrices(camera.matrixWorldInverse, camera.matrixWorld);
|
|
253
|
+
uniforms.projectionMatrix.value.copy(camera.projectionMatrix);
|
|
254
|
+
}
|
|
255
|
+
|
|
211
256
|
/**
|
|
212
257
|
*
|
|
213
258
|
* @param {WebGLRenderer} renderer
|
|
@@ -218,37 +263,49 @@ export class VirtualTextureManager {
|
|
|
218
263
|
|
|
219
264
|
const usage_buffer = this.#usage_buffer;
|
|
220
265
|
|
|
221
|
-
const uniforms = usage_material.uniforms;
|
|
222
266
|
|
|
223
|
-
|
|
224
|
-
uniforms.projectionMatrix.value.copy(camera.projectionMatrix);
|
|
267
|
+
const camera_projection_matrix = camera.projectionMatrix.elements;
|
|
225
268
|
|
|
226
269
|
// remember existing state
|
|
227
270
|
const _old_render_target = renderer.getRenderTarget();
|
|
228
271
|
const _auto_clear = renderer.autoClear;
|
|
229
|
-
|
|
272
|
+
array_copy(camera_projection_matrix, 0, scratch_matrix, 0, 16);
|
|
230
273
|
const _old_material = scene.overrideMaterial;
|
|
274
|
+
const _old_camera_matrix_update = camera.matrixAutoUpdate;
|
|
275
|
+
|
|
276
|
+
camera.matrixAutoUpdate = false;
|
|
231
277
|
|
|
232
278
|
renderer.autoClear = false;
|
|
233
279
|
renderer.setRenderTarget(usage_buffer);
|
|
234
|
-
scene.overrideMaterial = usage_material;
|
|
235
280
|
|
|
236
281
|
// clear out usage texture
|
|
237
282
|
renderScreenSpace(renderer, clear_usage_material);
|
|
238
283
|
|
|
239
284
|
renderer.clearDepth();
|
|
240
285
|
|
|
286
|
+
scene.overrideMaterial = usage_material;
|
|
287
|
+
|
|
288
|
+
this.#prepareUsageUniforms(camera);
|
|
289
|
+
|
|
241
290
|
renderer.render(scene, camera);
|
|
242
291
|
|
|
243
292
|
scene.overrideMaterial = _old_material;
|
|
244
293
|
|
|
245
294
|
renderer.readRenderTargetPixels(usage_buffer, 0, 0, usage_buffer.width, usage_buffer.height, this.#usage_pixel_data.data);
|
|
246
295
|
|
|
296
|
+
// restore state
|
|
247
297
|
renderer.setRenderTarget(_old_render_target);
|
|
248
298
|
renderer.autoClear = _auto_clear;
|
|
299
|
+
array_copy(scratch_matrix, 0, camera_projection_matrix, 0, 16);
|
|
249
300
|
|
|
301
|
+
camera.matrixAutoUpdate = _old_camera_matrix_update;
|
|
302
|
+
|
|
303
|
+
//
|
|
250
304
|
this.#usage_metadata.fromTexture(this.#usage_pixel_data.data);
|
|
251
305
|
this.#usage_metadata.promoteAncestors(1);
|
|
306
|
+
this.#usage_metadata.sortOccupancy();
|
|
307
|
+
|
|
308
|
+
this.#frame_index++;
|
|
252
309
|
}
|
|
253
310
|
|
|
254
311
|
dispose() {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { CSS_ABSOLUTE_POSITIONING } from "../../../../../../view/CSS_ABSOLUTE_POSITIONING.js";
|
|
2
|
+
import { CanvasView } from "../../../../../../view/elements/CanvasView.js";
|
|
3
|
+
import EmptyView from "../../../../../../view/elements/EmptyView.js";
|
|
4
|
+
import { sampler2d_write_to_canvas_raw } from "../../../sampler/sampler2d_write_to_canvas_raw.js";
|
|
5
|
+
|
|
6
|
+
export class ResidencyDebugView extends EmptyView {
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @type {PageTexture|null}
|
|
10
|
+
*/
|
|
11
|
+
texture = null;
|
|
12
|
+
|
|
13
|
+
#canvas = new CanvasView();
|
|
14
|
+
|
|
15
|
+
#previous_residency = new Uint32Array(1024);
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
super({
|
|
19
|
+
css: {
|
|
20
|
+
position: "absolute",
|
|
21
|
+
boxShadow: "0 0 8px black",
|
|
22
|
+
background: "black"
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
this.#canvas.css(CSS_ABSOLUTE_POSITIONING);
|
|
27
|
+
|
|
28
|
+
this.addChild(this.#canvas);
|
|
29
|
+
|
|
30
|
+
this.#previous_residency.fill(-1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
update() {
|
|
34
|
+
|
|
35
|
+
const t = this.texture;
|
|
36
|
+
if (t === null) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const canvas = this.#canvas;
|
|
41
|
+
canvas.size.readFromArray(t.page_texture_resolution);
|
|
42
|
+
|
|
43
|
+
this.size.copy(canvas.size);
|
|
44
|
+
|
|
45
|
+
const residentTiles = t.resident_tiles;
|
|
46
|
+
|
|
47
|
+
const temp = new CanvasView();
|
|
48
|
+
const tile_resolution = t.tile_resolution;
|
|
49
|
+
temp.size.setScalar(tile_resolution);
|
|
50
|
+
|
|
51
|
+
const tile_columns = t.page_texture_resolution[0] / tile_resolution;
|
|
52
|
+
|
|
53
|
+
for (let i = 0; i < residentTiles.length; i++) {
|
|
54
|
+
const tile = residentTiles[i];
|
|
55
|
+
|
|
56
|
+
const page_slot = tile.page_slot;
|
|
57
|
+
if (this.#previous_residency[page_slot] === tile.finder_print) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
sampler2d_write_to_canvas_raw(tile.data, temp.el);
|
|
62
|
+
const column = page_slot % tile_columns;
|
|
63
|
+
const row = (page_slot / tile_columns) | 0;
|
|
64
|
+
|
|
65
|
+
canvas.context2d.drawImage(temp.el, 0, 0, tile_resolution, tile_resolution, tile_resolution * column, tile_resolution * row, tile_resolution, tile_resolution);
|
|
66
|
+
|
|
67
|
+
this.#previous_residency[page_slot] = tile.finder_print;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import LabelView from "../../../../../../view/common/LabelView.js";
|
|
2
|
+
import EmptyView from "../../../../../../view/elements/EmptyView.js";
|
|
3
|
+
import { decompose_finger_print } from "../tile/decompose_finger_print.js";
|
|
4
|
+
import { tile_address_to_finger_print } from "../tile/tile_address_to_finger_print.js";
|
|
5
|
+
|
|
6
|
+
export class UsageDebugView extends EmptyView {
|
|
7
|
+
#tileCount = new LabelView("")
|
|
8
|
+
#tiles = new EmptyView();
|
|
9
|
+
#mip_levels = 0;
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
constructor(opt) {
|
|
13
|
+
super(opt);
|
|
14
|
+
|
|
15
|
+
this.addChild(this.#tileCount);
|
|
16
|
+
this.addChild(this.#tiles);
|
|
17
|
+
|
|
18
|
+
this.css({
|
|
19
|
+
position: "absolute",
|
|
20
|
+
left: "0",
|
|
21
|
+
top: "0",
|
|
22
|
+
background: "rgba(255,255,255,0.5)",
|
|
23
|
+
fontFamily: "monospace",
|
|
24
|
+
fontSize: "10px"
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
set mip_levels(v) {
|
|
29
|
+
this.#mip_levels = v;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
*
|
|
34
|
+
* @param {VirtualTextureUsage} usage
|
|
35
|
+
*/
|
|
36
|
+
set usage(usage) {
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
this.#tiles.removeAllChildren();
|
|
40
|
+
|
|
41
|
+
const occupancy = usage.occupancy;
|
|
42
|
+
const occupancyCount = usage.occupancy_count;
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < occupancyCount; i++) {
|
|
45
|
+
const occupancy_index = occupancy[i];
|
|
46
|
+
const fingerPrint = tile_address_to_finger_print(occupancy_index);
|
|
47
|
+
|
|
48
|
+
const count = usage.getCountByFingerprint(fingerPrint);
|
|
49
|
+
|
|
50
|
+
if (count <= 0) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { mip, x, y } = decompose_finger_print(fingerPrint);
|
|
55
|
+
|
|
56
|
+
this.#tiles.addChild(new LabelView(`ID: ${0} Level: ${mip} X: ${x} Y: ${y} USAGE: ${count}`));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
this.#tileCount.updateText(`Tile Count: ${occupancyCount}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
}
|