@woosh/meep-engine 2.27.0 → 2.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/geom/3d/plane_computeConvex3PlaneIntersection.js +17 -25
- package/core/geom/AABB2.d.ts +2 -0
- package/core/geom/GeometryMath.js +0 -127
- package/core/geom/random/randomPointInBox.js +12 -0
- package/core/geom/random/randomPointInCircle.js +18 -0
- package/core/geom/random/randomPointInPoint.js +8 -0
- package/core/geom/random/randomPointInSphere.js +31 -0
- package/core/geom/random/randomPointOnBox.js +33 -0
- package/core/geom/random/randomPointOnSphere.js +27 -0
- package/core/math/noise/sdnoise.js +24 -39
- package/core/process/worker/WorkerBuilder.js +5 -1
- package/editor/process/symbolic/makeParticleEmitterSymbolicDisplay.js +1 -1
- package/editor/view/ecs/components/particles/ParticleLayerController.js +2 -4
- package/engine/Engine.d.ts +5 -1
- package/engine/Engine.js +35 -17
- package/engine/EngineHarness.js +9 -1
- package/engine/animation/AnimationUtils.js +8 -0
- package/engine/asset/AssetManager.js +14 -3
- package/engine/asset/loaders/image/codec/CodecWithFallback.js +1 -1
- package/engine/asset/loaders/image/png/PNGReader.js +19 -21
- package/engine/ecs/EntityManager.js +10 -0
- package/engine/ecs/terrain/overlay/TerrainOverlay.js +8 -1
- package/engine/graphics/camera/makeOrbitalCameraController.js +2 -3
- package/engine/graphics/ecs/camera/topdown/ComputeCameraFacingVector.js +21 -0
- package/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +2 -0
- package/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +26 -0
- package/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +4 -24
- package/engine/graphics/ecs/mesh/applyTransform.js +5 -7
- package/engine/graphics/particles/particular/engine/ParticularEngine.js +1 -0
- package/engine/graphics/particles/particular/engine/emitter/EmissionFromType.js +8 -0
- package/engine/graphics/particles/particular/engine/emitter/EmissionShapeType.js +9 -0
- package/engine/graphics/particles/particular/engine/emitter/PARTICLE_ATTRIBUTES.js +3 -0
- package/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.js +61 -36
- package/engine/graphics/particles/particular/engine/emitter/ParticleLayer.js +17 -20
- package/engine/graphics/particles/particular/engine/emitter/ParticleLayer.spec.js +3 -1
- package/engine/graphics/particles/particular/engine/emitter/ParticlePool.js +30 -10
- package/engine/graphics/particles/particular/engine/parameter/ParameterLookupTable.js +4 -6
- package/engine/graphics/particles/particular/engine/parameter/ParameterTrackSet.js +6 -3
- package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js +271 -1
- package/engine/graphics/particles/particular/engine/renderers/billboard/prototypeBillboardRenderer.js +164 -0
- package/engine/graphics/particles/particular/engine/shader/ShaderManager.js +10 -555
- package/engine/graphics/particles/particular/engine/simulator/AbstractSimulationStep.js +6 -0
- package/engine/graphics/particles/particular/engine/simulator/SimulationStepFixedPhysics.js +16 -1
- package/engine/graphics/particles/particular/engine/simulator/update_parameters.js +41 -0
- package/engine/graphics/render/buffer/FrameBufferManager.js +2 -0
- package/engine/graphics/render/visibility/IncrementalDeltaSet.js +5 -0
- package/engine/graphics/render/visibility/VisibilityComputer.js +6 -6
- package/engine/graphics/render/visibility/VisibilityFilter.js +10 -0
- package/engine/navigation/ecs/components/Path.d.ts +7 -0
- package/engine/navigation/ecs/components/Path.js +33 -49
- package/engine/navigation/ecs/path_following/PathFollower.d.ts +5 -15
- package/package.json +3 -3
- package/view/elements/progress/segmented/SegmentedResourceBarView.js +7 -0
- package/view/minimap/Minimap.js +1 -1
- package/view/util/DomSizeObserver.js +59 -10
|
@@ -74,8 +74,10 @@ export class ParticlePool {
|
|
|
74
74
|
this.occupancy.set(index, true);
|
|
75
75
|
|
|
76
76
|
//ensure attribute arrays are large enough
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
const min_capacity = index + 1;
|
|
78
|
+
|
|
79
|
+
if (this.capacity < min_capacity) {
|
|
80
|
+
this.growCapacity(min_capacity);
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
return index;
|
|
@@ -86,7 +88,9 @@ export class ParticlePool {
|
|
|
86
88
|
* @returns {boolean}
|
|
87
89
|
*/
|
|
88
90
|
hasHoles() {
|
|
89
|
-
|
|
91
|
+
const occupancy = this.occupancy;
|
|
92
|
+
|
|
93
|
+
return occupancy.nextClearBit(0) < occupancy.size();
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
/**
|
|
@@ -111,6 +115,8 @@ export class ParticlePool {
|
|
|
111
115
|
holeIndex = occupancy.nextClearBit(0);
|
|
112
116
|
lastIndex = occupancy.previousSetBit(occupancy.size());
|
|
113
117
|
|
|
118
|
+
const attributes = this.attributes;
|
|
119
|
+
|
|
114
120
|
while (holeIndex < lastIndex) {
|
|
115
121
|
|
|
116
122
|
//move occupancy flag from the last to the hole
|
|
@@ -119,7 +125,7 @@ export class ParticlePool {
|
|
|
119
125
|
|
|
120
126
|
//move attribute values
|
|
121
127
|
for (attributeIndex = 0; attributeIndex < numAttributes; attributeIndex++) {
|
|
122
|
-
const attribute =
|
|
128
|
+
const attribute = attributes[attributeIndex];
|
|
123
129
|
|
|
124
130
|
const itemSize = attribute.itemSize;
|
|
125
131
|
|
|
@@ -127,13 +133,13 @@ export class ParticlePool {
|
|
|
127
133
|
*
|
|
128
134
|
* @type {Float32Array}
|
|
129
135
|
*/
|
|
130
|
-
const
|
|
136
|
+
const attribute_array = attribute.array;
|
|
131
137
|
|
|
132
138
|
//do swaps in the old array
|
|
133
139
|
const targetIndex = holeIndex * itemSize;
|
|
134
140
|
const sourceIndex = lastIndex * itemSize;
|
|
135
141
|
|
|
136
|
-
|
|
142
|
+
attribute_array.copyWithin(targetIndex, sourceIndex, sourceIndex + itemSize);
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
//move hole and last cursors
|
|
@@ -269,7 +275,14 @@ export class ParticlePool {
|
|
|
269
275
|
* @param {number} capacity
|
|
270
276
|
*/
|
|
271
277
|
growCapacity(capacity) {
|
|
272
|
-
const newCapacity = Math.floor(
|
|
278
|
+
const newCapacity = Math.floor(
|
|
279
|
+
max3(
|
|
280
|
+
capacity,
|
|
281
|
+
this.capacity * this.growFactor,
|
|
282
|
+
this.capacity + GROW_MIN_STEP
|
|
283
|
+
)
|
|
284
|
+
);
|
|
285
|
+
|
|
273
286
|
this.setCapacity(newCapacity);
|
|
274
287
|
}
|
|
275
288
|
|
|
@@ -278,8 +291,13 @@ export class ParticlePool {
|
|
|
278
291
|
* @param {number} newCapacity
|
|
279
292
|
*/
|
|
280
293
|
shrinkCapacity(newCapacity) {
|
|
281
|
-
if (
|
|
294
|
+
if (
|
|
295
|
+
newCapacity < this.capacity * this.shrinkFactor
|
|
296
|
+
&& newCapacity < this.capacity - SHRINK_THRESHOLD
|
|
297
|
+
) {
|
|
298
|
+
|
|
282
299
|
this.setCapacity(newCapacity);
|
|
300
|
+
|
|
283
301
|
}
|
|
284
302
|
}
|
|
285
303
|
|
|
@@ -293,8 +311,10 @@ export class ParticlePool {
|
|
|
293
311
|
return;
|
|
294
312
|
}
|
|
295
313
|
|
|
296
|
-
|
|
297
|
-
|
|
314
|
+
const occupancy_size = this.occupancy.size();
|
|
315
|
+
|
|
316
|
+
if (newCapacity < occupancy_size) {
|
|
317
|
+
throw new Error(`Can not set capacity (=${newCapacity}) below occupancy set size (=${occupancy_size})`);
|
|
298
318
|
}
|
|
299
319
|
|
|
300
320
|
this.capacity = newCapacity;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import { inverseLerp } from "../../../../../../core/math/inverseLerp.js";
|
|
2
|
-
import {
|
|
3
|
-
computeHashFloatArray,
|
|
4
|
-
computeHashIntegerArray
|
|
5
|
-
} from "../../../../../../core/math/MathUtils.js";
|
|
2
|
+
import { computeHashFloatArray, computeHashIntegerArray } from "../../../../../../core/math/MathUtils.js";
|
|
6
3
|
import { assert } from "../../../../../../core/assert.js";
|
|
7
4
|
import { max2 } from "../../../../../../core/math/max2.js";
|
|
8
5
|
import { min2 } from "../../../../../../core/math/min2.js";
|
|
@@ -123,11 +120,12 @@ export class ParameterLookupTable {
|
|
|
123
120
|
/**
|
|
124
121
|
*
|
|
125
122
|
* @param {number} position
|
|
126
|
-
* @param {number[]} result
|
|
123
|
+
* @param {number[]|Float32Array|Float64Array} result
|
|
127
124
|
*/
|
|
128
125
|
sample(position, result) {
|
|
129
126
|
assert.isNumber(position, 'position');
|
|
130
|
-
assert.
|
|
127
|
+
assert.greaterThanOrEqual(position, 0, 'position');
|
|
128
|
+
// assert.ok(position >= 0 && position <= 1, `position must be between 0 and 1, instead was ${position}`);
|
|
131
129
|
|
|
132
130
|
const itemSize = this.itemSize;
|
|
133
131
|
const data = this.data;
|
|
@@ -37,12 +37,15 @@ ParameterTrackSet.prototype.forEach = function (visitor) {
|
|
|
37
37
|
*/
|
|
38
38
|
ParameterTrackSet.prototype.getTrackByName = function (name) {
|
|
39
39
|
const tracks = this.tracks;
|
|
40
|
-
|
|
40
|
+
|
|
41
|
+
const tracks_array = tracks.asArray();
|
|
42
|
+
|
|
43
|
+
const nTracks = tracks_array.length;
|
|
41
44
|
|
|
42
45
|
for (let i = 0; i < nTracks; i++) {
|
|
43
|
-
const parameterTrack =
|
|
46
|
+
const parameterTrack = tracks_array[i];
|
|
44
47
|
|
|
45
|
-
if(parameterTrack.name === name){
|
|
48
|
+
if (parameterTrack.name === name) {
|
|
46
49
|
return parameterTrack;
|
|
47
50
|
}
|
|
48
51
|
}
|
package/engine/graphics/particles/particular/engine/renderers/billboard/ParticleBillboardMaterial.js
CHANGED
|
@@ -1,3 +1,273 @@
|
|
|
1
|
-
|
|
1
|
+
import { AddEquation, CustomBlending, Matrix4, OneFactor, OneMinusSrcAlphaFactor, ShaderMaterial } from "three";
|
|
2
|
+
import { Vector2 as ThreeVector2 } from "three/src/math/Vector2.js";
|
|
3
|
+
import { ParticleSpecification } from "../../../group/ParticleSpecification.js";
|
|
4
|
+
import { ParticleAttribute } from "../../../group/ParticleAttribute.js";
|
|
5
|
+
import { ParticleAttributeType, ParticleDataType } from "../../../group/ParticleGroup.js";
|
|
2
6
|
|
|
7
|
+
export const BILLBOARD_PARTICLE_SPECIFICATION = new ParticleSpecification();
|
|
8
|
+
|
|
9
|
+
BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('position', ParticleAttributeType.Vector3, ParticleDataType.Float32));
|
|
10
|
+
BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('atlasPatch', ParticleAttributeType.Vector4, ParticleDataType.Float32));
|
|
11
|
+
BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('size', ParticleAttributeType.Scalar, ParticleDataType.Float32));
|
|
12
|
+
BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('velocity', ParticleAttributeType.Vector3, ParticleDataType.Float32));
|
|
13
|
+
BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('rotation', ParticleAttributeType.Scalar, ParticleDataType.Float32));
|
|
14
|
+
BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('color', ParticleAttributeType.Vector4, ParticleDataType.Float32));
|
|
15
|
+
BILLBOARD_PARTICLE_SPECIFICATION.add(new ParticleAttribute('blending', ParticleAttributeType.Scalar, ParticleDataType.Uint8));
|
|
16
|
+
|
|
17
|
+
export const BILLBOARD_PARTICLE_ATTRIBUTE_POSITION = 0;
|
|
18
|
+
export const BILLBOARD_PARTICLE_ATTRIBUTE_UV = 1;
|
|
19
|
+
export const BILLBOARD_PARTICLE_ATTRIBUTE_SIZE = 2;
|
|
20
|
+
export const BILLBOARD_PARTICLE_ATTRIBUTE_VELOCITY = 3;
|
|
21
|
+
export const BILLBOARD_PARTICLE_ATTRIBUTE_COLOR = 5;
|
|
22
|
+
export const BILLBOARD_PARTICLE_ATTRIBUTE_BLEND = 6;
|
|
23
|
+
|
|
24
|
+
const DEPTH_ERROR_MARGIN = 0.0001;
|
|
25
|
+
|
|
26
|
+
function make_vertex_shader() {
|
|
27
|
+
return `
|
|
28
|
+
uniform float cameraNear;
|
|
29
|
+
uniform float cameraFar;
|
|
30
|
+
uniform vec2 resolution;
|
|
31
|
+
|
|
32
|
+
attribute float size;
|
|
33
|
+
attribute vec4 color;
|
|
34
|
+
attribute vec4 atlasPatch;
|
|
35
|
+
attribute float rotation;
|
|
36
|
+
attribute vec3 velocity;
|
|
37
|
+
attribute float blending;
|
|
38
|
+
|
|
39
|
+
varying vec4 vPatch;
|
|
40
|
+
varying float vSize;
|
|
41
|
+
varying float vFadeDistance;
|
|
42
|
+
varying vec4 vColor;
|
|
43
|
+
varying vec2 vRotationMultiplier;
|
|
44
|
+
varying float vBlending;
|
|
45
|
+
|
|
46
|
+
void main() {
|
|
47
|
+
|
|
48
|
+
vColor = color;
|
|
49
|
+
vSize = size;
|
|
50
|
+
vPatch = atlasPatch;
|
|
51
|
+
vBlending = blending;
|
|
52
|
+
|
|
53
|
+
mat4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix;
|
|
54
|
+
|
|
55
|
+
vec4 position4 = vec4( position, 1.0 );
|
|
56
|
+
|
|
57
|
+
gl_Position = modelViewProjectionMatrix * position4;
|
|
58
|
+
|
|
59
|
+
float rotationGlobal = rotation;
|
|
60
|
+
|
|
61
|
+
//
|
|
62
|
+
#ifdef ALIGN_DIRECTION_ENABLED
|
|
63
|
+
if(velocity != vec3(0.0)){
|
|
64
|
+
|
|
65
|
+
vec4 vecNext = modelViewProjectionMatrix * (position4 + vec4(velocity,0.0) );
|
|
66
|
+
|
|
67
|
+
vec2 p_2 = gl_Position.xy / gl_Position.w;
|
|
68
|
+
vec2 vecNext_2 = vecNext.xy / vecNext.w;
|
|
69
|
+
|
|
70
|
+
vec2 direction = vecNext_2 - p_2;
|
|
71
|
+
|
|
72
|
+
float upAngle = atan(direction.y, direction.x) - 1.57079632679;
|
|
73
|
+
|
|
74
|
+
rotationGlobal = rotationGlobal + upAngle;
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
#endif
|
|
78
|
+
//
|
|
79
|
+
|
|
80
|
+
vRotationMultiplier = vec2( cos(rotationGlobal),sin(rotationGlobal) );
|
|
81
|
+
|
|
82
|
+
float radius = vSize/2.0;
|
|
83
|
+
|
|
84
|
+
#ifdef DEPTH_SOFT_ENABLED
|
|
85
|
+
|
|
86
|
+
vFadeDistance = 1.0 / radius;
|
|
87
|
+
|
|
88
|
+
#endif
|
|
89
|
+
|
|
90
|
+
gl_PointSize = resolution.y * projectionMatrix[1][1] * radius / gl_Position.w;
|
|
91
|
+
}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function make_fragment_shader() {
|
|
95
|
+
return `
|
|
96
|
+
uniform sampler2D tSpriteAtlas;
|
|
97
|
+
uniform sampler2D tDepth;
|
|
98
|
+
uniform float cameraNear;
|
|
99
|
+
uniform float cameraFar;
|
|
100
|
+
uniform mat4 modelViewMatrix;
|
|
101
|
+
uniform mat4 projectionMatrix;
|
|
102
|
+
uniform vec2 resolution;
|
|
103
|
+
|
|
104
|
+
varying float vFadeDistance;
|
|
105
|
+
varying vec4 vPatch;
|
|
106
|
+
varying float vSize;
|
|
107
|
+
varying vec4 vColor;
|
|
108
|
+
varying vec2 vRotationMultiplier;
|
|
109
|
+
varying float vBlending;
|
|
110
|
+
|
|
111
|
+
float depthToLinear( float z ) {
|
|
112
|
+
float f = cameraFar;
|
|
113
|
+
float n = cameraNear;
|
|
114
|
+
|
|
115
|
+
float d_n = 2.0*z - 1.0;
|
|
116
|
+
|
|
117
|
+
float fn = f*n;
|
|
118
|
+
|
|
119
|
+
float z_diff = f - n;
|
|
120
|
+
|
|
121
|
+
float denominator = (f + n - d_n * z_diff );
|
|
122
|
+
|
|
123
|
+
float z_view = (2.0*fn) / denominator;
|
|
124
|
+
|
|
125
|
+
return z_view-n;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
float calculateFade(in float particleDepth, in float sceneDepth){
|
|
130
|
+
float zFade;
|
|
131
|
+
|
|
132
|
+
float linearParticleDepth = depthToLinear(particleDepth);
|
|
133
|
+
|
|
134
|
+
float linearSceneDepth = depthToLinear(sceneDepth);
|
|
135
|
+
|
|
136
|
+
float depthDelta = (linearSceneDepth - linearParticleDepth);
|
|
137
|
+
|
|
138
|
+
float inputDepth = depthDelta* vFadeDistance;
|
|
139
|
+
|
|
140
|
+
if(inputDepth <= 0.0){
|
|
141
|
+
return 0.0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if(inputDepth >= 1.0){
|
|
145
|
+
return 1.0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if(inputDepth <= 0.5){
|
|
149
|
+
zFade = 0.5 * pow( clamp(2.0*inputDepth, 0.0, 1.0), 2.0);
|
|
150
|
+
}else{
|
|
151
|
+
zFade = 1.0 - 0.5 * pow( clamp(2.0*(1.0 - inputDepth), 0.0, 1.0), 2.0);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return zFade;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
void main() {
|
|
158
|
+
float fragmentDepth = gl_FragCoord.z;
|
|
159
|
+
|
|
160
|
+
vec2 pixelPosition = gl_FragCoord.xy / resolution;
|
|
161
|
+
|
|
162
|
+
float sceneDepth = texture2D( tDepth, pixelPosition ).x;
|
|
163
|
+
|
|
164
|
+
#ifdef DEPTH_READ_ENABLED
|
|
165
|
+
|
|
166
|
+
if(fragmentDepth + ${DEPTH_ERROR_MARGIN} > sceneDepth){
|
|
167
|
+
discard;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
#endif
|
|
171
|
+
|
|
172
|
+
vec2 centeredUv = gl_PointCoord.xy - 0.5;
|
|
173
|
+
|
|
174
|
+
vec2 texelCoordinate = vec2( centeredUv.x* vRotationMultiplier.x - centeredUv.y* vRotationMultiplier.y, centeredUv.x * vRotationMultiplier.y + centeredUv.y * vRotationMultiplier.x) + 0.5;
|
|
175
|
+
|
|
176
|
+
texelCoordinate = clamp(texelCoordinate, vec2(0.0), vec2(1.0) );
|
|
177
|
+
|
|
178
|
+
vec2 uv = texelCoordinate*vPatch.zw + vPatch.xy;
|
|
179
|
+
|
|
180
|
+
vec4 spriteColor = texture2D( tSpriteAtlas, uv );
|
|
181
|
+
|
|
182
|
+
if(spriteColor.a == 0.0){
|
|
183
|
+
discard;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
vec4 texel = spriteColor *vColor;
|
|
187
|
+
|
|
188
|
+
// premultiply alpha
|
|
189
|
+
texel.xyz *= texel.a;
|
|
190
|
+
|
|
191
|
+
if(vBlending > 0.1){
|
|
192
|
+
// additive blending
|
|
193
|
+
texel.a = 0.0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
#ifdef DEPTH_SOFT_ENABLED
|
|
197
|
+
|
|
198
|
+
float zFade = calculateFade(fragmentDepth, sceneDepth);
|
|
199
|
+
texel *= zFade;
|
|
200
|
+
|
|
201
|
+
#endif
|
|
202
|
+
|
|
203
|
+
gl_FragColor = texel;
|
|
204
|
+
|
|
205
|
+
}`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/*
|
|
209
|
+
NOTES:
|
|
210
|
+
- To implement per-particle blend modes, we need to have access to what we're blending on to, that is - the color buffer
|
|
211
|
+
Having the color buffer - we can do just about any kind of a blend
|
|
212
|
+
|
|
213
|
+
- Support animation by adding animation sprite sheet to the main sprite atlas, record resolution of the sheet (in frames X,Y) and interpolate over tiles based on some parameter
|
|
214
|
+
*/
|
|
215
|
+
export function make_particle_billboard_shader() {
|
|
216
|
+
const shader = new ShaderMaterial({
|
|
217
|
+
defines: {
|
|
218
|
+
DEPTH_READ_ENABLED: true,
|
|
219
|
+
DEPTH_SOFT_ENABLED: true,
|
|
220
|
+
ALIGN_DIRECTION_ENABLED: false,
|
|
221
|
+
},
|
|
222
|
+
uniforms: {
|
|
223
|
+
tSpriteAtlas: {
|
|
224
|
+
type: 't',
|
|
225
|
+
value: null
|
|
226
|
+
},
|
|
227
|
+
cameraNear: {
|
|
228
|
+
type: 'f',
|
|
229
|
+
value: 1,
|
|
230
|
+
},
|
|
231
|
+
cameraFar: {
|
|
232
|
+
type: 'f',
|
|
233
|
+
value: 1,
|
|
234
|
+
},
|
|
235
|
+
tDepth: {
|
|
236
|
+
type: 't',
|
|
237
|
+
value: null
|
|
238
|
+
},
|
|
239
|
+
tColor: {
|
|
240
|
+
type: 't',
|
|
241
|
+
value: null
|
|
242
|
+
},
|
|
243
|
+
modelViewMatrix: {
|
|
244
|
+
type: 'm4',
|
|
245
|
+
value: new Matrix4()
|
|
246
|
+
},
|
|
247
|
+
projectionMatrix: {
|
|
248
|
+
type: 'm4',
|
|
249
|
+
value: new Matrix4()
|
|
250
|
+
},
|
|
251
|
+
resolution: {
|
|
252
|
+
type: 'v2',
|
|
253
|
+
value: new ThreeVector2()
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
vertexShader: make_vertex_shader(),
|
|
257
|
+
fragmentShader: make_fragment_shader(),
|
|
258
|
+
blending: CustomBlending,
|
|
259
|
+
lights: false,
|
|
260
|
+
depthTest: true,
|
|
261
|
+
depthWrite: false,
|
|
262
|
+
transparent: true,
|
|
263
|
+
vertexColors: false,
|
|
264
|
+
glslVersion: 2
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
shader.blending = CustomBlending;
|
|
268
|
+
shader.blendEquation = AddEquation;
|
|
269
|
+
shader.blendSrc = OneFactor;
|
|
270
|
+
shader.blendDst = OneMinusSrcAlphaFactor;
|
|
271
|
+
|
|
272
|
+
return shader;
|
|
3
273
|
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { EngineHarness } from "../../../../../../EngineHarness.js";
|
|
2
|
+
import { ParticlePool } from "../../emitter/ParticlePool.js";
|
|
3
|
+
import {
|
|
4
|
+
BILLBOARD_PARTICLE_ATTRIBUTE_BLEND,
|
|
5
|
+
BILLBOARD_PARTICLE_ATTRIBUTE_COLOR,
|
|
6
|
+
BILLBOARD_PARTICLE_ATTRIBUTE_POSITION,
|
|
7
|
+
BILLBOARD_PARTICLE_ATTRIBUTE_SIZE,
|
|
8
|
+
BILLBOARD_PARTICLE_ATTRIBUTE_UV,
|
|
9
|
+
BILLBOARD_PARTICLE_SPECIFICATION,
|
|
10
|
+
make_particle_billboard_shader
|
|
11
|
+
} from "./ParticleBillboardMaterial.js";
|
|
12
|
+
import { DataTexture, LinearFilter, LinearMipMapLinearFilter, Matrix4, Points } from "three";
|
|
13
|
+
import { StandardFrameBuffers } from "../../../../../GraphicsEngine.js";
|
|
14
|
+
import { ManagedAtlas } from "../../../../../texture/atlas/ManagedTextureAtlas.js";
|
|
15
|
+
import { writeSample2DDataToDataTexture } from "../../../../../texture/sampler/writeSampler2DDataToDataTexture.js";
|
|
16
|
+
import { ImageRGBADataLoader } from "../../../../../../asset/loaders/image/ImageRGBADataLoader.js";
|
|
17
|
+
import { EngineConfiguration } from "../../../../../../EngineConfiguration.js";
|
|
18
|
+
import { MeshSystem } from "../../../../../ecs/mesh/MeshSystem.js";
|
|
19
|
+
import EntityBuilder from "../../../../../../ecs/EntityBuilder.js";
|
|
20
|
+
import { Transform } from "../../../../../../ecs/transform/Transform.js";
|
|
21
|
+
import Mesh from "../../../../../ecs/mesh/Mesh.js";
|
|
22
|
+
import Vector3 from "../../../../../../../core/geom/Vector3.js";
|
|
23
|
+
import { RenderPassType } from "../../../../../render/RenderPassType.js";
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
const engineHarness = new EngineHarness();
|
|
27
|
+
|
|
28
|
+
async function init(engineHarness) {
|
|
29
|
+
|
|
30
|
+
const engine = await engineHarness.initialize();
|
|
31
|
+
|
|
32
|
+
const config = new EngineConfiguration();
|
|
33
|
+
|
|
34
|
+
config.addSystem(new MeshSystem(engine.graphics, engine.assetManager));
|
|
35
|
+
config.addLoader('image', new ImageRGBADataLoader());
|
|
36
|
+
|
|
37
|
+
await config.apply(engine);
|
|
38
|
+
|
|
39
|
+
main(engine);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @param {Engine} engine
|
|
45
|
+
* @returns {Promise<void>}
|
|
46
|
+
*/
|
|
47
|
+
async function main(engine) {
|
|
48
|
+
const ecd = engine.entityManager.dataset;
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
const particle_pool = new ParticlePool(BILLBOARD_PARTICLE_SPECIFICATION);
|
|
52
|
+
|
|
53
|
+
const particle_a = particle_pool.create();
|
|
54
|
+
|
|
55
|
+
particle_pool.writeAttributeScalar(particle_a, BILLBOARD_PARTICLE_ATTRIBUTE_SIZE, 5);
|
|
56
|
+
particle_pool.writeAttributeVector3(particle_a, BILLBOARD_PARTICLE_ATTRIBUTE_POSITION, 5, 2, 5);
|
|
57
|
+
particle_pool.writeAttributeVector4(particle_a, BILLBOARD_PARTICLE_ATTRIBUTE_UV, 0, 0, 1, 1);
|
|
58
|
+
particle_pool.writeAttributeVector4(particle_a, BILLBOARD_PARTICLE_ATTRIBUTE_COLOR, 1, 1, 1, 1);
|
|
59
|
+
particle_pool.writeAttributeScalar(particle_a, BILLBOARD_PARTICLE_ATTRIBUTE_BLEND, 0);
|
|
60
|
+
|
|
61
|
+
const particle_b = particle_pool.create();
|
|
62
|
+
|
|
63
|
+
particle_pool.writeAttributeScalar(particle_b, BILLBOARD_PARTICLE_ATTRIBUTE_SIZE, 5);
|
|
64
|
+
particle_pool.writeAttributeVector3(particle_b, BILLBOARD_PARTICLE_ATTRIBUTE_POSITION, 10, 2, 5);
|
|
65
|
+
particle_pool.writeAttributeVector4(particle_b, BILLBOARD_PARTICLE_ATTRIBUTE_UV, 0, 0, 1, 1);
|
|
66
|
+
particle_pool.writeAttributeVector4(particle_b, BILLBOARD_PARTICLE_ATTRIBUTE_COLOR, 1, 1, 1, 1);
|
|
67
|
+
particle_pool.writeAttributeScalar(particle_b, BILLBOARD_PARTICLE_ATTRIBUTE_BLEND, 1);
|
|
68
|
+
|
|
69
|
+
const particle_c = particle_pool.create();
|
|
70
|
+
|
|
71
|
+
particle_pool.writeAttributeScalar(particle_c, BILLBOARD_PARTICLE_ATTRIBUTE_SIZE, 5);
|
|
72
|
+
particle_pool.writeAttributeVector3(particle_c, BILLBOARD_PARTICLE_ATTRIBUTE_POSITION, 10, 2, 10);
|
|
73
|
+
particle_pool.writeAttributeVector4(particle_c, BILLBOARD_PARTICLE_ATTRIBUTE_UV, 0, 0, 1, 1);
|
|
74
|
+
particle_pool.writeAttributeVector4(particle_c, BILLBOARD_PARTICLE_ATTRIBUTE_COLOR, 1, 1, 1, 1);
|
|
75
|
+
particle_pool.writeAttributeScalar(particle_c, BILLBOARD_PARTICLE_ATTRIBUTE_BLEND, 1);
|
|
76
|
+
|
|
77
|
+
const particle_d = particle_pool.create();
|
|
78
|
+
|
|
79
|
+
particle_pool.writeAttributeScalar(particle_d, BILLBOARD_PARTICLE_ATTRIBUTE_SIZE, 5);
|
|
80
|
+
particle_pool.writeAttributeVector3(particle_d, BILLBOARD_PARTICLE_ATTRIBUTE_POSITION, 5, 2, 10);
|
|
81
|
+
particle_pool.writeAttributeVector4(particle_d, BILLBOARD_PARTICLE_ATTRIBUTE_UV, 0, 0, 1, 1);
|
|
82
|
+
particle_pool.writeAttributeVector4(particle_d, BILLBOARD_PARTICLE_ATTRIBUTE_COLOR, 1, 1, 1, 1);
|
|
83
|
+
particle_pool.writeAttributeScalar(particle_d, BILLBOARD_PARTICLE_ATTRIBUTE_BLEND, 0);
|
|
84
|
+
|
|
85
|
+
particle_pool.compact();
|
|
86
|
+
|
|
87
|
+
const managedAtlas = new ManagedAtlas(engine.assetManager);
|
|
88
|
+
const sprite_atlas_texture = new DataTexture(new Uint8Array(4), 1, 1);
|
|
89
|
+
sprite_atlas_texture.generateMipmaps = true;
|
|
90
|
+
sprite_atlas_texture.minFilter = LinearMipMapLinearFilter;
|
|
91
|
+
sprite_atlas_texture.magFilter = LinearFilter;
|
|
92
|
+
sprite_atlas_texture.anisotropy = 0; // billboards don't need anisotropy
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
managedAtlas.acquire('data/textures/utility/uv_map_reference.jpg');
|
|
96
|
+
// managedAtlas.acquire('data/textures/particle/UETools/Star_41.png');
|
|
97
|
+
|
|
98
|
+
const shaderMaterial = make_particle_billboard_shader();
|
|
99
|
+
|
|
100
|
+
shaderMaterial.uniforms.tSpriteAtlas.value = sprite_atlas_texture;
|
|
101
|
+
|
|
102
|
+
managedAtlas.atlas.on.painted.add(() => {
|
|
103
|
+
writeSample2DDataToDataTexture(managedAtlas.atlas.sampler, sprite_atlas_texture);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const points = new Points(particle_pool.geometry.getValue(), shaderMaterial);
|
|
107
|
+
points.frustumCulled = false;
|
|
108
|
+
|
|
109
|
+
const layer = engine.graphics.layers.create('x');
|
|
110
|
+
|
|
111
|
+
layer.managed = true;
|
|
112
|
+
layer.visibleSet.initializeUpdate();
|
|
113
|
+
layer.visibleSet.push(points);
|
|
114
|
+
layer.visibleSet.finalizeUpdate();
|
|
115
|
+
|
|
116
|
+
layer.renderPass = RenderPassType.Transparent;
|
|
117
|
+
|
|
118
|
+
engine.graphics.on.visibilityConstructionStarted.add((renderer, camera, scene) => {
|
|
119
|
+
renderer.getSize(shaderMaterial.uniforms.resolution.value);
|
|
120
|
+
|
|
121
|
+
const projectionMatrix = camera.projectionMatrix;
|
|
122
|
+
const modelViewMatrix = (new Matrix4()).multiplyMatrices(camera.matrixWorldInverse, camera.matrixWorld);
|
|
123
|
+
const cameraNear = camera.near;
|
|
124
|
+
const cameraFar = camera.far;
|
|
125
|
+
|
|
126
|
+
const uniforms = shaderMaterial.uniforms;
|
|
127
|
+
|
|
128
|
+
uniforms.projectionMatrix.value = projectionMatrix;
|
|
129
|
+
uniforms.modelViewMatrix.value = modelViewMatrix;
|
|
130
|
+
uniforms.cameraNear.value = cameraNear;
|
|
131
|
+
uniforms.cameraFar.value = cameraFar;
|
|
132
|
+
|
|
133
|
+
const fb = engine.graphics.frameBuffers.getById(StandardFrameBuffers.ColorAndDepth);
|
|
134
|
+
|
|
135
|
+
uniforms.tDepth.value = fb.renderTarget.depthTexture;
|
|
136
|
+
uniforms.tColor.value = fb.renderTarget.texture;
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
EngineHarness.buildCamera({
|
|
140
|
+
engine,
|
|
141
|
+
target: new Vector3(5, 2, 5)
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
EngineHarness.buildOrbitalCameraController({
|
|
145
|
+
engine
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
EngineHarness.buildLights({
|
|
149
|
+
engine
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
EngineHarness.buildTerrain({
|
|
153
|
+
engine,
|
|
154
|
+
enableWater: false
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
new EntityBuilder()
|
|
159
|
+
.add(Mesh.fromJSON({ url: 'data/models/Jauntmessina/Red_Robot/gltf/Model.gltf' }))
|
|
160
|
+
.add(new Transform())
|
|
161
|
+
.build(ecd)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
init(engineHarness);
|