@needle-tools/engine 4.6.1-next.26cf56c → 4.6.1-next.2b6c7ea
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/dist/{needle-engine.bundle-B23LP9xh.min.js → needle-engine.bundle-BzX-r0pE.min.js} +170 -170
- package/dist/{needle-engine.bundle-gJVfKnbJ.js → needle-engine.bundle-CHrGRiUE.js} +8208 -8156
- package/dist/{needle-engine.bundle-B0Kku0-E.umd.cjs → needle-engine.bundle-Cyccgqnt.umd.cjs} +146 -146
- package/dist/needle-engine.js +342 -341
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-BPhSPjAn.umd.cjs → postprocessing-CjW23fio.umd.cjs} +17 -17
- package/dist/{postprocessing-XKNCD6By.js → postprocessing-DYLNOL3W.js} +1 -0
- package/dist/{postprocessing-DoBd3XIR.min.js → postprocessing-xYQWCHFu.min.js} +26 -26
- package/lib/engine/engine_context.d.ts +2 -0
- package/lib/engine/engine_context.js +6 -0
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/Antialiasing.js +2 -1
- package/lib/engine-components/postprocessing/Effects/Antialiasing.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/BloomEffect.d.ts +1 -1
- package/lib/engine-components/postprocessing/Effects/BloomEffect.js +3 -0
- package/lib/engine-components/postprocessing/Effects/BloomEffect.js.map +1 -1
- package/lib/engine-components/postprocessing/PostProcessingEffect.d.ts +18 -0
- package/lib/engine-components/postprocessing/PostProcessingEffect.js +18 -0
- package/lib/engine-components/postprocessing/PostProcessingEffect.js.map +1 -1
- package/lib/engine-components/postprocessing/PostProcessingHandler.d.ts +4 -3
- package/lib/engine-components/postprocessing/PostProcessingHandler.js +83 -119
- package/lib/engine-components/postprocessing/PostProcessingHandler.js.map +1 -1
- package/lib/engine-components/postprocessing/Volume.d.ts +0 -1
- package/lib/engine-components/postprocessing/Volume.js +48 -36
- package/lib/engine-components/postprocessing/Volume.js.map +1 -1
- package/lib/engine-components/postprocessing/index.d.ts +1 -0
- package/lib/engine-components/postprocessing/index.js +1 -0
- package/lib/engine-components/postprocessing/index.js.map +1 -1
- package/lib/engine-components/postprocessing/utils.d.ts +40 -0
- package/lib/engine-components/postprocessing/utils.js +101 -0
- package/lib/engine-components/postprocessing/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/engine_context.ts +8 -1
- package/src/engine-components/postprocessing/Effects/Antialiasing.ts +2 -1
- package/src/engine-components/postprocessing/Effects/BloomEffect.ts +4 -2
- package/src/engine-components/postprocessing/PostProcessingEffect.ts +19 -0
- package/src/engine-components/postprocessing/PostProcessingHandler.ts +94 -123
- package/src/engine-components/postprocessing/Volume.ts +52 -42
- package/src/engine-components/postprocessing/index.ts +2 -1
- package/src/engine-components/postprocessing/utils.ts +121 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Effect } from "postprocessing";
|
|
1
|
+
import type { Effect, EffectComposer } from "postprocessing";
|
|
2
2
|
|
|
3
3
|
import { isDevEnvironment, showBalloonMessage } from "../../engine/debug/index.js";
|
|
4
4
|
import { Context } from "../../engine/engine_context.js";
|
|
@@ -187,50 +187,64 @@ export class Volume extends Behaviour implements IEditorModificationReceiver, IP
|
|
|
187
187
|
|
|
188
188
|
this.context.composer.setMainScene(this.context.scene);
|
|
189
189
|
|
|
190
|
-
const composer = this.context.composer;
|
|
190
|
+
const composer = this.context.composer as EffectComposer;
|
|
191
191
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (
|
|
197
|
-
|
|
192
|
+
if (this.multisampling === "auto") {
|
|
193
|
+
|
|
194
|
+
// If the postprocessing handler is using depth+normals (e.g. with SMAA) we ALWAYS disable multisampling to avoid ugly edges
|
|
195
|
+
if (this._postprocessing && (this._postprocessing.hasSmaaEffect)) {
|
|
196
|
+
if (composer.multisampling !== 0) {
|
|
197
|
+
composer.multisampling = 0;
|
|
198
|
+
if (debug || isDevEnvironment()) {
|
|
199
|
+
console.warn(`[PostProcessing] Disabling multisampling you're using SMAA and have set the 'multisampling: auto' on your PostprocessingManager/Volume component. If you need anti-aliasing, consider adding an Antialiasing component or SMAA effect to the PostprocessingManager.`);
|
|
200
|
+
}
|
|
198
201
|
}
|
|
199
202
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const timeSinceLastChange = this.context.time.realtimeSinceStartup - this._multisampleAutoChangeTime;
|
|
204
|
-
|
|
205
|
-
if (this.context.time.realtimeSinceStartup - this._componentEnabledTime > 2
|
|
206
|
-
&& timeSinceLastChange > .5
|
|
207
|
-
) {
|
|
208
|
-
const prev = composer.multisampling;
|
|
203
|
+
else {
|
|
204
|
+
const timeSinceLastChange = this.context.time.realtimeSinceStartup - this._multisampleAutoChangeTime;
|
|
209
205
|
|
|
210
|
-
if (
|
|
211
|
-
|
|
212
|
-
this._multisampleAutoDecreaseTime = this.context.time.realtimeSinceStartup;
|
|
213
|
-
composer.multisampling *= .5;
|
|
214
|
-
composer.multisampling = Math.floor(composer.multisampling);
|
|
215
|
-
if (debug) console.debug(`[PostProcessing] Reduced multisampling from ${prev} to ${composer.multisampling}`);
|
|
216
|
-
}
|
|
217
|
-
// if performance is good for a while try increasing multisampling again
|
|
218
|
-
else if (timeSinceLastChange > 1
|
|
219
|
-
&& this.context.time.smoothedFps >= 59
|
|
220
|
-
&& composer.multisampling < this.context.renderer.capabilities.maxSamples
|
|
221
|
-
&& this.context.time.realtimeSinceStartup - this._multisampleAutoDecreaseTime > 10
|
|
206
|
+
if (this.context.time.realtimeSinceStartup - this._componentEnabledTime > 2
|
|
207
|
+
&& timeSinceLastChange > .5
|
|
222
208
|
) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
composer.multisampling
|
|
226
|
-
|
|
209
|
+
const prev = composer.multisampling;
|
|
210
|
+
|
|
211
|
+
if (composer.multisampling > 0 && this.context.time.smoothedFps <= 50) {
|
|
212
|
+
this._multisampleAutoChangeTime = this.context.time.realtimeSinceStartup;
|
|
213
|
+
this._multisampleAutoDecreaseTime = this.context.time.realtimeSinceStartup;
|
|
214
|
+
let newMultiSample = composer.multisampling * .5;
|
|
215
|
+
newMultiSample = Math.floor(newMultiSample);
|
|
216
|
+
if (newMultiSample != composer.multisampling) {
|
|
217
|
+
composer.multisampling = newMultiSample;
|
|
218
|
+
}
|
|
219
|
+
if (debug) console.debug(`[PostProcessing] Reduced multisampling from ${prev} to ${composer.multisampling}`);
|
|
220
|
+
}
|
|
221
|
+
// if performance is good for a while try increasing multisampling again
|
|
222
|
+
else if (timeSinceLastChange > 1
|
|
223
|
+
&& this.context.time.smoothedFps >= 59
|
|
224
|
+
&& composer.multisampling < this.context.renderer.capabilities.maxSamples
|
|
225
|
+
&& this.context.time.realtimeSinceStartup - this._multisampleAutoDecreaseTime > 10
|
|
226
|
+
) {
|
|
227
|
+
this._multisampleAutoChangeTime = this.context.time.realtimeSinceStartup;
|
|
228
|
+
let newMultiSample = composer.multisampling <= 0 ? 1 : composer.multisampling * 2;
|
|
229
|
+
newMultiSample = Math.floor(newMultiSample);
|
|
230
|
+
if (newMultiSample !== composer.multisampling) {
|
|
231
|
+
composer.multisampling = newMultiSample;
|
|
232
|
+
}
|
|
233
|
+
if (debug) console.debug(`[PostProcessing] Increased multisampling from ${prev} to ${composer.multisampling}`);
|
|
234
|
+
}
|
|
227
235
|
}
|
|
228
236
|
}
|
|
229
237
|
}
|
|
230
238
|
else {
|
|
231
|
-
|
|
239
|
+
const newMultiSample = Math.max(0, Math.min(this.multisampling, this.context.renderer.capabilities.maxSamples));
|
|
240
|
+
if (newMultiSample !== composer.multisampling)
|
|
241
|
+
composer.multisampling = newMultiSample;
|
|
232
242
|
}
|
|
233
243
|
|
|
244
|
+
// Fix multisampling for the composer, it ONLY needs to be done for the input buffer
|
|
245
|
+
// this is super important for performance a negative visual impact
|
|
246
|
+
composer.outputBuffer.samples = 0;
|
|
247
|
+
|
|
234
248
|
// only set the main camera if any pass has a different camera
|
|
235
249
|
// trying to avoid doing this regularly since it involves doing potentially unnecessary work
|
|
236
250
|
// https://github.com/pmndrs/postprocessing/blob/3d3df0576b6d49aec9e763262d5a1ff7429fd91a/src/core/EffectComposer.js#L406
|
|
@@ -257,7 +271,7 @@ export class Volume extends Behaviour implements IEditorModificationReceiver, IP
|
|
|
257
271
|
private _isDirty: boolean = false;
|
|
258
272
|
|
|
259
273
|
private apply() {
|
|
260
|
-
if (debug) console.log(`Apply PostProcessing "${this.name}"`);
|
|
274
|
+
if (debug) console.log(`Apply PostProcessing "${this.name || "unnamed"}"`);
|
|
261
275
|
|
|
262
276
|
if (isDevEnvironment()) {
|
|
263
277
|
if (this._lastApplyTime !== undefined && Date.now() - this._lastApplyTime < 100) {
|
|
@@ -269,7 +283,6 @@ export class Volume extends Behaviour implements IEditorModificationReceiver, IP
|
|
|
269
283
|
}
|
|
270
284
|
|
|
271
285
|
this._isDirty = false;
|
|
272
|
-
this.unapply();
|
|
273
286
|
|
|
274
287
|
this._activeEffects.length = 0;
|
|
275
288
|
// get from profile
|
|
@@ -312,16 +325,13 @@ export class Volume extends Behaviour implements IEditorModificationReceiver, IP
|
|
|
312
325
|
console.warn(`[PostProcessing] No composer found`);
|
|
313
326
|
}
|
|
314
327
|
})
|
|
315
|
-
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
this._postprocessing?.unapply(false);
|
|
316
331
|
}
|
|
317
332
|
|
|
318
333
|
}
|
|
319
334
|
|
|
320
|
-
private unapply() {
|
|
321
|
-
this._postprocessing?.unapply();
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
|
|
325
335
|
private _applyPostQueue() {
|
|
326
336
|
if (this._modificationQueue) {
|
|
327
337
|
for (const entry of this._modificationQueue.values()) this.onEditorModification(entry);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from "./PostProcessingEffect.js";
|
|
2
2
|
export * from "./PostProcessingHandler.js"
|
|
3
|
+
export { PostProcessingEffectPriority } from "./utils.js";
|
|
3
4
|
export { PostProcessingManager } from "./Volume.js"
|
|
4
5
|
export * from "./VolumeParameter.js"
|
|
5
|
-
export * from "./VolumeProfile.js";
|
|
6
|
+
export * from "./VolumeProfile.js";
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import type { Effect, Pass } from "postprocessing";
|
|
1
2
|
import { Object3D } from "three";
|
|
2
3
|
|
|
3
4
|
import { isDevEnvironment } from "../../engine/debug/index.js";
|
|
4
5
|
import { addComponent } from "../../engine/engine_components.js";
|
|
5
6
|
import { foreachComponentEnumerator } from "../../engine/engine_gameobject.js";
|
|
6
|
-
import {
|
|
7
|
+
import { MODULES } from "../../engine/engine_modules.js";
|
|
8
|
+
import { Constructor, ConstructorConcrete, IComponent } from "../../engine/engine_types.js";
|
|
7
9
|
import { getParam } from "../../engine/engine_utils.js";
|
|
8
10
|
import { type PostProcessingEffect } from "./PostProcessingEffect.js";
|
|
9
11
|
|
|
@@ -52,4 +54,121 @@ export function getPostProcessingManager(effect: PostProcessingEffect): IPostPro
|
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
return manager;
|
|
55
|
-
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
export type PostprocessingEffectData = {
|
|
62
|
+
effect: Effect | Pass;
|
|
63
|
+
priority?: number,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Default priority for post-processing effects. This can be used to sort effects by their rendering order when creating custom effects.
|
|
68
|
+
* E.g. in your custom effect, you can set `priority: PostProcessingEffectPriority.Bloom + 1;` to ensure it gets rendered after the bloom effect.
|
|
69
|
+
* OR `priority: PostProcessingEffectPriority.Bloom - 1;` to ensure it gets rendered before the bloom effect.
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* import { PostProcessingEffectPriority } from "@needle-tools/engine"
|
|
73
|
+
*
|
|
74
|
+
* export class MyCustomEffect extends PostProcessingEffect {
|
|
75
|
+
* priority: PostProcessingEffectPriority.Bloom + 1; // render after bloom
|
|
76
|
+
*
|
|
77
|
+
* // ... your effect code
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export const PostProcessingEffectPriority = {
|
|
82
|
+
/** Used to render effects at the start of the post-processing chain */
|
|
83
|
+
AT_START: -10_000,
|
|
84
|
+
|
|
85
|
+
NormalPass: 0,
|
|
86
|
+
DepthDownsamplingPass: 10,
|
|
87
|
+
SMAA: 20,
|
|
88
|
+
SSAO: 30,
|
|
89
|
+
TiltShift: 40,
|
|
90
|
+
DepthOfField: 50,
|
|
91
|
+
ChromaticAberration: 60,
|
|
92
|
+
Bloom: 70,
|
|
93
|
+
Vignette: 80,
|
|
94
|
+
Pixelation: 90,
|
|
95
|
+
ToneMapping: 100,
|
|
96
|
+
HueSaturation: 110,
|
|
97
|
+
BrightnessContrast: 120,
|
|
98
|
+
|
|
99
|
+
/** Used to render effects at the end of the post-processing chain, e.g. for final adjustments or overlays. */
|
|
100
|
+
AT_END: 10_000,
|
|
101
|
+
}
|
|
102
|
+
// let effectsOrder: Array<Constructor<Effect | Pass>> | null = null;
|
|
103
|
+
|
|
104
|
+
let builtinOrder: Map<Constructor<Effect | Pass>, number> | null = null;
|
|
105
|
+
|
|
106
|
+
export function orderEffects(effects: Array<PostprocessingEffectData>) {
|
|
107
|
+
if (debug === "verbose") console.debug("Before ordering effects", [...effects]);
|
|
108
|
+
|
|
109
|
+
if (!builtinOrder) {
|
|
110
|
+
builtinOrder = new Map<Constructor<Effect | Pass>, number>();
|
|
111
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.NormalPass, PostProcessingEffectPriority.NormalPass);
|
|
112
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.DepthDownsamplingPass, PostProcessingEffectPriority.DepthDownsamplingPass);
|
|
113
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.SMAAEffect, PostProcessingEffectPriority.SMAA);
|
|
114
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.SSAOEffect, PostProcessingEffectPriority.SSAO);
|
|
115
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.TiltShiftEffect, PostProcessingEffectPriority.TiltShift);
|
|
116
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.DepthOfFieldEffect, PostProcessingEffectPriority.DepthOfField);
|
|
117
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.ChromaticAberrationEffect, PostProcessingEffectPriority.ChromaticAberration);
|
|
118
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.BloomEffect, PostProcessingEffectPriority.Bloom);
|
|
119
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.VignetteEffect, PostProcessingEffectPriority.Vignette);
|
|
120
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.PixelationEffect, PostProcessingEffectPriority.Pixelation);
|
|
121
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.ToneMappingEffect, PostProcessingEffectPriority.ToneMapping);
|
|
122
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.HueSaturationEffect, PostProcessingEffectPriority.HueSaturation);
|
|
123
|
+
builtinOrder.set(MODULES.POSTPROCESSING.MODULE.BrightnessContrastEffect, PostProcessingEffectPriority.BrightnessContrast);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// enforce correct order of effects (e.g. DOF before Bloom)
|
|
127
|
+
effects.sort((a, b) => {
|
|
128
|
+
// we use find index here because sometimes constructor names are prefixed with `_`
|
|
129
|
+
// TODO: find a more robust solution that isnt name based (not sure if that exists tho... maybe we must give effect TYPES some priority/index)
|
|
130
|
+
const aidx = typeof a.priority === "number" ? a.priority : builtinOrder!.get(a.effect.constructor as Constructor<Effect | Pass>) || -1;
|
|
131
|
+
const bidx = typeof b.priority === "number" ? b.priority : builtinOrder!.get(b.effect.constructor as Constructor<Effect | Pass>) || -1;
|
|
132
|
+
|
|
133
|
+
// Unknown effects should be rendered first
|
|
134
|
+
if (aidx < 0) {
|
|
135
|
+
if (debug) console.warn("Unknown effect found: ", a.constructor.name);
|
|
136
|
+
return -1;
|
|
137
|
+
}
|
|
138
|
+
else if (bidx < 0) {
|
|
139
|
+
if (debug) console.warn("Unknown effect found: ", b.constructor.name);
|
|
140
|
+
return 1;
|
|
141
|
+
}
|
|
142
|
+
// if (aidx < 0) return 1;
|
|
143
|
+
// if (bidx < 0) return -1;
|
|
144
|
+
return aidx - bidx;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// effects.sort((a, b) => {
|
|
148
|
+
// if (a.beforeEffect) {
|
|
149
|
+
// const beforeA = effectsOrder!.findIndex(e => a.beforeEffect!.constructor.name.endsWith(e.name));
|
|
150
|
+
// if (beforeA >= 0) {
|
|
151
|
+
// return -1; // before effect should be rendered first
|
|
152
|
+
// }
|
|
153
|
+
// else {
|
|
154
|
+
// return 1; // no before effect, so we can keep the order
|
|
155
|
+
// }
|
|
156
|
+
// }
|
|
157
|
+
// else if (b.beforeEffect) {
|
|
158
|
+
// const beforeB = effectsOrder!.findIndex(e => b.beforeEffect!.constructor.name.endsWith(e.name));
|
|
159
|
+
// if (beforeB >= 0) {
|
|
160
|
+
// return 1; // before effect should be rendered first
|
|
161
|
+
// }
|
|
162
|
+
// else if (a.beforeEffect) {
|
|
163
|
+
// return -1; // no before effect, so we can keep the order
|
|
164
|
+
// }
|
|
165
|
+
|
|
166
|
+
// }
|
|
167
|
+
// return 0; // no before effect, so we can keep the order
|
|
168
|
+
// });
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
if (debug === "verbose") console.debug("After ordering effects", [...effects]);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|