@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.
- package/core/bvh2/BinaryNode.js +93 -82
- package/core/bvh2/BinaryNode.spec.js +1 -0
- package/core/bvh2/LeafNode.js +20 -11
- package/core/bvh2/Node.js +1 -0
- package/core/geom/3d/aabb/aabb3_computeDistanceAbovePlane.js +1 -1
- package/engine/ecs/foliage/InstancedFoliage.js +2 -2
- package/engine/ecs/foliage/ViewState.js +5 -30
- package/engine/graphics/composit/CompositLayer.js +15 -1
- package/engine/graphics/ecs/highlight/plugin/OutlineRenderPlugin.js +7 -0
- package/engine/graphics/ecs/light/binding/three/ThreeLightBinding.js +24 -2
- package/engine/graphics/geometry/instancing/InstancedMeshGroup.js +1 -1
- package/engine/graphics/micron/format/MicronGeometryPatch.js +0 -7
- package/engine/graphics/render/buffer/simple-fx/DepthLimitedBlur.js +27 -4
- package/engine/graphics/render/buffer/simple-fx/ao/AmbientOcclusionPostProcessEffect.js +10 -3
- package/engine/graphics/render/buffer/simple-fx/ao/SAOShader.js +186 -186
- package/engine/graphics/render/visibility/hiz/buildCanvasViewFromTexture.js +3 -3
- package/engine/plugin/EnginePluginManager.js +2 -1
- package/package.json +1 -1
package/core/bvh2/BinaryNode.js
CHANGED
|
@@ -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
|
-
|
|
117
|
+
let visitCount = 0;
|
|
111
118
|
|
|
112
|
-
|
|
119
|
+
const stackOffset = stackPointer;
|
|
113
120
|
|
|
114
|
-
|
|
121
|
+
stack[stackPointer++] = this;
|
|
115
122
|
|
|
116
|
-
|
|
123
|
+
let n;
|
|
117
124
|
|
|
118
|
-
|
|
125
|
+
while (stackPointer-- > stackOffset) {
|
|
119
126
|
|
|
120
|
-
|
|
127
|
+
visitCount++;
|
|
121
128
|
|
|
122
|
-
|
|
129
|
+
n = stack[stackPointer];
|
|
123
130
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
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
|
|
603
|
+
const left = this.left;
|
|
579
604
|
|
|
580
|
-
const lL =
|
|
581
|
-
const lR =
|
|
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
|
-
|
|
612
|
+
left.right = r;
|
|
588
613
|
if (r !== null) {
|
|
589
|
-
r.parentNode =
|
|
614
|
+
r.parentNode = left;
|
|
590
615
|
}
|
|
591
616
|
|
|
592
|
-
|
|
617
|
+
left.left = lR;
|
|
593
618
|
|
|
594
|
-
|
|
619
|
+
left.updateLeafNodeCount();
|
|
620
|
+
left.updateHeight();
|
|
595
621
|
|
|
596
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
package/core/bvh2/LeafNode.js
CHANGED
|
@@ -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
|
@@ -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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
48
|
-
|
|
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 {
|
|
@@ -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 {
|
|
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:
|
|
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.
|
|
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.
|
|
8
|
+
"version": "2.34.41",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|