@woosh/meep-engine 2.34.37 → 2.34.41

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.
@@ -34,7 +34,7 @@ let stackPointer = 0;
34
34
  */
35
35
  const stack = [];
36
36
 
37
- export class BinaryNode extends Node{
37
+ export class BinaryNode extends Node {
38
38
  constructor() {
39
39
  super();
40
40
 
@@ -58,10 +58,17 @@ export class BinaryNode extends Node{
58
58
 
59
59
  /**
60
60
  * Number of leaf nodes in the hierarchy
61
+ * @deprecated
61
62
  * @type {number}
62
63
  * @private
63
64
  */
64
65
  this.leafNodeCount = 0;
66
+
67
+ /**
68
+ * Leaf node will have height 0, root node will have height equal to maximum depth of the tree
69
+ * @type {number}
70
+ */
71
+ this.height = 0;
65
72
  }
66
73
 
67
74
  /**
@@ -107,38 +114,38 @@ export class BinaryNode extends Node{
107
114
  * @param {*} [thisArg]
108
115
  */
109
116
  traverseLeavesPreOrderUsingStack(visitor, thisArg) {
110
- let visitCount = 0;
117
+ let visitCount = 0;
111
118
 
112
- const stackOffset = stackPointer;
119
+ const stackOffset = stackPointer;
113
120
 
114
- stack[stackPointer++] = this;
121
+ stack[stackPointer++] = this;
115
122
 
116
- let n;
123
+ let n;
117
124
 
118
- while (stackPointer-- > stackOffset) {
125
+ while (stackPointer-- > stackOffset) {
119
126
 
120
- visitCount++;
127
+ visitCount++;
121
128
 
122
- n = stack[stackPointer];
129
+ n = stack[stackPointer];
123
130
 
124
- if (n.isLeafNode) {
125
- visitor.call(thisArg, n);
126
- } else {
127
- //a binary node
128
- if (n.right !== null) {
129
- stack[stackPointer++] = n.right;
130
- }
131
- if (n.left !== null) {
132
- stack[stackPointer++] = n.left;
133
- }
131
+ if (n.isLeafNode) {
132
+ visitor.call(thisArg, n);
133
+ } else {
134
+ //a binary node
135
+ if (n.right !== null) {
136
+ stack[stackPointer++] = n.right;
137
+ }
138
+ if (n.left !== null) {
139
+ stack[stackPointer++] = n.left;
134
140
  }
135
141
  }
142
+ }
136
143
 
137
144
  // drop stack frame
138
145
  stackPointer = stackOffset;
139
146
 
140
- return visitCount;
141
- }
147
+ return visitCount;
148
+ }
142
149
 
143
150
 
144
151
  /**
@@ -154,6 +161,7 @@ export class BinaryNode extends Node{
154
161
  this.right = null;
155
162
 
156
163
  this.leafNodeCount = 0;
164
+ this.height = 0;
157
165
 
158
166
  this.setNegativelyInfiniteBounds();
159
167
  }
@@ -167,10 +175,6 @@ export class BinaryNode extends Node{
167
175
  this.left = left;
168
176
  this.right = right;
169
177
 
170
- this.updateLeafNodeCount()
171
-
172
- this.refitFor2();
173
-
174
178
  left.parentNode = this;
175
179
  right.parentNode = this;
176
180
  }
@@ -183,11 +187,6 @@ export class BinaryNode extends Node{
183
187
  assert.isNull(this.left, 'left');
184
188
 
185
189
  this.left = child;
186
-
187
- this.updateLeafNodeCount();
188
-
189
- this.refit();
190
-
191
190
  child.parentNode = this;
192
191
  }
193
192
 
@@ -199,16 +198,12 @@ export class BinaryNode extends Node{
199
198
  assert.isNull(this.right, 'right');
200
199
 
201
200
  this.right = child;
202
-
203
- this.updateLeafNodeCount();
204
-
205
- this.refit();
206
-
207
201
  child.parentNode = this;
208
202
  }
209
203
 
210
204
  /**
211
205
  * For incremental insertion, a sibling needs to be found, newly inserted node will be parented together with this sibling
206
+ * @see https://github.com/erincatto/box2d/blob/9dc24a6fd4f32442c4bcf80791de47a0a7d25afb/src/collision/b2_dynamic_tree.cpp#L197
212
207
  * @param {AABB3} box
213
208
  * @returns {BinaryNode|LeafNode}
214
209
  */
@@ -503,6 +498,35 @@ export class BinaryNode extends Node{
503
498
  return surfaceAreaHeuristic(thisArea, leftArea, rightArea, leftLeaves, rightLeaves);
504
499
  }
505
500
 
501
+ updateHeight() {
502
+ let node = this;
503
+ let n = 0;
504
+
505
+ while (node !== null) {
506
+ n = 0;
507
+
508
+ const right = node.right;
509
+
510
+ if (right !== null) {
511
+ n = right.height;
512
+ }
513
+
514
+ const left = this.left;
515
+
516
+ if (left !== null) {
517
+ n = max2(n, left.height);
518
+ }
519
+
520
+ node.height = n + 1;
521
+
522
+ // propagate update up the tree
523
+ node = node.parentNode;
524
+ }
525
+ }
526
+
527
+ /**
528
+ * @deprecated
529
+ */
506
530
  updateLeafNodeCount() {
507
531
  let node = this;
508
532
 
@@ -568,6 +592,7 @@ export class BinaryNode extends Node{
568
592
  r.right = rL;
569
593
 
570
594
  r.updateLeafNodeCount();
595
+ r.updateHeight();
571
596
 
572
597
  r.bubbleRefit();
573
598
  }
@@ -575,25 +600,26 @@ export class BinaryNode extends Node{
575
600
  rotateRight() {
576
601
  const r = this.right;
577
602
 
578
- const l = this.left;
603
+ const left = this.left;
579
604
 
580
- const lL = l.left;
581
- const lR = l.right;
605
+ const lL = left.left;
606
+ const lR = left.right;
582
607
 
583
608
  if (lL !== null) {
584
609
  lL.parentNode = this;
585
610
  }
586
611
 
587
- l.right = r;
612
+ left.right = r;
588
613
  if (r !== null) {
589
- r.parentNode = l;
614
+ r.parentNode = left;
590
615
  }
591
616
 
592
- l.left = lR;
617
+ left.left = lR;
593
618
 
594
- l.updateLeafNodeCount();
619
+ left.updateLeafNodeCount();
620
+ left.updateHeight();
595
621
 
596
- l.bubbleRefit();
622
+ left.bubbleRefit();
597
623
  }
598
624
 
599
625
  /**
@@ -624,8 +650,14 @@ export class BinaryNode extends Node{
624
650
  for (i = 0; i < remaining_nodes - 1; i += 2) {
625
651
  const a = nodes[i];
626
652
  const b = nodes[i + 1];
653
+
627
654
  n = new BinaryNode();
655
+
628
656
  n.setChildren(a, b);
657
+
658
+ n.updateHeight();
659
+ n.refitFor2();
660
+
629
661
  nodes[i >> 1] = n;
630
662
  }
631
663
 
@@ -994,15 +1026,19 @@ export class BinaryNode extends Node{
994
1026
  const sibling = this.__insertion_findSiblingFor(child);
995
1027
 
996
1028
  const sibling_parent = sibling.parentNode;
1029
+ let parent = sibling_parent;
1030
+
997
1031
  if (sibling_parent === null) {
998
- // root node
1032
+ // "sibling" is the root node
1033
+
1034
+ parent = sibling;
999
1035
 
1000
1036
  if (sibling.left === null) {
1001
1037
  sibling.setChildLeft(child);
1002
1038
  } else if (sibling.right === null) {
1003
1039
  sibling.setChildRight(child);
1004
1040
  } else {
1005
- const parent = new BinaryNode();
1041
+ parent = new BinaryNode();
1006
1042
 
1007
1043
  parent.setChildren(sibling.right, child);
1008
1044
  sibling.right = parent;
@@ -1025,12 +1061,23 @@ export class BinaryNode extends Node{
1025
1061
 
1026
1062
  } else {
1027
1063
 
1028
- transplantNewCommonParent(sibling, child)
1064
+ parent = transplantNewCommonParent(sibling, child)
1029
1065
 
1030
1066
  }
1031
1067
 
1032
- sibling_parent.bubbleRefit();
1068
+ }
1069
+
1070
+ // walk back up the tree fixing heights and bounds
1071
+ while (parent !== null) {
1072
+ // parent = this.balance();
1073
+
1074
+ const left = parent.left;
1075
+ const right = parent.right;
1033
1076
 
1077
+ parent.height = 1 + max2(left !== null ? left.height : 0, right !== null ? right.height : 0);
1078
+ parent.refit();
1079
+
1080
+ parent = parent.parentNode;
1034
1081
  }
1035
1082
  }
1036
1083
 
@@ -1116,38 +1163,6 @@ function inclusion_cost_lower_bound(node, addition) {
1116
1163
  }
1117
1164
 
1118
1165
 
1119
- /**
1120
- *
1121
- * @param {Node} n0
1122
- * @param {Node} n1
1123
- * @return {number}
1124
- */
1125
- function sortMortonCodes(n0, n1) {
1126
- return n0._mortonCode - n1._mortonCode;
1127
- }
1128
-
1129
-
1130
- /**
1131
- *
1132
- * @param node
1133
- */
1134
- function countLeaves(node) {
1135
- if (isLeaf(node)) {
1136
- return 1;
1137
- }
1138
-
1139
- let result = 0;
1140
-
1141
- node.traversePreOrderUsingStack(function (node) {
1142
- if (isLeaf(node)) {
1143
- result++;
1144
- }
1145
- });
1146
-
1147
- return result;
1148
- }
1149
-
1150
-
1151
1166
  /**
1152
1167
  * @private
1153
1168
  * Used in intersection traversal methods. Should be invoked via Function.apply and Function.call only and not be called directly
@@ -1179,10 +1194,6 @@ function transplantNewCommonParent(node, child) {
1179
1194
  bNode.setChildren(node, child);
1180
1195
  bNode.parentNode = parent;
1181
1196
 
1182
- parent.bubbleExpandToFit(bNode);
1183
-
1184
- parent.updateLeafNodeCount();
1185
-
1186
1197
  return bNode;
1187
1198
  }
1188
1199
 
@@ -287,6 +287,7 @@ test("setChildren", () => {
287
287
  b.setBounds(-1, -2, -3, 0, 2, 2);
288
288
 
289
289
  root.setChildren(a, b);
290
+ root.refit();
290
291
 
291
292
  expect(a.parentNode).toBe(root);
292
293
  expect(b.parentNode).toBe(root);
@@ -39,17 +39,6 @@ export class LeafNode extends Node {
39
39
  this.y1 = y1;
40
40
  this.z1 = z1;
41
41
 
42
- /**
43
- *
44
- * @type {boolean}
45
- */
46
- this.isLeafNode = true;
47
- /**
48
- * Useful shortcut, to avoid having to distinguish between leaf and intermediate nodes
49
- * @readonly
50
- * @type {number}
51
- */
52
- this.leafNodeCount = 1;
53
42
  }
54
43
 
55
44
  /**
@@ -105,6 +94,26 @@ export class LeafNode extends Node {
105
94
  }
106
95
  }
107
96
 
97
+ /**
98
+ *
99
+ * @type {boolean}
100
+ */
101
+ LeafNode.prototype.isLeafNode = true;
102
+
103
+ /**
104
+ * Leaf node will have height 0, root node will have height equal to maximum depth of the tree
105
+ * @type {number}
106
+ */
107
+ LeafNode.prototype.height = 0;
108
+
109
+ /**
110
+ * Useful shortcut, to avoid having to distinguish between leaf and intermediate nodes
111
+ * @readonly
112
+ * @deprecated
113
+ * @type {number}
114
+ */
115
+ LeafNode.prototype.leafNodeCount = 1;
116
+
108
117
  /**
109
118
  *
110
119
  * @param {BinaryBuffer} buffer
package/core/bvh2/Node.js CHANGED
@@ -132,6 +132,7 @@ export class Node extends AABB3 {
132
132
  }
133
133
 
134
134
  node.updateLeafNodeCount();
135
+ node.updateHeight();
135
136
  }
136
137
 
137
138
  /**
@@ -23,5 +23,5 @@ export function aabb3_computeDistanceAbovePlane(
23
23
  const pz = plane_normal_z > 0 ? _z1 : _z0;
24
24
 
25
25
  // dot(v4,v4) inlined for speed
26
- return (plane_normal_x * px + plane_normal_y * py + plane_normal_z * pz) + plane_constant;
26
+ return plane_constant + plane_normal_x * px + plane_normal_y * py + plane_normal_z * pz;
27
27
  }
@@ -176,7 +176,7 @@ export class InstancedFoliage {
176
176
  );
177
177
 
178
178
  //compute bounding box for this instance
179
- this.bomputeInstanceBoundsTight(position, rotation, scale, leaf);
179
+ this.computeInstanceBoundsTight(position, rotation, scale, leaf);
180
180
 
181
181
  //insert bounding box into the spatial index
182
182
  this.bvh.insertNode(leaf);
@@ -218,7 +218,7 @@ export class InstancedFoliage {
218
218
  * @param {Quaternion} rotation
219
219
  * @param {Vector3} scale
220
220
  */
221
- bomputeInstanceBoundsTight(position, rotation, scale, result) {
221
+ computeInstanceBoundsTight(position, rotation, scale, result) {
222
222
 
223
223
  const vertexData = this.geometry.attributes.position.array;
224
224
 
@@ -1,6 +1,5 @@
1
1
  import { BitSet } from "../../../core/binary/BitSet.js";
2
2
  import { InstancedMeshGroup } from "../../graphics/geometry/instancing/InstancedMeshGroup.js";
3
- import { assert } from "../../../core/assert.js";
4
3
  import { queryBinaryNode_FrustumIntersections_Data } from "../../../core/bvh2/traversal/queryBinaryNode_FrustumIntersections.js";
5
4
  import Quaternion from "../../../core/geom/Quaternion.js";
6
5
 
@@ -48,30 +47,6 @@ export class ViewState {
48
47
  this.instances.dispose();
49
48
  }
50
49
 
51
-
52
- /**
53
- *
54
- * @param {number} index
55
- * @param {int} ref
56
- */
57
- __updateVisibility(index, ref) {
58
- assert.isNonNegativeInteger(ref, 'ref');
59
-
60
- /**
61
- *
62
- * @type {BitSet}
63
- */
64
- const visibleElementSet = this.__visible_set;
65
-
66
- if (!visibleElementSet.get(ref)) {
67
- //no longer visible
68
- this.__garbage[this.__garbagePointer++] = ref;
69
- } else {
70
- //visible, and is already in the group, update the set
71
- visibleElementSet.set(ref, false);
72
- }
73
- }
74
-
75
50
  __compute_visibility_update() {
76
51
  const instances = this.instances;
77
52
 
@@ -127,16 +102,16 @@ export class ViewState {
127
102
  */
128
103
  update(bvh, data) {
129
104
 
105
+ const visible_instance_set = this.__visible_set;
106
+
107
+ const instances = this.instances;
108
+
130
109
  // reset visible set
131
- this.__visible_set.reset();
110
+ visible_instance_set.reset();
132
111
 
133
112
  //reset garbage pointer
134
113
  this.__garbagePointer = 0;
135
114
 
136
- const instances = this.instances;
137
-
138
- const visible_instance_set = this.__visible_set;
139
-
140
115
 
141
116
  // collect visible instances
142
117
  const collected_nodes = queryBinaryNode_FrustumIntersections_Data(scratch_array, 0, bvh, this.__view.frustum);
@@ -58,7 +58,7 @@ export class CompositLayer {
58
58
  *
59
59
  * @type {BlendingType}
60
60
  */
61
- this.blending = blending;
61
+ this.__blending = blending;
62
62
  /**
63
63
  *
64
64
  * @type {WebGLRenderTarget}
@@ -98,6 +98,20 @@ export class CompositLayer {
98
98
  };
99
99
  }
100
100
 
101
+ get blending() {
102
+ return this.__blending;
103
+ }
104
+
105
+ set blending(v) {
106
+ if (v === this.__blending) {
107
+ return;
108
+ }
109
+
110
+ this.__blending = v;
111
+
112
+ assignMaterialBlending(this.object.material, v);
113
+ }
114
+
101
115
  /**
102
116
  *
103
117
  * @param {number} v
@@ -8,6 +8,7 @@ import { ObjectPoolFactory } from "../../../../../core/model/object/ObjectPoolFa
8
8
  import { HighlightRenderElement } from "../renderer/HighlightRenderElement.js";
9
9
  import { noop } from "../../../../../core/function/Functions.js";
10
10
  import { CompositingStages } from "../../../composit/CompositingStages.js";
11
+ import { ProcessState } from "../../../../../core/process/ProcessState.js";
11
12
 
12
13
  export class OutlineRenderPlugin extends EnginePlugin {
13
14
  constructor() {
@@ -137,6 +138,12 @@ export class OutlineRenderPlugin extends EnginePlugin {
137
138
  }
138
139
 
139
140
  async startup() {
141
+
142
+ if (this.getState().getValue() === ProcessState.Running) {
143
+ //already running
144
+ return;
145
+ }
146
+
140
147
  const graphics = this.engine.graphics;
141
148
  const viewport_size = graphics.viewport.size;
142
149
 
@@ -44,8 +44,30 @@ function __getDepthMaterial(object) {
44
44
  * @return {boolean}
45
45
  */
46
46
  function scene_object_filter(object3D) {
47
- return object3D.castShadow
48
- && object3D.visible
47
+
48
+ if (object3D.castShadow === false) {
49
+ return false;
50
+ }
51
+
52
+ if (object3D.visible === false) {
53
+ return false;
54
+ }
55
+
56
+ if (object3D.isMesh) {
57
+
58
+ /**
59
+ * @type {THREE.Material|null|undefined}
60
+ */
61
+ const material = (object3D.customDepthMaterial !== null ? object3D.customDepthMaterial : object3D.material);
62
+
63
+ if (material && material.visible === false) {
64
+ //material's main
65
+ return false;
66
+ }
67
+
68
+ }
69
+
70
+ return true;
49
71
  }
50
72
 
51
73
  export class ThreeLightBinding extends LightBinding {
@@ -274,7 +274,7 @@ export class InstancedMeshGroup {
274
274
  //get index
275
275
  const index = this.count;
276
276
  //grow
277
- this.setCount(this.count + 1);
277
+ this.setCount(index + 1);
278
278
 
279
279
  this.indices[reference] = index;
280
280
  this.references[index] = reference;
@@ -68,13 +68,6 @@ export class MicronGeometryPatch {
68
68
  */
69
69
  this.children = [];
70
70
 
71
- /**
72
- * Runtime dependency patches, if this patch is refined at runtime - dependencies must be refined as well
73
- * These dependencies allow for more aggressive simplification of topology
74
- * @type {number[]}
75
- */
76
- this.dependencies = [];
77
-
78
71
  /**
79
72
  * Level of detail, lower number means more detailed
80
73
  * @type {number}
@@ -1,9 +1,19 @@
1
- import { NoBlending, RGBAFormat, ShaderMaterial, UniformsUtils, Vector2, WebGLMultisampleRenderTarget } from "three";
1
+ import {
2
+ Color,
3
+ NoBlending,
4
+ RGBAFormat,
5
+ ShaderMaterial,
6
+ UniformsUtils,
7
+ Vector2,
8
+ WebGLMultisampleRenderTarget
9
+ } from "three";
2
10
  import { BlurShaderUtils, DepthLimitedBlurShader } from "three/examples/jsm/shaders/DepthLimitedBlurShader.js";
3
11
  import { renderScreenSpace } from "../../utils/renderScreenSpace.js";
4
12
 
13
+ const scratch_color = new Color();
14
+
5
15
  export class DepthLimitedBlur {
6
- constructor({ format = RGBAFormat, radius = 8 }) {
16
+ constructor({ format = RGBAFormat, radius = 8, clear_color = 0, clear_alpha = 1 }) {
7
17
 
8
18
  /**
9
19
  *
@@ -43,6 +53,9 @@ export class DepthLimitedBlur {
43
53
 
44
54
  this.__blur_radius = radius;
45
55
  this.__blur_std_dev = 4;
56
+
57
+ this.__clear_color = new Color(clear_color);
58
+ this.__clear_alpha = clear_alpha;
46
59
  }
47
60
 
48
61
  configureMaterials() {
@@ -113,21 +126,31 @@ export class DepthLimitedBlur {
113
126
  mx.uniforms.size.value.set(this.__rt_output.width, this.__rt_output.height);
114
127
  my.uniforms.size.value.set(this.__rt_output.width, this.__rt_output.height);
115
128
 
116
-
129
+ // remember renderer state
117
130
  const __old_state_rt = renderer.getRenderTarget();
118
-
131
+ const __old_clear_color = scratch_color;
132
+ renderer.getClearColor(__old_clear_color);
133
+ const __old_clear_alpha = renderer.getClearAlpha();
134
+ const __old_auto_clear = renderer.autoClear;
135
+
136
+ //
137
+ renderer.autoClear = false;
138
+ renderer.setClearColor(this.__clear_color);
119
139
  renderer.setRenderTarget(this.__intermediate);
120
140
  renderer.clearColor();
121
141
 
122
142
  renderScreenSpace(renderer, mx);
123
143
 
124
144
  renderer.setRenderTarget(this.__rt_output);
145
+
125
146
  renderer.clearColor();
126
147
 
127
148
  renderScreenSpace(renderer, my);
128
149
 
129
150
  // restore state
130
151
  renderer.setRenderTarget(__old_state_rt);
152
+ renderer.setClearColor(__old_clear_color, __old_clear_alpha);
153
+ renderer.autoClear = __old_auto_clear;
131
154
  }
132
155
 
133
156
  /**
@@ -6,6 +6,7 @@ import {
6
6
  RedFormat,
7
7
  ShaderMaterial,
8
8
  UniformsUtils,
9
+ UnsignedByteType,
9
10
  WebGLMultisampleRenderTarget
10
11
  } from "three";
11
12
  import { SAOShader } from "./SAOShader.js";
@@ -27,7 +28,9 @@ export class AmbientOcclusionPostProcessEffect extends EnginePlugin {
27
28
  fragmentShader: SAOShader.fragmentShader,
28
29
  vertexShader: SAOShader.vertexShader,
29
30
  uniforms: UniformsUtils.clone(SAOShader.uniforms),
30
- glslVersion: GLSL3
31
+ glslVersion: GLSL3,
32
+ depthWrite: false,
33
+ depthTest: false
31
34
  });
32
35
 
33
36
  // AO parameters
@@ -89,6 +92,8 @@ export class AmbientOcclusionPostProcessEffect extends EnginePlugin {
89
92
  magFilter: LinearFilter,
90
93
 
91
94
  format: RedFormat,
95
+ type: UnsignedByteType,
96
+ internalFormat: 'R8',
92
97
  depthBuffer: false,
93
98
  stencilBuffer: false,
94
99
  generateMipmaps: false,
@@ -106,7 +111,7 @@ export class AmbientOcclusionPostProcessEffect extends EnginePlugin {
106
111
  * @type {DepthLimitedBlur}
107
112
  * @private
108
113
  */
109
- this.__blur = new DepthLimitedBlur({ format: RedFormat });
114
+ this.__blur = new DepthLimitedBlur({ format: RedFormat, clear_color: 0xFFFFFF });
110
115
  }
111
116
 
112
117
  /**
@@ -302,7 +307,9 @@ export class AmbientOcclusionPostProcessEffect extends EnginePlugin {
302
307
  // bind compositing layer
303
308
  this.__composit_layer = graphics.layerComposer.createLayer(
304
309
  {
305
- format: RedFormat
310
+ format: RedFormat,
311
+ type: UnsignedByteType,
312
+ internalFormat: 'R8'
306
313
  },
307
314
  BlendingType.Multiply
308
315
  );
@@ -1,186 +1,186 @@
1
- import { Matrix4, Vector2 } from 'three';
2
-
3
- /**
4
- * TODO
5
- */
6
-
7
- const SAOShader = {
8
- defines: {
9
- 'NUM_SAMPLES': 7,
10
- 'NUM_RINGS': 4,
11
- 'NORMAL_TEXTURE': 0,
12
- 'DIFFUSE_TEXTURE': 0,
13
- 'DEPTH_PACKING': 1,
14
- 'PERSPECTIVE_CAMERA': 1
15
- },
16
- uniforms: {
17
-
18
- 'tDepth': { value: null },
19
- 'tNormal': { value: null },
20
- 'size': { value: new Vector2(512, 512) },
21
-
22
- 'cameraNear': { value: 1 },
23
- 'cameraFar': { value: 100 },
24
- 'cameraProjectionMatrix': { value: new Matrix4() },
25
- 'cameraInverseProjectionMatrix': { value: new Matrix4() },
26
-
27
- 'intensity': { value: 0.1 },
28
- 'bias': { value: 0.5 },
29
-
30
- 'minResolution': { value: 0.0 },
31
- 'kernelRadius': { value: 100.0 },
32
- 'randomSeed': { value: 0.0 }
33
- },
34
- vertexShader: /* glsl */`
35
-
36
- varying vec2 vUv;
37
-
38
- void main() {
39
- vUv = uv;
40
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
41
- }`,
42
-
43
- fragmentShader: /* glsl */`
44
-
45
- #include <common>
46
-
47
- varying vec2 vUv;
48
-
49
- uniform sampler2D tDepth;
50
-
51
- #if NORMAL_TEXTURE == 1
52
- uniform sampler2D tNormal;
53
- #endif
54
-
55
- uniform float cameraNear;
56
- uniform float cameraFar;
57
- uniform mat4 cameraProjectionMatrix;
58
- uniform mat4 cameraInverseProjectionMatrix;
59
-
60
- uniform float intensity;
61
- uniform float bias;
62
- uniform float kernelRadius;
63
- uniform float minResolution;
64
- uniform vec2 size;
65
- uniform float randomSeed;
66
-
67
- // RGBA depth
68
-
69
- #include <packing>
70
-
71
- out float out_occlusion;
72
-
73
- float getDepth( const in vec2 screenPosition ) {
74
- #if DEPTH_PACKING == 1
75
- return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );
76
- #else
77
- return texture2D( tDepth, screenPosition ).x;
78
- #endif
79
- }
80
-
81
- float getViewZ( const in float depth ) {
82
- #if PERSPECTIVE_CAMERA == 1
83
- return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );
84
- #else
85
- return orthographicDepthToViewZ( depth, cameraNear, cameraFar );
86
- #endif
87
- }
88
-
89
- vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) {
90
- float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3];
91
- vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 );
92
- clipPosition *= clipW; // unprojection.
93
-
94
- return ( cameraInverseProjectionMatrix * clipPosition ).xyz;
95
- }
96
-
97
- vec3 getViewNormal( const in vec3 viewPosition, const in vec2 screenPosition ) {
98
- #if NORMAL_TEXTURE == 1
99
- return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz );
100
- #else
101
- return normalize( cross( dFdx( viewPosition ), dFdy( viewPosition ) ) );
102
- #endif
103
- }
104
-
105
- // Non-sin based hash function, fast and has good randomness
106
- float hash12(vec2 p){
107
- vec3 p3 = fract(vec3(p.xyx) * .1031);
108
- p3 += dot(p3, p3.yzx + 33.33);
109
- return fract((p3.x + p3.y) * p3.z);
110
- }
111
-
112
- float minResolutionMultipliedByCameraFar;
113
-
114
- float getOcclusion( const in vec3 centerViewPosition, const in vec3 centerViewNormal, const in vec3 sampleViewPosition ) {
115
- vec3 viewDelta = sampleViewPosition - centerViewPosition;
116
-
117
- float viewDistance = length( viewDelta );
118
-
119
- float vn = dot( centerViewNormal, viewDelta );
120
- float a2 = (vn - minResolutionMultipliedByCameraFar) / viewDistance - bias;
121
- float a1 = (1.0 + pow2( viewDistance ) );
122
-
123
- return max(0.0, a2) / a1;
124
- }
125
-
126
- // moving costly divides into consts
127
- const float ANGLE_STEP = PI2 * float( NUM_RINGS ) / float( NUM_SAMPLES );
128
- const float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES );
129
-
130
- float getAmbientOcclusion( const in vec3 centerViewPosition ) {
131
- // precompute some variables require in getOcclusion.
132
- minResolutionMultipliedByCameraFar = minResolution * cameraFar;
133
- vec3 centerViewNormal = getViewNormal( centerViewPosition, vUv );
134
-
135
- // jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/
136
- float angle = hash12( vUv + randomSeed ) * PI2;
137
- vec2 radius = vec2( kernelRadius * INV_NUM_SAMPLES ) / size;
138
-
139
- float occlusionSum = 0.0;
140
- float weightSum = 0.0;
141
-
142
- for( int i = 0; i < NUM_SAMPLES; i ++ ) {
143
- vec2 sampleUv = vUv + vec2( cos( angle ), sin( angle ) ) * radius * float(i+1);
144
-
145
- angle += ANGLE_STEP;
146
-
147
- float sampleDepth = getDepth( sampleUv );
148
-
149
- if( sampleDepth >= ( 1.0 - EPSILON ) ) {
150
- // skip, too far
151
- continue;
152
- }
153
-
154
- float sampleViewZ = getViewZ( sampleDepth );
155
-
156
- vec3 sampleViewPosition = getViewPosition( sampleUv, sampleDepth, sampleViewZ );
157
-
158
- occlusionSum += getOcclusion( centerViewPosition, centerViewNormal, sampleViewPosition );
159
-
160
- weightSum += 1.0;
161
- }
162
-
163
- if( weightSum == 0.0 ) discard;
164
-
165
- return occlusionSum * ( intensity / weightSum );
166
- }
167
-
168
- void main() {
169
- float centerDepth = getDepth( vUv );
170
- if( centerDepth >= ( 1.0 - EPSILON ) ) {
171
- discard;
172
- }
173
-
174
- float centerViewZ = getViewZ( centerDepth );
175
- vec3 viewPosition = getViewPosition( vUv, centerDepth, centerViewZ );
176
-
177
- float ambientOcclusion = getAmbientOcclusion( viewPosition );
178
-
179
- float invOcclusion = 1.0 - ambientOcclusion;
180
-
181
- out_occlusion = invOcclusion;
182
- }`
183
-
184
- };
185
-
186
- export { SAOShader };
1
+ import { Matrix4, Vector2 } from 'three';
2
+
3
+ /**
4
+ * TODO
5
+ */
6
+
7
+ const SAOShader = {
8
+ defines: {
9
+ 'NUM_SAMPLES': 7,
10
+ 'NUM_RINGS': 4,
11
+ 'NORMAL_TEXTURE': 0,
12
+ 'DIFFUSE_TEXTURE': 0,
13
+ 'DEPTH_PACKING': 1,
14
+ 'PERSPECTIVE_CAMERA': 1
15
+ },
16
+ uniforms: {
17
+
18
+ 'tDepth': { value: null },
19
+ 'tNormal': { value: null },
20
+ 'size': { value: new Vector2(512, 512) },
21
+
22
+ 'cameraNear': { value: 1 },
23
+ 'cameraFar': { value: 100 },
24
+ 'cameraProjectionMatrix': { value: new Matrix4() },
25
+ 'cameraInverseProjectionMatrix': { value: new Matrix4() },
26
+
27
+ 'intensity': { value: 0.1 },
28
+ 'bias': { value: 0.5 },
29
+
30
+ 'minResolution': { value: 0.0 },
31
+ 'kernelRadius': { value: 100.0 },
32
+ 'randomSeed': { value: 0.0 }
33
+ },
34
+ vertexShader: /* glsl */`
35
+
36
+ varying vec2 vUv;
37
+
38
+ void main() {
39
+ vUv = uv;
40
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
41
+ }`,
42
+
43
+ fragmentShader: /* glsl */`
44
+
45
+ #include <common>
46
+
47
+ varying vec2 vUv;
48
+
49
+ uniform sampler2D tDepth;
50
+
51
+ #if NORMAL_TEXTURE == 1
52
+ uniform sampler2D tNormal;
53
+ #endif
54
+
55
+ uniform float cameraNear;
56
+ uniform float cameraFar;
57
+ uniform mat4 cameraProjectionMatrix;
58
+ uniform mat4 cameraInverseProjectionMatrix;
59
+
60
+ uniform float intensity;
61
+ uniform float bias;
62
+ uniform float kernelRadius;
63
+ uniform float minResolution;
64
+ uniform vec2 size;
65
+ uniform float randomSeed;
66
+
67
+ // RGBA depth
68
+
69
+ #include <packing>
70
+
71
+ out float out_occlusion;
72
+
73
+ float getDepth( const in vec2 screenPosition ) {
74
+ #if DEPTH_PACKING == 1
75
+ return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );
76
+ #else
77
+ return texture2D( tDepth, screenPosition ).x;
78
+ #endif
79
+ }
80
+
81
+ float getViewZ( const in float depth ) {
82
+ #if PERSPECTIVE_CAMERA == 1
83
+ return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );
84
+ #else
85
+ return orthographicDepthToViewZ( depth, cameraNear, cameraFar );
86
+ #endif
87
+ }
88
+
89
+ vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) {
90
+ float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3];
91
+ vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 );
92
+ clipPosition *= clipW; // unprojection.
93
+
94
+ return ( cameraInverseProjectionMatrix * clipPosition ).xyz;
95
+ }
96
+
97
+ vec3 getViewNormal( const in vec3 viewPosition, const in vec2 screenPosition ) {
98
+ #if NORMAL_TEXTURE == 1
99
+ return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz );
100
+ #else
101
+ return normalize( cross( dFdx( viewPosition ), dFdy( viewPosition ) ) );
102
+ #endif
103
+ }
104
+
105
+ // Non-sin based hash function, fast and has good randomness
106
+ float hash12(vec2 p){
107
+ vec3 p3 = fract(vec3(p.xyx) * .1031);
108
+ p3 += dot(p3, p3.yzx + 33.33);
109
+ return fract((p3.x + p3.y) * p3.z);
110
+ }
111
+
112
+ float minResolutionMultipliedByCameraFar;
113
+
114
+ float getOcclusion( const in vec3 centerViewPosition, const in vec3 centerViewNormal, const in vec3 sampleViewPosition ) {
115
+ vec3 viewDelta = sampleViewPosition - centerViewPosition;
116
+
117
+ float viewDistance = length( viewDelta );
118
+
119
+ float vn = dot( centerViewNormal, viewDelta );
120
+ float a2 = (vn - minResolutionMultipliedByCameraFar) / viewDistance - bias;
121
+ float a1 = (1.0 + pow2( viewDistance ) );
122
+
123
+ return max(0.0, a2) / a1;
124
+ }
125
+
126
+ // moving costly divides into consts
127
+ const float ANGLE_STEP = PI2 * float( NUM_RINGS ) / float( NUM_SAMPLES );
128
+ const float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES );
129
+
130
+ float getAmbientOcclusion( const in vec3 centerViewPosition ) {
131
+ // precompute some variables require in getOcclusion.
132
+ minResolutionMultipliedByCameraFar = minResolution * cameraFar;
133
+ vec3 centerViewNormal = getViewNormal( centerViewPosition, vUv );
134
+
135
+ // jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/
136
+ float angle = hash12( vUv + randomSeed ) * PI2;
137
+ vec2 radius = vec2( kernelRadius * INV_NUM_SAMPLES ) / size;
138
+
139
+ float occlusionSum = 0.0;
140
+ float weightSum = 0.0;
141
+
142
+ for( int i = 0; i < NUM_SAMPLES; i ++ ) {
143
+ vec2 sampleUv = vUv + vec2( cos( angle ), sin( angle ) ) * radius * float(i+1);
144
+
145
+ angle += ANGLE_STEP;
146
+
147
+ float sampleDepth = getDepth( sampleUv );
148
+
149
+ if( sampleDepth >= ( 1.0 - EPSILON ) ) {
150
+ // skip, too far
151
+ continue;
152
+ }
153
+
154
+ float sampleViewZ = getViewZ( sampleDepth );
155
+
156
+ vec3 sampleViewPosition = getViewPosition( sampleUv, sampleDepth, sampleViewZ );
157
+
158
+ occlusionSum += getOcclusion( centerViewPosition, centerViewNormal, sampleViewPosition );
159
+
160
+ weightSum += 1.0;
161
+ }
162
+
163
+ if( weightSum == 0.0 ) discard;
164
+
165
+ return occlusionSum * ( intensity / weightSum );
166
+ }
167
+
168
+ void main() {
169
+ float centerDepth = getDepth( vUv );
170
+ if( centerDepth >= ( 1.0 - EPSILON ) ) {
171
+ discard;
172
+ }
173
+
174
+ float centerViewZ = getViewZ( centerDepth );
175
+ vec3 viewPosition = getViewPosition( vUv, centerDepth, centerViewZ );
176
+
177
+ float ambientOcclusion = getAmbientOcclusion( viewPosition );
178
+
179
+ float invOcclusion = 1.0 - ambientOcclusion;
180
+
181
+ out_occlusion = invOcclusion;
182
+ }`
183
+
184
+ };
185
+
186
+ export { SAOShader };
@@ -89,12 +89,12 @@ function makeShader(texture) {
89
89
  * @param {THREE.Texture} texture
90
90
  * @param {THREE.WebGLRenderer} renderer
91
91
  * @param flipY
92
- * @return {{view: View, render: render}}
92
+ * @return {{view: View, render: function}}
93
93
  */
94
94
  export function buildCanvasViewFromTexture({
95
- height,
96
- width,
97
95
  texture = CheckersTexture.create(),
96
+ width = texture.image.width,
97
+ height = texture.image.height,
98
98
  renderer,
99
99
  flipY = true
100
100
  }) {
@@ -82,6 +82,7 @@ export class EnginePluginManager extends BaseProcess {
82
82
  if (state === ProcessState.Initialized || state === ProcessState.Running) {
83
83
  const dependencies = plugin.dependencies;
84
84
 
85
+ // resolve dependencies
85
86
  for (let i = 0; i < dependencies.length; i++) {
86
87
  const dependency = dependencies[i];
87
88
 
@@ -206,7 +207,7 @@ export class EnginePluginManager extends BaseProcess {
206
207
  async shutdown() {
207
208
  super.shutdown();
208
209
 
209
- return this.__transition_active_plugins_to(ProcessState.Initialized);
210
+ return this.__transition_active_plugins_to(ProcessState.Finalized);
210
211
  }
211
212
 
212
213
  /**
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "productName": "Meep",
6
6
  "description": "production-ready JavaScript game engine based on Entity Component System Architecture",
7
7
  "author": "Alexander Goldring",
8
- "version": "2.34.37",
8
+ "version": "2.34.41",
9
9
  "dependencies": {
10
10
  "gl-matrix": "3.4.3",
11
11
  "fast-levenshtein": "2.0.6",