@woosh/meep-engine 2.33.5 → 2.33.6

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 (35) hide show
  1. package/core/collection/RingBuffer.js +40 -10
  2. package/core/collection/array/typed/typed_array_copy.js +2 -2
  3. package/core/geom/3d/aabb/aabb3_compute_projected_area.js +5 -4
  4. package/core/process/undo/ActionProcessor.d.ts +2 -0
  5. package/core/process/undo/ActionProcessor.js +59 -1
  6. package/core/process/undo/ActionProcessor.spec.js +59 -0
  7. package/core/process/undo/Mark.js +2 -1
  8. package/engine/asset/loaders/material/bitmap2sampler_gl.js +19 -0
  9. package/engine/asset/loaders/material/computeImageBitmapEquality.js +7 -19
  10. package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +25 -16
  11. package/engine/graphics/material/SplatMaterial.js +4 -97
  12. package/engine/graphics/micron/build/buildMicronGeometryFromBufferGeometry.js +1 -5
  13. package/engine/graphics/micron/build/fill_patch_geometry_data.js +2 -0
  14. package/engine/graphics/micron/format/MicronGeometryPatch.js +11 -3
  15. package/engine/graphics/micron/format/MicronVertexDataSpec.js +25 -3
  16. package/engine/graphics/micron/render/VirtualGeometryBuilder.js +24 -8
  17. package/engine/graphics/micron/render/refinement/ActivePatchList.js +6 -25
  18. package/engine/graphics/micron/render/refinement/RefinementSpec.js +98 -0
  19. package/engine/graphics/micron/render/refinement/array_normalize_plane.js +25 -0
  20. package/engine/graphics/micron/render/refinement/array_setFromProjectionMatrix.js +60 -0
  21. package/engine/graphics/micron/render/v1/MaterialVertexSpec.js +21 -0
  22. package/engine/graphics/micron/render/v1/VGThreeRenderer.js +12 -9
  23. package/engine/graphics/render/buffer/buffers/ColorAndDepthFrameBuffer.js +5 -3
  24. package/engine/graphics/render/forward_plus/prototypeLightManager.js +1 -1
  25. package/engine/graphics/render/visibility/hiz/prototypeHiZ.js +1 -1
  26. package/engine/graphics/shadows/ShadowMapRenderer.js +12 -2
  27. package/engine/graphics/texture/cubemap/load_environment_map.js +29 -3
  28. package/engine/graphics/texture/sampler/Sampler2D.js +18 -62
  29. package/engine/graphics/texture/sampler/debug/paintSamplerOnHTML.js +3 -2
  30. package/engine/graphics/texture/sampler/differenceSampler.js +31 -0
  31. package/engine/graphics/texture/sampler/typedArrayConstructorByInstance.js +25 -0
  32. package/engine/graphics/texture/sampler/util/drawSamplerHTML.js +3 -2
  33. package/package.json +1 -1
  34. package/view/minimap/gl/MinimapMarkersGL.js +2 -2
  35. package/engine/graphics/micron/render/RefinementSpec.js +0 -181
@@ -2,6 +2,8 @@ import { isArrayEqual } from "../../../../core/collection/ArrayUtils.js";
2
2
  import { computeHashArray } from "../../../../core/math/MathUtils.js";
3
3
  import { invokeObjectHash } from "../../../../core/model/object/invokeObjectHash.js";
4
4
 
5
+ const DEFAULT_HASH = 123456;
6
+
5
7
  export class MicronVertexDataSpec {
6
8
  constructor() {
7
9
  /**
@@ -12,9 +14,21 @@ export class MicronVertexDataSpec {
12
14
 
13
15
  /**
14
16
  *
15
- * @type {RowFirstTableSpec|null}
17
+ * @type {number}
18
+ * @private
16
19
  */
17
- this.data = null;
20
+ this.__hash = DEFAULT_HASH;
21
+ }
22
+
23
+ /**
24
+ *
25
+ * @param {MicronGeometryBufferAttributeSpec[]} attributes
26
+ */
27
+ setAttributes(attributes) {
28
+ this.attributes = attributes;
29
+
30
+ // reset hash to trigger hash update
31
+ this.__hash = DEFAULT_HASH;
18
32
  }
19
33
 
20
34
  /**
@@ -30,10 +44,18 @@ export class MicronVertexDataSpec {
30
44
  return isArrayEqual(this.attributes, other.attributes);
31
45
  }
32
46
 
33
- hash() {
47
+ computeHash() {
34
48
  return computeHashArray(this.attributes, invokeObjectHash);
35
49
  }
36
50
 
51
+ hash() {
52
+ if (this.__hash === DEFAULT_HASH) {
53
+ this.__hash = this.computeHash();
54
+ }
55
+
56
+ return this.__hash;
57
+ }
58
+
37
59
  /**
38
60
  *
39
61
  * @param {string} name
@@ -2,19 +2,33 @@ import { Frustum, Matrix4 } from "three";
2
2
  import { array_copy } from "../../../../core/collection/array/copyArray.js";
3
3
  import Vector2 from "../../../../core/geom/Vector2.js";
4
4
  import { MicronGeometryPatchOccurrence } from "../format/MicronGeometryPatchOccurance.js";
5
- import { RefinementSpec } from "./RefinementSpec.js";
5
+ import { RefinementSpec } from "./refinement/RefinementSpec.js";
6
6
  import { ActivePatchList } from "./refinement/ActivePatchList.js";
7
7
  import { ActivePatchFlags } from "./refinement/ActivePatchFlags.js";
8
8
 
9
-
9
+ /**
10
+ * @readonly
11
+ * @type {RefinementSpec}
12
+ */
10
13
  const refinement_spec = new RefinementSpec();
11
14
 
12
15
  export class VirtualGeometryBuilder {
13
16
  constructor() {
14
17
  this.view_projection_matrix = new Matrix4();
15
- this.matrix_projection = new Matrix4();
18
+
19
+ /**
20
+ *
21
+ * @type {Float32Array|number[]|mat4}
22
+ */
23
+ this.matrix_projection = new Float32Array(16);
24
+
16
25
  this.matrix_projection_inverse = new Matrix4();
17
- this.matrix_world_inverse = new Matrix4();
26
+
27
+ /**
28
+ *
29
+ * @type {Float32Array|number[]|mat4}
30
+ */
31
+ this.matrix_world_inverse = new Float32Array(16);
18
32
 
19
33
  /**
20
34
  *
@@ -76,7 +90,7 @@ export class VirtualGeometryBuilder {
76
90
  this.__flags__enforce_dependency_splits = true;
77
91
  }
78
92
 
79
- dropCache(){
93
+ dropCache() {
80
94
  this.__acl.clear();
81
95
  }
82
96
 
@@ -98,8 +112,10 @@ export class VirtualGeometryBuilder {
98
112
  camera.updateMatrixWorld(true);
99
113
 
100
114
  this.view_projection_matrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
101
- this.matrix_world_inverse.copy(camera.matrixWorldInverse);
102
- this.matrix_projection.copy(camera.projectionMatrix);
115
+
116
+ this.matrix_world_inverse.set(camera.matrixWorldInverse.elements);
117
+ this.matrix_projection.set(camera.projectionMatrix.elements);
118
+
103
119
  this.matrix_projection_inverse.copy(camera.projectionMatrixInverse);
104
120
 
105
121
  this.view_frustum.setFromProjectionMatrix(this.view_projection_matrix);
@@ -170,7 +186,7 @@ export class VirtualGeometryBuilder {
170
186
  apl
171
187
  ) {
172
188
 
173
- refinement_spec.build(transform, this.matrix_world_inverse, this.matrix_projection);
189
+ refinement_spec.build(transform.elements, this.matrix_world_inverse, this.matrix_projection);
174
190
 
175
191
  const output = this.output;
176
192
 
@@ -185,6 +185,8 @@ export class ActivePatchList {
185
185
  refine(spec) {
186
186
 
187
187
  const frustum_planes = spec.frustum_f32;
188
+ const projection_matrix = spec.projection_matrix;
189
+ const error_threshold = spec.error_threshold_normalized;
188
190
 
189
191
  let record = this.records
190
192
 
@@ -199,8 +201,7 @@ export class ActivePatchList {
199
201
  check if node is in view frustum
200
202
  NOTE: following suggestion in "FastMesh: Efficient View-dependent Meshing" by Renato Pajarola et al, we can do a more coarse frustum test approximating frustum as a cone initially
201
203
  */
202
- const bounding_box = node.bounding_box;
203
- const in_view_frustum = aabb3_intersects_frustum(bounding_box, frustum_planes);
204
+ const in_view_frustum = aabb3_intersects_frustum(node.bounding_box, frustum_planes);
204
205
 
205
206
  if (!in_view_frustum) {
206
207
  // outside of view frustum, cull
@@ -211,21 +212,6 @@ export class ActivePatchList {
211
212
  continue;
212
213
  }
213
214
 
214
- // compute projected bounds of the patch
215
- // const patch_screen_area = compute_projected_area(bounding_box, spec);
216
-
217
- // const patch_is_too_small_to_be_seen = patch_screen_area < spec.error_threshold;
218
- //
219
- // if (patch_is_too_small_to_be_seen) {
220
- // // the whole patch is too small, cull
221
- // if (prev_is_visible) {
222
- // record.clearFlag(ActivePatchFlags.Visible);
223
- // }
224
- //
225
- // // try to merge with sibling
226
- // continue;
227
- // }
228
-
229
215
  if (!prev_is_visible) {
230
216
  record.setFlag(ActivePatchFlags.Visible);
231
217
  }
@@ -243,22 +229,17 @@ export class ActivePatchList {
243
229
  // not the lowest level of LOD, see if subdivision might be necessary
244
230
 
245
231
  // compute average triangle area
246
- const group_screen_area = aabb3_project_to_2d(node.group_bounding_box_corners, spec.projection_matrix);
232
+ const group_screen_area = aabb3_project_to_2d(node.group_bounding_box_corners, projection_matrix);
247
233
  const screen_space_error = node.group_error * group_screen_area;
248
234
 
249
-
250
- if (screen_space_error > spec.error_threshold_normalized) {
235
+ if (screen_space_error > error_threshold) {
251
236
  // error too large, needs to be split
252
237
  record = this.node_split(record);
253
238
  continue;
254
239
  }
255
240
  }
256
- record = record.link_next;
257
241
 
258
- // check if record and its sibling can be merged
259
- // if (approximate_triangle_area < spec.error_threshold) {
260
- // this.node_try_merge(record, spec);
261
- // }
242
+ record = record.link_next;
262
243
  }
263
244
  }
264
245
  }
@@ -0,0 +1,98 @@
1
+ import Vector2 from "../../../../../core/geom/Vector2.js";
2
+ import { mat4 } from "gl-matrix";
3
+ import { array_setFromProjectionMatrix } from "./array_setFromProjectionMatrix.js";
4
+
5
+ export class RefinementSpec {
6
+ constructor() {
7
+
8
+ /**
9
+ * Viewport resolution
10
+ * @type {Vector2}
11
+ */
12
+ this.resolution = new Vector2();
13
+
14
+ /**
15
+ * Number of pixels in the viewport
16
+ * @type {number}
17
+ */
18
+ this.viewport_area = 0;
19
+
20
+ /**
21
+ * How much error to accept when deciding to subdivide a cluster
22
+ * Measured in pixels
23
+ * Higher value will result in better performance but more visible artifacts
24
+ * @type {number}
25
+ */
26
+ this.error_threshold = 1;
27
+
28
+ /**
29
+ * Error threshold as a fraction of the screen area instead of pixels, derived internally from pixel value
30
+ * @type {number}
31
+ */
32
+ this.error_threshold_normalized = 1;
33
+
34
+ /**
35
+ * Continuous memory region for faster access
36
+ * @type {ArrayBuffer}
37
+ */
38
+ const array_buffer = new ArrayBuffer(160);
39
+
40
+ /**
41
+ * Object-space camera frustum
42
+ * Frustum planes in compact form
43
+ * @type {Float32Array}
44
+ */
45
+ this.frustum_f32 = new Float32Array(array_buffer, 0, 24);
46
+
47
+
48
+ /**
49
+ * Contains transformation from camera space to object space
50
+ * @type {Float32Array|number[]|mat4}
51
+ */
52
+ this.projection_matrix = new Float32Array(array_buffer, 24 * 4, 16);
53
+
54
+ /**
55
+ * Model world transform
56
+ * @type {Float32Array|number[]|mat4}
57
+ */
58
+ // this.transform = new Float32Array(16);
59
+
60
+ /**
61
+ * Object-space camera position
62
+ * @type {Float32Array}
63
+ */
64
+ this.view_position = new Float32Array(3);
65
+ }
66
+
67
+ get frustum() {
68
+ throw new Error('deprecated, use .frustum_f32 instead');
69
+ }
70
+
71
+ setResolution(x, y) {
72
+ this.resolution.set(x, y);
73
+
74
+ this.viewport_area = x * y;
75
+
76
+ this.error_threshold_normalized = this.error_threshold / this.viewport_area;
77
+ }
78
+
79
+ /**
80
+ *
81
+ * @param {number[]|mat4|Float32Array|ArrayLike<number>} transform world-space object transform
82
+ * @param {number[]|mat4|Float32Array|ArrayLike<number>} matrix_world_inverse camera's world inverse matrix
83
+ * @param {number[]|mat4|Float32Array|ArrayLike<number>} matrix_projection camera's projection matrix
84
+ */
85
+ build(transform, matrix_world_inverse, matrix_projection) {
86
+ // const _transform = this.transform;
87
+ // _transform.set(transform);
88
+
89
+ // build projection matrix
90
+ const projection_matrix = this.projection_matrix;
91
+
92
+ mat4.multiply(projection_matrix, matrix_world_inverse, transform);
93
+ mat4.multiply(projection_matrix, matrix_projection, projection_matrix);
94
+
95
+ // compute view frustum in model-space
96
+ array_setFromProjectionMatrix(this.frustum_f32, projection_matrix);
97
+ }
98
+ }
@@ -0,0 +1,25 @@
1
+ import { v3_length } from "../../../../../core/geom/Vector3.js";
2
+
3
+ /**
4
+ * Normalize a plane in-place
5
+ * @param {number[]} source
6
+ * @param {number} source_offset
7
+ */
8
+ function array_normalize_plane(source, source_offset) {
9
+ const _x = source[source_offset];
10
+ const _y = source[source_offset + 1];
11
+ const _z = source[source_offset + 2];
12
+
13
+ const length = v3_length(_x, _y, _z);
14
+
15
+ const inverseNormalLength = 1.0 / length;
16
+
17
+ /*
18
+ By re-using values already in the registers instead of using *= we save a few extra READ ops
19
+ */
20
+ source[source_offset] = _x * inverseNormalLength;
21
+ source[source_offset + 1] = _y * inverseNormalLength;
22
+ source[source_offset + 2] = _z * inverseNormalLength;
23
+
24
+ source[source_offset + 3] *= inverseNormalLength;
25
+ }
@@ -0,0 +1,60 @@
1
+ import { v3_length } from "../../../../../core/geom/Vector3.js";
2
+
3
+ /**
4
+ *
5
+ * @param {number[]} destination
6
+ * @param {number} destination_offset
7
+ * @param {number} x
8
+ * @param {number} y
9
+ * @param {number} z
10
+ * @param {number} w
11
+ */
12
+ function array_set_plane_normalized(destination, destination_offset, x, y, z, w) {
13
+ const length = v3_length(x, y, z);
14
+
15
+ const inverseNormalLength = 1.0 / length;
16
+
17
+ destination[destination_offset] = x * inverseNormalLength;
18
+ destination[destination_offset + 1] = y * inverseNormalLength;
19
+ destination[destination_offset + 2] = z * inverseNormalLength;
20
+ destination[destination_offset + 3] = w * inverseNormalLength;
21
+ }
22
+
23
+ /**
24
+ *
25
+ * @param {number[]|Float32Array} frustum_planes
26
+ * @param {number[]} me
27
+ */
28
+ export function array_setFromProjectionMatrix(frustum_planes, me) {
29
+
30
+ const me0 = me[0];
31
+ const me3 = me[3];
32
+
33
+ const me4 = me[4];
34
+ const me7 = me[7];
35
+
36
+ const me8 = me[8];
37
+ const me11 = me[11];
38
+
39
+ const me12 = me[12];
40
+ const me15 = me[15];
41
+
42
+ array_set_plane_normalized(frustum_planes, 0, me3 - me0, me7 - me4, me11 - me8, me15 - me12);
43
+ array_set_plane_normalized(frustum_planes, 4, me3 + me0, me7 + me4, me11 + me8, me15 + me12);
44
+
45
+ const me1 = me[1];
46
+ const me5 = me[5];
47
+ const me9 = me[9];
48
+ const me13 = me[13];
49
+
50
+ array_set_plane_normalized(frustum_planes, 8, me3 + me1, me7 + me5, me11 + me9, me15 + me13);
51
+ array_set_plane_normalized(frustum_planes, 12, me3 - me1, me7 - me5, me11 - me9, me15 - me13);
52
+
53
+ const me2 = me[2];
54
+ const me6 = me[6];
55
+ const me10 = me[10];
56
+ const me14 = me[14];
57
+
58
+ array_set_plane_normalized(frustum_planes, 16, me3 - me2, me7 - me6, me11 - me10, me15 - me14);
59
+ array_set_plane_normalized(frustum_planes, 20, me3 + me2, me7 + me6, me11 + me10, me15 + me14);
60
+ }
@@ -12,6 +12,27 @@ export class MaterialVertexSpec {
12
12
  this.material = null;
13
13
  }
14
14
 
15
+ /**
16
+ *
17
+ * @param {MaterialVertexSpec} other
18
+ */
19
+ copy(other) {
20
+ this.spec = other.spec;
21
+ this.material = other.material;
22
+ }
23
+
24
+ /**
25
+ *
26
+ * @return {MaterialVertexSpec}
27
+ */
28
+ clone() {
29
+ const r = new MaterialVertexSpec();
30
+
31
+ r.copy(this);
32
+
33
+ return r;
34
+ }
35
+
15
36
  /**
16
37
  * @param {MicronVertexDataSpec} spec
17
38
  * @param {Material} material
@@ -7,6 +7,12 @@ import { HashMap } from "../../../../../core/collection/HashMap.js";
7
7
  import Signal from "../../../../../core/events/signal/Signal.js";
8
8
  import { array_copy } from "../../../../../core/collection/array/copyArray.js";
9
9
 
10
+ /**
11
+ *
12
+ * @type {MaterialVertexSpec}
13
+ */
14
+ const scratch_mvc = new MaterialVertexSpec();
15
+
10
16
  export class VGThreeRenderer {
11
17
  constructor() {
12
18
  this.geometry = new VirtualGeometry();
@@ -32,13 +38,6 @@ export class VGThreeRenderer {
32
38
  */
33
39
  this.__contexts_array = [];
34
40
 
35
- /**
36
- *
37
- * @type {Scene|null}
38
- * @private
39
- */
40
- this.__scene = null;
41
-
42
41
  /**
43
42
  *
44
43
  * @type {Object3D[]}
@@ -75,14 +74,18 @@ export class VGThreeRenderer {
75
74
  * @private
76
75
  */
77
76
  __obtain_material(spec, m) {
78
- const key = MaterialVertexSpec.from(spec, m);
77
+ scratch_mvc.material = m;
78
+ scratch_mvc.spec = spec;
79
79
 
80
- const existing = this.material_contexts.get(key);
80
+ const existing = this.material_contexts.get(scratch_mvc);
81
81
 
82
82
  if (existing !== undefined) {
83
83
  return existing;
84
84
  }
85
85
 
86
+ // create a separate instance to be stored alongside the context
87
+ const key = scratch_mvc.clone();
88
+
86
89
  const ctx = new MaterialContext(spec, m);
87
90
 
88
91
  ctx.init(this.__gl_context);
@@ -1,9 +1,10 @@
1
1
  import { FrameBuffer } from "../FrameBuffer.js";
2
2
  import {
3
+ DepthFormat,
3
4
  DepthTexture,
4
5
  FloatType,
5
6
  NearestFilter,
6
- RGBAFormat,
7
+ RGBFormat,
7
8
  sRGBEncoding,
8
9
  Vector2,
9
10
  WebGLMultisampleRenderTarget
@@ -39,9 +40,9 @@ export class ColorAndDepthFrameBuffer extends FrameBuffer {
39
40
 
40
41
  renderer.getSize(size);
41
42
 
42
- const target = new WebGLMultisampleRenderTarget(size.x, size.y);
43
+ const target = new WebGLMultisampleRenderTarget(size.x, size.y,{ignoreDepth: false});
43
44
 
44
- target.texture.format = RGBAFormat; // note, three.js required RGBA render texture, even though RGB would do here
45
+ target.texture.format = RGBFormat; // note, three.js required RGBA render texture, even though RGB would do here
45
46
  target.texture.minFilter = NearestFilter;
46
47
  target.texture.magFilter = NearestFilter;
47
48
  target.texture.generateMipmaps = false;
@@ -51,6 +52,7 @@ export class ColorAndDepthFrameBuffer extends FrameBuffer {
51
52
  target.depthBuffer = true;
52
53
 
53
54
  target.depthTexture = new DepthTexture();
55
+ target.depthTexture.format = DepthFormat;
54
56
  target.depthTexture.type = FloatType;
55
57
  target.depthTexture.generateMipmaps = false;
56
58
  target.depthTexture.internalFormat = 'DEPTH_COMPONENT32F';
@@ -233,7 +233,7 @@ function prepare_scene_0() {
233
233
 
234
234
  controls.minDistance = 2;
235
235
 
236
- for (let i = 0; i < 5000; i++) {
236
+ for (let i = 0; i < 500; i++) {
237
237
  const radius = randomFloatBetween(random, 4, 4);
238
238
  const intensity = randomFloatBetween(random, 2, 2);
239
239
  addPointLight([
@@ -65,7 +65,7 @@ import LabelView from "../../../../../view/common/LabelView.js";
65
65
  import { randomFloatBetween } from "../../../../../core/math/MathUtils.js";
66
66
  import { seededRandom } from "../../../../../core/math/random/seededRandom.js";
67
67
  import { Sampler2D } from "../../../texture/sampler/Sampler2D.js";
68
- import { RefinementSpec } from "../../../micron/render/RefinementSpec.js";
68
+ import { RefinementSpec } from "../../../micron/render/refinement/RefinementSpec.js";
69
69
  import { Matrix4 } from "three";
70
70
  import { inverseLerp } from "../../../../../core/math/inverseLerp.js";
71
71
  import { clamp } from "../../../../../core/math/clamp.js";
@@ -64,7 +64,6 @@ export class ShadowMapRenderer {
64
64
  this.__renderer = renderer;
65
65
 
66
66
  this.__ensure_map(shadow, renderer);
67
- shadow_camera.updateProjectionMatrix();
68
67
 
69
68
  // draw scene from perspective of shadow camera into the render texture
70
69
 
@@ -92,7 +91,7 @@ export class ShadowMapRenderer {
92
91
 
93
92
  renderer.clear(true, true, false);
94
93
 
95
- shadow.updateMatrices(light);
94
+ shadow.updateMatrices(light, 0);
96
95
 
97
96
  this.onBeforeRender.send3(renderer, shadow_camera, scene);
98
97
 
@@ -123,6 +122,16 @@ export class ShadowMapRenderer {
123
122
  __do_vsm_pass(shadow) {
124
123
  const _renderer = this.__renderer;
125
124
 
125
+ if (shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples) {
126
+
127
+ shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples;
128
+ shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples;
129
+
130
+ shadowMaterialVertical.needsUpdate = true;
131
+ shadowMaterialHorizontal.needsUpdate = true;
132
+
133
+ }
134
+
126
135
  // vertical pass
127
136
 
128
137
  const vertical = shadowMaterialVertical.uniforms;
@@ -181,6 +190,7 @@ export class ShadowMapRenderer {
181
190
  shadow.map = new WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
182
191
  shadow.map.texture.name = '.shadowMap';
183
192
 
193
+ shadow.camera.updateProjectionMatrix();
184
194
  }
185
195
  }
186
196
  }
@@ -2,6 +2,7 @@ import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader.js";
2
2
  import { CubeTextureLoader, LinearFilter, PMREMGenerator, sRGBEncoding, TextureLoader, UnsignedByteType } from "three";
3
3
  import { noop } from "../../../../core/function/Functions.js";
4
4
  import { computeFileExtension } from "../../../../core/FilePath.js";
5
+ import { HDRCubeTextureLoader } from "three/examples/jsm/loaders/HDRCubeTextureLoader.js";
5
6
 
6
7
  /**
7
8
  *
@@ -11,6 +12,28 @@ import { computeFileExtension } from "../../../../core/FilePath.js";
11
12
  function load_cube_texture(paths) {
12
13
  // piece-wise cubemap, a collection of images for each face
13
14
  const cubeTextureLoader = new CubeTextureLoader();
15
+ return new Promise((resolve, reject) => {
16
+ cubeTextureLoader.load(
17
+ paths,
18
+ texture => {
19
+ texture.magFilter = LinearFilter;
20
+ texture.encoding = sRGBEncoding;
21
+ resolve(texture);
22
+ },
23
+ noop,
24
+ reject
25
+ );
26
+ });
27
+ }
28
+
29
+ /**
30
+ *
31
+ * @param {string[]|string} paths
32
+ * @return {Promise<THREE.CubeTexture>}
33
+ */
34
+ function load_hdr_cube_texture(paths) {
35
+ // piece-wise cubemap, a collection of images for each face
36
+ const cubeTextureLoader = new HDRCubeTextureLoader();
14
37
  return new Promise((resolve, reject) => {
15
38
  cubeTextureLoader.load(
16
39
  paths,
@@ -78,10 +101,13 @@ export async function load_environment_map({ path, renderer, original = false, f
78
101
  let texture;
79
102
 
80
103
  if (Array.isArray(path)) {
81
- texture = await load_cube_texture(path);
104
+ const ext = computeFileExtension(path[0]);
82
105
 
83
- texture.magFilter = LinearFilter;
84
- texture.encoding = sRGBEncoding;
106
+ if (ext === 'hdr') {
107
+ texture = await load_hdr_cube_texture(path);
108
+ } else {
109
+ texture = await load_cube_texture(path);
110
+ }
85
111
 
86
112
  type = 'c';
87
113