@woosh/meep-engine 2.60.0 → 2.61.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.
Files changed (65) hide show
  1. package/build/meep.cjs +20211 -20240
  2. package/build/meep.min.js +1 -1
  3. package/build/meep.module.js +20211 -20240
  4. package/package.json +1 -1
  5. package/src/core/binary/BitSet.js +1 -1
  6. package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.js +30 -182
  7. package/src/core/geom/3d/sphere/harmonics/sh3_dering_optimize_positive.spec.js +27 -1
  8. package/src/core/geom/ConicRay.js +16 -21
  9. package/src/core/geom/ConicRay.spec.js +24 -0
  10. package/src/core/geom/packing/miniball/Miniball.js +68 -117
  11. package/src/core/geom/packing/miniball/Miniball.spec.js +3 -3
  12. package/src/core/geom/packing/miniball/Subspan.js +47 -34
  13. package/src/core/geom/packing/miniball/miniball_compute_quality.js +64 -0
  14. package/src/core/math/bessel_3.js +1 -0
  15. package/src/core/math/random/randomBytes.js +2 -2
  16. package/src/core/math/sqr.js +8 -0
  17. package/src/core/model/node-graph/Connection.js +21 -23
  18. package/src/core/model/node-graph/DataType.js +16 -17
  19. package/src/core/model/node-graph/NodeGraph.js +49 -50
  20. package/src/core/model/node-graph/node/NodeDescription.js +42 -44
  21. package/src/core/model/node-graph/node/NodeInstance.js +59 -60
  22. package/src/core/model/node-graph/node/NodeInstancePortReference.js +27 -29
  23. package/src/core/model/node-graph/node/NodeRegistry.js +16 -18
  24. package/src/core/model/node-graph/node/Port.js +35 -37
  25. package/src/core/model/node-graph/node/parameter/NodeParameterDescription.js +27 -13
  26. package/src/core/path/computePathDirectory.spec.js +8 -0
  27. package/src/core/process/BaseProcess.d.ts +5 -0
  28. package/src/core/process/WatchDog.js +76 -75
  29. package/src/core/process/action/AsynchronousAction.js +24 -22
  30. package/src/core/process/executor/profile/Profile.js +34 -24
  31. package/src/core/process/executor/profile/TraceEvent.js +75 -75
  32. package/src/core/process/worker/OnDemandWorkerManager.js +27 -30
  33. package/src/core/process/worker/WorkerBuilder.js +149 -149
  34. package/src/core/process/worker/WorkerProxy.js +25 -21
  35. package/src/core/process/worker/extractTransferables.js +2 -2
  36. package/src/engine/Engine.js +58 -53
  37. package/src/engine/EngineConfiguration.d.ts +4 -4
  38. package/src/engine/ecs/EntityManager.js +517 -614
  39. package/src/engine/ecs/System.js +2 -2
  40. package/src/engine/ecs/transform/Transform.d.ts +7 -5
  41. package/src/engine/ecs/transform/Transform.js +30 -16
  42. package/src/engine/ecs/validateSystem.js +89 -0
  43. package/src/engine/graphics/GraphicsEngine.js +433 -483
  44. package/src/engine/graphics/camera/testClippingPlaneComputation.js +46 -48
  45. package/src/engine/graphics/ecs/camera/Camera.js +11 -11
  46. package/src/engine/graphics/ecs/decal/v2/FPDecalSystem.js +2 -2
  47. package/src/engine/graphics/ecs/mesh-v2/ShadedGeometrySystem.js +2 -2
  48. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMeshSystem.js +2 -2
  49. package/src/engine/graphics/ecs/path/tube/prototypeAnimatedPathMask.js +60 -62
  50. package/src/engine/graphics/ecs/water2/shader/testWaterShader.js +20 -22
  51. package/src/engine/graphics/geometry/instancing/InstancedMeshGroup.js +15 -4
  52. package/src/engine/graphics/particles/particular/engine/ParticularEngine.js +156 -180
  53. package/src/engine/graphics/particles/particular/engine/utils/volume/prototypeParticleVolume.js +69 -71
  54. package/src/engine/graphics/render/buffer/buffers/prototypeNormalFrameBuffer.js +51 -53
  55. package/src/engine/graphics/render/forward_plus/plugin/ptototypeFPPlugin.js +67 -69
  56. package/src/engine/graphics/render/visibility/hiz/prototypeHiZ.js +56 -58
  57. package/src/engine/graphics/shadows/testShadowMapRendering.js +30 -34
  58. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_lanczos.spec.js +22 -20
  59. package/src/engine/graphics/texture/sampler/resize/sampler2d_scale_down_linear.js +10 -13
  60. package/src/engine/graphics/texture/virtual/VirtualTexture.spec.js +1 -1
  61. package/src/engine/plugin/EnginePluginManager.d.ts +6 -1
  62. package/src/engine/ecs/components/ClingToHeightMap.js +0 -19
  63. package/src/engine/ecs/components/SynchronizePosition.js +0 -15
  64. package/src/engine/ecs/systems/ClingToHeightMapSystem.js +0 -170
  65. package/src/engine/ecs/systems/SynchronizePositionSystem.js +0 -43
@@ -13,31 +13,30 @@ import {
13
13
  VSMShadowMap,
14
14
  WebGLRenderer
15
15
  } from "three";
16
+ import {assert} from "../../core/assert.js";
16
17
 
17
- import Signal from "../../core/events/signal/Signal.js";
18
+ import {BinaryNode} from "../../core/bvh2/BinaryNode.js";
18
19
 
19
- import { BinaryNode } from "../../core/bvh2/BinaryNode.js";
20
- import { max2 } from "../../core/math/max2.js";
20
+ import Signal from "../../core/events/signal/Signal.js";
21
+ import Vector1 from "../../core/geom/Vector1.js";
22
+ import {max2} from "../../core/math/max2.js";
23
+ import EmptyView from "../../view/elements/EmptyView.js";
24
+ import {globalMetrics} from "../metrics/GlobalMetrics.js";
25
+ import {MetricsCategory} from "../metrics/MetricsCategory.js";
26
+ import {CompositingStages} from "./composit/CompositingStages.js";
21
27
 
22
28
  import LayerCompositer from "./composit/LayerCompositer.js";
23
- import { Camera } from "./ecs/camera/Camera.js";
24
- import EmptyView from "../../view/elements/EmptyView.js";
25
- import { assert } from "../../core/assert.js";
26
- import { RenderLayerManager } from "./render/layers/RenderLayerManager.js";
27
- import { FrameBufferManager } from "./render/buffer/FrameBufferManager.js";
28
- import { ColorAndDepthFrameBuffer } from "./render/buffer/buffers/ColorAndDepthFrameBuffer.js";
29
- import { RenderPassType } from "./render/RenderPassType.js";
30
- import { renderTextureToScreenQuad } from "./render/utils/renderTextureToScreenQuad.js";
31
- import { globalMetrics } from "../metrics/GlobalMetrics.js";
32
- import { MetricsCategory } from "../metrics/MetricsCategory.js";
33
- import Vector1 from "../../core/geom/Vector1.js";
34
- import { NormalFrameBuffer } from "./render/buffer/buffers/NormalFrameBuffer.js";
35
- import { MaterialManager } from "./material/manager/MaterialManager.js";
36
- import { ShadowMapRenderer } from "./shadows/ShadowMapRenderer.js";
37
- import { CameraViewManager } from "./render/view/CameraViewManager.js";
38
- import { StandardFrameBuffers } from "./StandardFrameBuffers.js";
39
- import { CompositingStages } from "./composit/CompositingStages.js";
40
- import { DEG_TO_RAD } from "../../core/math/DEG_TO_RAD.js";
29
+ import {Camera} from "./ecs/camera/Camera.js";
30
+ import {MaterialManager} from "./material/manager/MaterialManager.js";
31
+ import {ColorAndDepthFrameBuffer} from "./render/buffer/buffers/ColorAndDepthFrameBuffer.js";
32
+ import {NormalFrameBuffer} from "./render/buffer/buffers/NormalFrameBuffer.js";
33
+ import {FrameBufferManager} from "./render/buffer/FrameBufferManager.js";
34
+ import {RenderLayerManager} from "./render/layers/RenderLayerManager.js";
35
+ import {RenderPassType} from "./render/RenderPassType.js";
36
+ import {renderTextureToScreenQuad} from "./render/utils/renderTextureToScreenQuad.js";
37
+ import {CameraViewManager} from "./render/view/CameraViewManager.js";
38
+ import {ShadowMapRenderer} from "./shadows/ShadowMapRenderer.js";
39
+ import {StandardFrameBuffers} from "./StandardFrameBuffers.js";
41
40
 
42
41
  /**
43
42
  *
@@ -70,609 +69,560 @@ function configureThreeRenderer(webGLRenderer) {
70
69
  }
71
70
 
72
71
 
73
- /**
74
- *
75
- * @param {Camera} camera
76
- * @param {EntityManager} entityManger
77
- * @constructor
78
- */
79
- function GraphicsEngine(camera, entityManger) {
80
- const self = this;
81
-
82
- this.entityManager = entityManger;
83
-
72
+ export class GraphicsEngine {
84
73
  /**
85
74
  *
86
- * @type {MaterialManager}
87
- * @private
75
+ * @param {Camera} camera
76
+ * @constructor
88
77
  */
89
- this.__material_manager = new MaterialManager();
78
+ constructor(camera) {
79
+ const self = this;
80
+
81
+ /**
82
+ *
83
+ * @type {MaterialManager}
84
+ * @private
85
+ */
86
+ this.__material_manager = new MaterialManager();
87
+
88
+ // The line below would de-dupe textures, it is a rather slow process however
89
+ // this.__material_manager.addCompileStep(new CoalesceTextures());
90
90
 
91
- // The line below would de-dupe textures, it is a rather slow process however
92
- // this.__material_manager.addCompileStep(new CoalesceTextures());
91
+ this.on = {
92
+ preRender: new Signal(),
93
+ postRender: new Signal(),
93
94
 
94
- this.on = {
95
- preRender: new Signal(),
96
- postRender: new Signal(),
95
+ preOpaquePass: new Signal(),
96
+ postOpaquePass: new Signal(),
97
97
 
98
- preOpaquePass: new Signal(),
99
- postOpaquePass: new Signal(),
98
+ /**
99
+ * @deprecated
100
+ */
101
+ preComposite: new Signal(),
102
+ /**
103
+ * @deprecated
104
+ */
105
+ postComposite: new Signal(),
106
+
107
+ buffersRendered: new Signal(),
108
+ visibilityConstructionStarted: new Signal(),
109
+ visibilityConstructionEnded: new Signal()
110
+ };
100
111
 
101
112
  /**
102
- * @deprecated
113
+ * @type {Vector1}
103
114
  */
104
- preComposite: new Signal(),
115
+ this.pixelRatio = new Vector1(1);
116
+
105
117
  /**
106
- * @deprecated
118
+ *
119
+ * @type {RenderLayerManager}
107
120
  */
108
- postComposite: new Signal(),
121
+ this.layers = new RenderLayerManager();
109
122
 
110
- buffersRendered: new Signal(),
111
- visibilityConstructionStarted: new Signal(),
112
- visibilityConstructionEnded: new Signal()
113
- };
123
+ /**
124
+ *
125
+ * @type {BinaryNode}
126
+ */
127
+ this.bvh = new BinaryNode();
128
+ this.bvh.setNegativelyInfiniteBounds();
114
129
 
115
- /**
116
- * @type {Vector1}
117
- */
118
- this.pixelRatio = new Vector1(1);
130
+ //renderer setup
131
+ const scene = new ThreeScene();
132
+ //prevent automatic updates to all descendants of the scene, such updates are very wasteful
133
+ scene.autoUpdate = false;
134
+ //prevent scene matrix from automatically updating, as it would result in updates to the entire scene graph
135
+ scene.matrixAutoUpdate = false;
136
+ //setup environment
119
137
 
120
- /**
121
- *
122
- * @type {RenderLayerManager}
123
- */
124
- this.layers = new RenderLayerManager();
125
138
 
126
- /**
127
- *
128
- * @type {BinaryNode}
129
- */
130
- this.bvh = new BinaryNode();
131
- this.bvh.setNegativelyInfiniteBounds();
139
+ /**
140
+ *
141
+ * @type {Scene}
142
+ */
143
+ this.scene = scene;
132
144
 
133
- //renderer setup
134
- const scene = new ThreeScene();
135
- //prevent automatic updates to all descendants of the scene, such updates are very wasteful
136
- scene.autoUpdate = false;
137
- //prevent scene matrix from automatically updating, as it would result in updates to the entire scene graph
138
- scene.matrixAutoUpdate = false;
139
- //setup environment
140
145
 
146
+ /**
147
+ *
148
+ * @type {Group}
149
+ */
150
+ this.visibleGroup = new Group();
151
+ this.visibleGroup.matrixAutoUpdate = false;
141
152
 
142
- /**
143
- *
144
- * @type {Scene}
145
- */
146
- this.scene = scene;
153
+ this.scene.add(this.visibleGroup);
147
154
 
155
+ /**
156
+ *
157
+ * @type {Camera}
158
+ */
159
+ this.camera = camera;
148
160
 
149
- /**
150
- *
151
- * @type {Group}
152
- */
153
- this.visibleGroup = new Group();
154
- this.visibleGroup.matrixAutoUpdate = false;
161
+ /**
162
+ *
163
+ * @type {WebGLRenderer}
164
+ */
165
+ this.renderer = null;
155
166
 
156
- this.scene.add(this.visibleGroup);
167
+ //webGLRenderer.shadowMapDebug = true;
168
+ this.layerComposer = new LayerCompositer();
157
169
 
158
- /**
159
- *
160
- * @type {Camera}
161
- */
162
- this.camera = camera;
170
+ Object.defineProperties(this, {
171
+ info: {
172
+ get: function () {
173
+ return self.renderer.info;
174
+ }
175
+ }
176
+ });
163
177
 
164
- /**
165
- *
166
- * @type {WebGLRenderer}
167
- */
168
- this.renderer = null;
178
+ /**
179
+ * @type {View}
180
+ */
181
+ this.viewport = new EmptyView();
182
+ this.viewport.size.onChanged.add(this.updateSize, this);
183
+ this.pixelRatio.onChanged.add(this.updateSize, this);
169
184
 
170
- //webGLRenderer.shadowMapDebug = true;
171
- this.layerComposer = new LayerCompositer();
185
+ /**
186
+ * @readonly
187
+ * @type {FrameBufferManager}
188
+ */
189
+ this.frameBuffers = new FrameBufferManager();
172
190
 
173
- this.initGUI = function (folder) {
174
- const ge = this;
175
- if (ge.effects === void 0) {
176
- return;
177
- }
178
- ge.effects.initializeGUI(folder);
179
- };
191
+ /**
192
+ *
193
+ * @type {ShadowMapRenderer}
194
+ */
195
+ this.shadowmap_renderer = new ShadowMapRenderer();
180
196
 
181
- Object.defineProperties(this, {
182
- info: {
183
- get: function () {
184
- return self.renderer.info;
185
- }
186
- }
187
- });
197
+ /**
198
+ * @readonly
199
+ * @type {CameraViewManager}
200
+ */
201
+ this.views = new CameraViewManager();
188
202
 
189
- /**
190
- * @type {View}
191
- */
192
- this.viewport = new EmptyView();
193
- this.viewport.size.onChanged.add(this.updateSize, this);
194
- this.pixelRatio.onChanged.add(this.updateSize, this);
203
+ /**
204
+ *
205
+ * @type {CameraView}
206
+ */
207
+ this.main_view = this.views.create();
208
+ this.main_view.name = 'Main Camera';
195
209
 
196
- /**
197
- * @readonly
198
- * @type {FrameBufferManager}
199
- */
200
- this.frameBuffers = new FrameBufferManager();
210
+ /**
211
+ * Used to signal that scene needs to be drawn
212
+ * When set to true will draw frame at next opportunity
213
+ * @type {boolean}
214
+ */
215
+ this.needDraw = true;
201
216
 
202
- /**
203
- *
204
- * @type {ShadowMapRenderer}
205
- */
206
- this.shadowmap_renderer = new ShadowMapRenderer();
217
+ /**
218
+ * Will automatically draw each frame
219
+ * @type {boolean}
220
+ */
221
+ this.autoDraw = true;
207
222
 
208
- /**
209
- * @readonly
210
- * @type {CameraViewManager}
211
- */
212
- this.views = new CameraViewManager();
223
+ /**
224
+ * Monotonically increasing rendered-frame counter
225
+ * @type {number}
226
+ */
227
+ this.frameIndex = 0;
228
+ this.intersectObjectUnderViewportPoint = (function () {
229
+ const point = new ThreeVector3();
230
+ const raycaster = new ThreeRaycaster();
231
+ const origin = new ThreeVector3();
232
+
233
+ function intersectObject(x, y, object, recurse) {
234
+ this.viewportProjectionRay(x, y, origin, point);
235
+ //
236
+ raycaster.set(origin, point);
237
+ //console.log(x,y,point.x, point.y, point.z);
238
+ return raycaster.intersectObject(object, recurse);
239
+ }
213
240
 
241
+ return intersectObject;
242
+ })();
243
+ }
214
244
  /**
215
245
  *
216
- * @type {CameraView}
246
+ * @returns {MaterialManager}
217
247
  */
218
- this.main_view = this.views.create();
219
- this.main_view.name = 'Main Camera';
248
+ getMaterialManager() {
249
+ return this.__material_manager;
250
+ }
220
251
 
221
252
  /**
222
- * Used to signal that scene needs to be drawn
223
- * When set to true will draw frame at next opportunity
224
- * @type {boolean}
253
+ * Get direct access to three.js renderer
254
+ * @returns {WebGLRenderer}
225
255
  */
226
- this.needDraw = true;
256
+ getRenderer() {
257
+ return this.renderer;
258
+ }
227
259
 
228
- /**
229
- * Will automatically draw each frame
230
- * @type {boolean}
231
- */
232
- this.autoDraw = true;
260
+ updateSize() {
261
+ const size = this.viewport.size;
233
262
 
234
- /**
235
- * Monotonically increasing rendered-frame counter
236
- * @type {number}
237
- */
238
- this.frameIndex = 0;
239
- }
263
+ const renderer = this.renderer;
240
264
 
241
- /**
242
- *
243
- * @returns {MaterialManager}
244
- */
245
- GraphicsEngine.prototype.getMaterialManager = function () {
246
- return this.__material_manager;
247
- }
265
+ const pixelRatio = this.pixelRatio.getValue();
248
266
 
249
- /**
250
- * Get direct access to three.js renderer
251
- * @returns {WebGLRenderer}
252
- */
253
- GraphicsEngine.prototype.getRenderer = function () {
254
- return this.renderer;
255
- };
267
+ const _w = max2(0, size.x * pixelRatio);
268
+ const _h = max2(0, size.y * pixelRatio);
256
269
 
257
- /**
258
- * @deprecated
259
- * @param {string[]|string} paths URLs to faces of the cubemap
260
- * @returns {Promise<Texture>}
261
- */
262
- GraphicsEngine.prototype.loadEnvironmentMap = async function (paths) {
263
- throw new Error('Deprecated use `load_and_set_cubemap_v0` instead');
264
- }
270
+ renderer.setSize(_w, _h);
265
271
 
266
- GraphicsEngine.prototype.updateSize = function () {
267
- const size = this.viewport.size;
272
+ const devicePixelRatio = window.devicePixelRatio;
268
273
 
269
- const renderer = this.renderer;
274
+ renderer.setPixelRatio(devicePixelRatio);
270
275
 
271
- const pixelRatio = this.pixelRatio.getValue();
272
276
 
273
- const _w = max2(0, size.x * pixelRatio);
274
- const _h = max2(0, size.y * pixelRatio);
277
+ renderer.domElement.style.width = size.x + "px";
278
+ renderer.domElement.style.height = size.y + "px";
275
279
 
276
- renderer.setSize(_w, _h);
277
280
 
278
- const devicePixelRatio = window.devicePixelRatio;
281
+ this.frameBuffers.setPixelRatio(devicePixelRatio);
282
+ this.layerComposer.setPixelRatio(devicePixelRatio);
279
283
 
280
- renderer.setPixelRatio(devicePixelRatio);
284
+ this.layerComposer.setSize(_w, _h);
285
+ this.frameBuffers.setSize(_w, _h);
286
+ }
281
287
 
288
+ /**
289
+ *
290
+ * @param {Vector2|{set:function(x:number,y:number)}} target
291
+ */
292
+ getResolution(target) {
293
+ const ar = this.computeTotalPixelRatio();
282
294
 
283
- renderer.domElement.style.width = size.x + "px";
284
- renderer.domElement.style.height = size.y + "px";
295
+ target.set(
296
+ this.viewport.size.x * ar,
297
+ this.viewport.size.y * ar
298
+ );
299
+ }
285
300
 
301
+ /**
302
+ *
303
+ * @returns {number}
304
+ */
305
+ computeTotalPixelRatio() {
306
+ return this.pixelRatio.getValue() * window.devicePixelRatio;
307
+ }
286
308
 
287
- this.frameBuffers.setPixelRatio(devicePixelRatio);
288
- this.layerComposer.setPixelRatio(devicePixelRatio);
309
+ initializeFrameBuffers() {
310
+ const colorAndDepthFrameBuffer = new ColorAndDepthFrameBuffer(StandardFrameBuffers.ColorAndDepth);
289
311
 
290
- this.layerComposer.setSize(_w, _h);
291
- this.frameBuffers.setSize(_w, _h);
292
- };
312
+ //whole renderer relies on color+depth buffer, so we flag it as always in use to ensure it's always being drawn
313
+ colorAndDepthFrameBuffer.referenceCount += 1;
293
314
 
294
- /**
295
- *
296
- * @param {Vector2|{set:function(x:number,y:number)}} target
297
- */
298
- GraphicsEngine.prototype.getResolution = function (target) {
299
- const ar = this.computeTotalPixelRatio();
315
+ this.frameBuffers.add(colorAndDepthFrameBuffer);
300
316
 
301
- target.set(
302
- this.viewport.size.x * ar,
303
- this.viewport.size.y * ar
304
- );
305
- }
317
+ const normalFrameBuffer = new NormalFrameBuffer(StandardFrameBuffers.Normal);
306
318
 
307
- /**
308
- *
309
- * @returns {number}
310
- */
311
- GraphicsEngine.prototype.computeTotalPixelRatio = function () {
312
- return this.pixelRatio.getValue() * window.devicePixelRatio;
313
- };
319
+ this.frameBuffers.add(normalFrameBuffer);
314
320
 
315
- GraphicsEngine.prototype.initializeFrameBuffers = function () {
316
- const colorAndDepthFrameBuffer = new ColorAndDepthFrameBuffer(StandardFrameBuffers.ColorAndDepth);
321
+ //initialize buffers
322
+ this.frameBuffers.initialize(this.renderer);
323
+ }
317
324
 
318
- //whole renderer relies on color+depth buffer, so we flag it as always in use to ensure it's always being drawn
319
- colorAndDepthFrameBuffer.referenceCount += 1;
325
+ start() {
326
+ const canvas = document.createElement("canvas");
327
+ const context = canvas.getContext("webgl2", {antialias: false});
320
328
 
321
- this.frameBuffers.add(colorAndDepthFrameBuffer);
329
+ const rendererParameters = {
330
+ antialias: true,
331
+ logarithmicDepthBuffer: false,
332
+ canvas,
333
+ context,
334
+ /**
335
+ * @see https://registry.khronos.org/webgl/specs/latest/1.0/#5.2
336
+ */
337
+ powerPreference: "high-performance"
338
+ };
322
339
 
323
- const normalFrameBuffer = new NormalFrameBuffer(StandardFrameBuffers.Normal);
340
+ const webGLRenderer = this.renderer = new WebGLRenderer(rendererParameters);
324
341
 
325
- this.frameBuffers.add(normalFrameBuffer);
342
+ //print GPU info
343
+ const GPU_NAME = this.getGPUName();
326
344
 
327
- //initialize buffers
328
- this.frameBuffers.initialize(this.renderer);
329
- };
345
+ console.log("GL renderer : ", GPU_NAME);
330
346
 
331
- /**
332
- * @returns {Texture}
333
- */
334
- GraphicsEngine.prototype.getDepthTexture = function () {
335
- const frameBuffer = this.frameBuffers.getById(StandardFrameBuffers.ColorAndDepth);
336
- return frameBuffer.renderTarget.depthTexture;
337
- };
338
-
339
- GraphicsEngine.prototype.start = function () {
340
- const canvas = document.createElement("canvas");
341
- const context = canvas.getContext("webgl2", { antialias: false });
342
-
343
- const rendererParameters = {
344
- antialias: true,
345
- logarithmicDepthBuffer: false,
346
- canvas,
347
- context,
348
- /**
349
- * @see https://registry.khronos.org/webgl/specs/latest/1.0/#5.2
350
- */
351
- powerPreference: "high-performance"
352
- };
347
+ globalMetrics.record("gpu-type", {
348
+ category: MetricsCategory.System,
349
+ label: GPU_NAME
350
+ });
353
351
 
354
- const webGLRenderer = this.renderer = new WebGLRenderer(rendererParameters);
355
352
 
356
- //print GPU info
357
- const GPU_NAME = this.getGPUName();
353
+ webGLRenderer.domElement.addEventListener("webglcontextrestored", function (event) {
354
+ console.warn("webgl cotnext restored", event);
355
+ }, false);
358
356
 
359
- console.log("GL renderer : ", GPU_NAME);
357
+ webGLRenderer.domElement.addEventListener("webglcontextlost", function (event) {
358
+ // By default when a WebGL program loses the context it never gets it back. To recover, we prevent default behaviour
359
+ event.preventDefault();
360
360
 
361
- globalMetrics.record("gpu-type", {
362
- category: MetricsCategory.System,
363
- label: GPU_NAME
364
- });
361
+ console.warn("webgl context lost", event);
362
+ }, false);
365
363
 
364
+ const domElement = this.domElement = webGLRenderer.domElement;
365
+ //disable selection
366
+ const style = domElement.style;
367
+ domElement.classList.add("graphics-engine-render-canvas");
368
+ style.userSelect = style.webkitUserSelect = style.mozUserSelect = "none";
369
+ // see : https://www.w3.org/TR/pointerevents/#the-touch-action-css-property
370
+ style.touchAction = "none";
366
371
 
367
- webGLRenderer.domElement.addEventListener("webglcontextrestored", function (event) {
368
- console.warn("webgl cotnext restored", event);
369
- }, false);
372
+ configureThreeRenderer(webGLRenderer);
370
373
 
371
- webGLRenderer.domElement.addEventListener("webglcontextlost", function (event) {
372
- // By default when a WebGL program loses the context it never gets it back. To recover, we prevent default behaviour
373
- event.preventDefault();
374
+ this.enableExtensions();
374
375
 
375
- console.warn("webgl context lost", event);
376
- }, false);
376
+ this.initializeFrameBuffers();
377
377
 
378
- const domElement = this.domElement = webGLRenderer.domElement;
379
- //disable selection
380
- const style = domElement.style;
381
- domElement.classList.add("graphics-engine-render-canvas");
382
- style.userSelect = style.webkitUserSelect = style.mozUserSelect = "none";
383
- // see : https://www.w3.org/TR/pointerevents/#the-touch-action-css-property
384
- style.touchAction = "none";
378
+ const viewport = this.viewport;
379
+ const viewportSize = viewport.size;
385
380
 
386
- configureThreeRenderer(webGLRenderer);
381
+ //initialize size
382
+ webGLRenderer.setSize(viewportSize.x, viewportSize.y);
383
+ this.frameBuffers.setSize(viewportSize.x, viewportSize.y);
387
384
 
388
- this.enableExtensions();
385
+ viewport.el = webGLRenderer.domElement;
386
+ }
389
387
 
390
- this.initializeFrameBuffers();
388
+ /**
389
+ * Produces GPU identification string via WebGL extension if available
390
+ * @returns {string}
391
+ */
392
+ getGPUName() {
393
+ const gl = this.renderer.getContext();
391
394
 
392
- const viewport = this.viewport;
393
- const viewportSize = viewport.size;
395
+ const ext = gl.getExtension("WEBGL_debug_renderer_info");
394
396
 
395
- //initialize size
396
- webGLRenderer.setSize(viewportSize.x, viewportSize.y);
397
- this.frameBuffers.setSize(viewportSize.x, viewportSize.y);
397
+ if (ext === null) {
398
+ return "Unknown";
399
+ }
398
400
 
399
- viewport.el = webGLRenderer.domElement;
400
- };
401
+ return gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
402
+ }
401
403
 
402
- /**
403
- * Produces GPU identification string via WebGL extension if available
404
- * @returns {string}
405
- */
406
- GraphicsEngine.prototype.getGPUName = function () {
407
- const gl = this.renderer.getContext();
404
+ /**
405
+ * Shut down renderer engine. After calling this method the engine may no longer be used.
406
+ */
407
+ stop() {
408
+ const renderer = this.renderer;
409
+ if (renderer !== undefined) {
410
+ renderer.forceContextLoss();
411
+ renderer.context = null;
412
+ renderer.domElement = null;
413
+ this.renderer = null;
414
+ }
415
+ }
408
416
 
409
- const ext = gl.getExtension("WEBGL_debug_renderer_info");
417
+ /**
418
+ * Enables various WebGL extensions required by the engine
419
+ */
420
+ enableExtensions() {
421
+ const ctx = this.renderer.getContext();
422
+ // Standard derivatives are required for Terrain Shader
423
+ ctx.getExtension("OES_standard_derivatives");
424
+ // Depth texture is required for Particle Emitter engine
425
+ ctx.getExtension("WEBGL_depth_texture");
426
+ ctx.getExtension("WEBGL_compressed_texture_s3tc");
410
427
 
411
- if (ext === null) {
412
- return "Unknown";
413
428
  }
414
429
 
415
- return gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
416
- };
417
- /**
418
- * Shut down renderer engine. After calling this method the engine may no longer be used.
419
- */
420
- GraphicsEngine.prototype.stop = function () {
421
- const renderer = this.renderer;
422
- if (renderer !== undefined) {
423
- renderer.forceContextLoss();
424
- renderer.context = null;
425
- renderer.domElement = null;
426
- this.renderer = null;
430
+ /**
431
+ * Creates a ray from viewport orthogonally into the view frustum
432
+ * @param {number} x
433
+ * @param {number} y
434
+ * @param {Vector3} source Ray source is written here
435
+ * @param {Vector3} direction Ray target is written here
436
+ */
437
+ viewportProjectionRay(x, y, source, direction) {
438
+ Camera.projectRay(this.camera, x, y, source, direction);
427
439
  }
428
- };
429
440
 
441
+ /**
442
+ * Converts screen-space pixel position to normalized clip-space
443
+ * @param {Vector2|Vector3} input
444
+ * @param {Vector2|Vector3} result
445
+ */
446
+ normalizeViewportPoint(input, result) {
447
+ assert.notEqual(input, undefined);
448
+ assert.notEqual(result, undefined);
430
449
 
431
- /**
432
- * Enables various WebGL extensions required by the engine
433
- */
434
- GraphicsEngine.prototype.enableExtensions = function () {
435
- const ctx = this.renderer.getContext();
436
- // Standard derivatives are required for Terrain Shader
437
- ctx.getExtension("OES_standard_derivatives");
438
- // Depth texture is required for Particle Emitter engine
439
- ctx.getExtension("WEBGL_depth_texture");
440
- ctx.getExtension("WEBGL_compressed_texture_s3tc");
450
+ const viewportSize = this.viewport.size;
441
451
 
442
- };
452
+ // shift by pixel center
453
+ const _x = input.x + 0.5;
454
+ const _y = input.y + 0.5;
443
455
 
444
- /**
445
- * Creates a ray from viewport orthogonally into the view frustum
446
- * @param {number} x
447
- * @param {number} y
448
- * @param {Vector3} source Ray source is written here
449
- * @param {Vector3} direction Ray target is written here
450
- */
451
- GraphicsEngine.prototype.viewportProjectionRay = function viewportProjectionRay(x, y, source, direction) {
452
- Camera.projectRay(this.camera, x, y, source, direction);
453
- };
454
-
455
- GraphicsEngine.prototype.intersectObjectUnderViewportPoint = (function () {
456
- const point = new ThreeVector3();
457
- const raycaster = new ThreeRaycaster();
458
- const origin = new ThreeVector3();
459
-
460
- function intersectObject(x, y, object, recurse) {
461
- this.viewportProjectionRay(x, y, origin, point);
462
- //
463
- raycaster.set(origin, point);
464
- //console.log(x,y,point.x, point.y, point.z);
465
- return raycaster.intersectObject(object, recurse);
456
+ result.x = (_x / viewportSize.x) * 2 - 1;
457
+ result.y = -(_y / viewportSize.y) * 2 + 1;
466
458
  }
467
459
 
468
- return intersectObject;
469
- })();
460
+ /**
461
+ * @private
462
+ * @param {THREE.WebGLRenderer} renderer
463
+ * @param {THREE.Camera} camera
464
+ * @param {THREE.Scene} scene
465
+ */
466
+ constructVisibleScene(renderer, camera, scene) {
467
+ this.on.visibilityConstructionStarted.send3(renderer, camera, scene);
470
468
 
471
- /**
472
- * Converts screen-space pixel position to normalized clip-space
473
- * @param {Vector2|Vector3} input
474
- * @param {Vector2|Vector3} result
475
- */
476
- GraphicsEngine.prototype.normalizeViewportPoint = function (input, result) {
477
- assert.notEqual(input, undefined);
478
- assert.notEqual(result, undefined);
469
+ // Build visibility information
470
+ this.main_view.set_from_camera(camera);
471
+ this.views.build_visibility(this.layers);
479
472
 
480
- const viewportSize = this.viewport.size;
473
+ this.on.visibilityConstructionEnded.send3(renderer, camera, scene);
474
+ }
481
475
 
482
- // shift by pixel center
483
- const _x = input.x + 0.5;
484
- const _y = input.y + 0.5;
476
+ clearVisibleGroup() {
477
+ this.visibleGroup.children.length = 0;
478
+ }
485
479
 
486
- result.x = (_x / viewportSize.x) * 2 - 1;
487
- result.y = -(_y / viewportSize.y) * 2 + 1;
488
- };
480
+ /**
481
+ *
482
+ * @param {RenderPassType} passType
483
+ */
484
+ prepareRenderPass(passType) {
489
485
 
490
- /**
491
- * Compute size of viewport in world-space
492
- * @param {PerspectiveCamera} camera
493
- * @param {number} zDistance
494
- * @param {Vector2} result
495
- * @returns {Vector2}
496
- */
497
- GraphicsEngine.prototype.viewportWorldSize = function (camera, zDistance, result) {
498
- const size = this.viewport.size;
499
- const angleY = camera.fov * DEG_TO_RAD;
500
- const cameraZ = camera.position.z;
501
- const distFromCamToPlane = Math.abs(cameraZ) + zDistance;
486
+ this.clearVisibleGroup();
502
487
 
503
- const planeHeight = Math.tan((angleY * 0.5)) * distFromCamToPlane * 2;
504
- const aspectRatio = size.x / size.y;
505
- const planeWidth = planeHeight * aspectRatio;
488
+ const visibleGroup = this.visibleGroup;
506
489
 
507
- result.x = planeWidth;
508
- result.y = planeHeight;
509
- return result;
510
- };
490
+ let j = 0;
511
491
 
512
- /**
513
- *
514
- * @param {THREE.WebGLRenderer} renderer
515
- * @param {THREE.Camera} camera
516
- * @param {THREE.Scene} scene
517
- */
518
- GraphicsEngine.prototype.constructVisibleScene = function (renderer, camera, scene) {
519
- this.on.visibilityConstructionStarted.send3(renderer, camera, scene);
492
+ const visible_objects = this.main_view.visible_objects;
520
493
 
521
- // Build visibility information
522
- this.main_view.set_from_camera(camera);
523
- this.views.build_visibility(this.layers);
494
+ const element_count = visible_objects.size;
495
+ const elements = visible_objects.elements;
524
496
 
525
- this.on.visibilityConstructionEnded.send3(renderer, camera, scene);
526
- };
497
+ for (let i = 0; i < element_count; i++) {
498
+ const object3D = elements[i];
527
499
 
528
- GraphicsEngine.prototype.clearVisibleGroup = function () {
529
- this.visibleGroup.children.length = 0;
530
- };
500
+ const object_pass = classifyPassTypeFromObject(object3D);
531
501
 
532
- /**
533
- *
534
- * @param {THREE.Object3D} object
535
- * @returns {RenderPassType}
536
- */
537
- function classifyPassTypeFromObject(object) {
538
- if (object.isMesh || object.isPoints) {
502
+ if (object_pass === passType) {
539
503
 
540
- /**
541
- * @type {THREE.Material}
542
- */
543
- const material = object.material;
544
- if (material.depthWrite === false && material.depthTest === false) {
545
- return RenderPassType.Transparent;
504
+ //insert object, bypassing Object#add for speed
505
+ //visibleGroup.add(object3D);
506
+ object3D.parent = visibleGroup;
507
+ visibleGroup.children[j++] = object3D;
508
+ }
546
509
  }
547
- }
548
-
549
- return RenderPassType.Opaque;
550
- }
551
510
 
552
- /**
553
- *
554
- * @param {RenderPassType} passType
555
- */
556
- GraphicsEngine.prototype.prepareRenderPass = function (passType) {
557
-
558
- this.clearVisibleGroup();
511
+ visibleGroup.length = j;
512
+ }
559
513
 
560
- const visibleGroup = this.visibleGroup;
514
+ /**
515
+ * Renders opaque assets
516
+ */
517
+ renderOpaque() {
518
+ this.on.preOpaquePass.send0();
561
519
 
562
- let j = 0;
520
+ this.prepareRenderPass(RenderPassType.Opaque);
563
521
 
564
- const visible_objects = this.main_view.visible_objects;
522
+ const renderer = this.renderer;
565
523
 
566
- const element_count = visible_objects.size;
567
- const elements = visible_objects.elements;
524
+ const buffers = this.frameBuffers;
568
525
 
569
- for (let i = 0; i < element_count; i++) {
570
- const object3D = elements[i];
526
+ buffers.render(renderer, this.camera, this.scene);
571
527
 
572
- const object_pass = classifyPassTypeFromObject(object3D);
528
+ // TODO designate opaque output buffer
529
+ const frameBuffer = buffers.getById(StandardFrameBuffers.ColorAndDepth);
573
530
 
574
- if (object_pass === passType) {
531
+ renderTextureToScreenQuad(frameBuffer.renderTarget.texture, renderer);
575
532
 
576
- //insert object, bypassing Object#add for speed
577
- //visibleGroup.add(object3D);
578
- object3D.parent = visibleGroup;
579
- visibleGroup.children[j++] = object3D;
580
- }
533
+ this.on.postOpaquePass.send0();
581
534
  }
582
535
 
583
- visibleGroup.length = j;
584
- };
536
+ /**
537
+ * Renders assets that (may) contain transparent fragments
538
+ */
539
+ renderTransparent() {
540
+ const scene = this.scene;
585
541
 
586
- /**
587
- * Renders opaque assets
588
- */
589
- GraphicsEngine.prototype.renderOpaque = function () {
590
- this.on.preOpaquePass.send0();
542
+ // clear background, as transparent pass is drawn on top, the background should already be composited
543
+ const _background = scene.background;
544
+ scene.background = null;
591
545
 
592
- this.prepareRenderPass(RenderPassType.Opaque);
546
+ this.prepareRenderPass(RenderPassType.Transparent);
593
547
 
594
- const renderer = this.renderer;
548
+ const renderer = this.renderer;
595
549
 
596
- const buffers = this.frameBuffers;
550
+ renderer.render(scene, this.camera);
597
551
 
598
- buffers.render(renderer, this.camera, this.scene);
552
+ // restore background
553
+ scene.background = _background;
554
+ }
599
555
 
600
- // TODO designate opaque output buffer
601
- const frameBuffer = buffers.getById(StandardFrameBuffers.ColorAndDepth);
556
+ /**
557
+ *
558
+ */
559
+ render() {
560
+ if (this.needDraw && !this.autoDraw) {
561
+ this.needDraw = false;
562
+ }
602
563
 
603
- renderTextureToScreenQuad(frameBuffer.renderTarget.texture, renderer);
564
+ this.frameIndex++;
604
565
 
605
- this.on.postOpaquePass.send0();
606
- };
566
+ const renderer = this.renderer;
607
567
 
608
- /**
609
- * Renders assets that (may) contain transparent fragments
610
- */
611
- GraphicsEngine.prototype.renderTransparent = function () {
612
- const scene = this.scene;
568
+ //reset renderer statistics (used for debug)
569
+ renderer.info.reset();
613
570
 
614
- // clear background, as transparent pass is drawn on top, the background should already be composited
615
- const _background = scene.background;
616
- scene.background = null;
571
+ renderer.autoClear = false;
572
+ renderer.clearAlpha = 0;
617
573
 
618
- this.prepareRenderPass(RenderPassType.Transparent);
574
+ //render actual scene
575
+ const scene = this.scene;
619
576
 
620
- const renderer = this.renderer;
577
+ const camera = this.camera;
621
578
 
622
- renderer.render(scene, this.camera);
579
+ if (scene.children.indexOf(camera) < 0) {
580
+ console.log("added camera");
581
+ scene.add(camera);
582
+ }
623
583
 
624
- // restore background
625
- scene.background = _background;
626
- };
584
+ this.constructVisibleScene(renderer, camera, scene);
627
585
 
628
- /**
629
- *
630
- */
631
- GraphicsEngine.prototype.render = function () {
632
- if (this.needDraw && !this.autoDraw) {
633
- this.needDraw = false;
634
- }
586
+ //dispatch pre-render event
587
+ this.on.preRender.send3(renderer, camera, scene);
635
588
 
636
- this.frameIndex++;
589
+ this.main_view.on.preRender.send1(this.main_view);
637
590
 
638
- const renderer = this.renderer;
591
+ //do the opaque pass
592
+ this.renderOpaque();
639
593
 
640
- //reset renderer statistics (used for debug)
641
- renderer.info.reset();
594
+ this.layerComposer.composite(renderer, CompositingStages.POST_OPAQUE);
642
595
 
643
- renderer.autoClear = false;
644
- renderer.clearAlpha = 0;
596
+ this.on.buffersRendered.send3(renderer, camera, scene);
645
597
 
646
- //render actual scene
647
- const scene = this.scene;
598
+ // transparent pass
599
+ this.renderTransparent();
648
600
 
649
- const camera = this.camera;
601
+ this.layerComposer.composite(renderer, CompositingStages.POST_TRANSPARENT);
650
602
 
651
- if (scene.children.indexOf(camera) < 0) {
652
- console.log("added camera");
653
- scene.add(camera);
603
+ //dispatch post-render event
604
+ this.on.postRender.send3(renderer, camera, scene);
654
605
  }
606
+ }
655
607
 
656
- this.constructVisibleScene(renderer, camera, scene);
657
-
658
- //dispatch pre-render event
659
- this.on.preRender.send3(renderer, camera, scene);
660
-
661
- this.main_view.on.preRender.send1(this.main_view);
662
-
663
- //do the opaque pass
664
- this.renderOpaque();
665
-
666
- this.layerComposer.composite(renderer, CompositingStages.POST_OPAQUE);
667
608
 
668
- this.on.buffersRendered.send3(renderer, camera, scene);
609
+ /**
610
+ *
611
+ * @param {THREE.Object3D} object
612
+ * @returns {RenderPassType}
613
+ */
614
+ function classifyPassTypeFromObject(object) {
615
+ if (object.isMesh || object.isPoints) {
669
616
 
670
- // transparent pass
671
- this.renderTransparent();
617
+ /**
618
+ * @type {THREE.Material}
619
+ */
620
+ const material = object.material;
621
+ if (material.depthWrite === false && material.depthTest === false) {
622
+ return RenderPassType.Transparent;
623
+ }
624
+ }
672
625
 
673
- this.layerComposer.composite(renderer, CompositingStages.POST_TRANSPARENT);
626
+ return RenderPassType.Opaque;
627
+ }
674
628
 
675
- //dispatch post-render event
676
- this.on.postRender.send3(renderer, camera, scene);
677
- };
678
- export { GraphicsEngine };