UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

169 lines 7.22 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { serializable } from "../../engine/engine_serialization.js"; import { getParam } from "../../engine/engine_utils.js"; import { Component } from "../Component.js"; import { getPostProcessingManager } from "./utils.js"; import { VolumeParameter } from "./VolumeParameter.js"; const debug = getParam("debugpost"); /** * PostProcessingEffect is a base class for post processing effects that can be applied to the scene. * To create a custom post processing effect, extend this class and override the `onCreateEffect` method and call `registerCustomEffectType` to make it available in the editor. * @example * ```typescript * import { EdgeDetectionMode, SMAAEffect, SMAAPreset } from "postprocessing"; * export class Antialiasing extends PostProcessingEffect { * get typeName(): string { * return "Antialiasing"; * } * @serializable(VolumeParameter) * preset!: VolumeParameter = new VolumeParameter(); * onCreateEffect(): EffectProviderResult { * const effect = new SMAAEffect({ * preset: SMAAPreset.HIGH, * edgeDetectionMode: EdgeDetectionMode.DEPTH * }); * this.preset.onValueChanged = (newValue) => { * effect.applyPreset(newValue); * }; * return effect; * } * } * registerCustomEffectType("Antialiasing", Antialiasing) * ``` * * @category Effects * @group Components */ export class PostProcessingEffect extends Component { get isPostProcessingEffect() { return true; } /** * The order of this effect. The higher the order the later the effect will be applied in the post processing stack. * This can be used to control the order of effects when multiple effects are applied. * It is recommended to use the PostProcessingEffectOrder constant to order your custom effects before or after built-in effects. * @default `undefined` (no specific order set, will be applied in the order of registration) * * @example * ```typescript * import { PostProcessingEffectOrder } from "@needle-tools/engine" * * export class MyCustomEffect extends PostProcessingEffect { * order: PostProcessingEffectOrder.Bloom + 1; // render after bloom * // This will ensure that the effect is applied after the bloom effect in the post processing stack. * // ... the rest of your effect code * } * ``` */ order = undefined; constructor(params = undefined) { super(); if (params) { for (const key of Object.keys(params)) { const value = params[key]; const param = this[key]; if (param instanceof VolumeParameter) { param.initialize(value); } // allow assigning values to properties that are not VolumeParameters // this is useful when effects are created in code else if (param !== undefined) { this[key] = value; } } } } /** * Whether the effect is active or not. Prefer using `enabled` instead. * @deprecated */ active = true; _manager = null; onEnable() { super.onEnable(); if (debug) console.warn("Enable", this.constructor.name + (!this.__internalDidAwakeAndStart ? " (awake)" : "")); // Dont override the serialized value by enabling (we could also just disable this component / map enabled to active) if (this.__internalDidAwakeAndStart) this.active = true; this.onEffectEnabled(); } onDisable() { super.onDisable(); if (debug) console.warn("Disable", this.constructor.name); this._manager?.removeEffect(this); this.active = false; } onEffectEnabled(manager) { if (manager && manager.isPostProcessingManager === true) this._manager = manager; else if (!this._manager) this._manager = getPostProcessingManager(this); this._manager.addEffect(this); this._manager.dirty = true; } /** override to initialize bindings on parameters */ init() { } /** previously created effect (if any) */ _result; _postprocessingContext = null; get postprocessingContext() { return this._postprocessingContext; } /** Apply post settings. Make sure to call super.apply() if you also create an effect */ apply(ctx) { this._postprocessingContext = ctx; if (!this._result) { this.initParameters(); this._result = this.onCreateEffect?.call(this); } // TODO: calling this twice because otherwise the Postprocessing sample doesnt look correct. Need to investigate which effect is causing this (init parameters should be refactored either way https://linear.app/needle/issue/NE-5182) if (this._result) { this.initParameters(); } return this._result; } /** Reset previously set values (e.g. when adjusting settings on the renderer like Tonemapping) */ unapply() { } dispose() { if (debug) console.warn("DISPOSE", this); if (this._result) { if (Array.isArray(this._result)) { this._result.forEach(r => r.dispose()); } else { this._result.dispose(); } } this._result = undefined; } initParameters() { // Automatically call init on all VolumeParameter properties // This will enforce the valueProcessor and onValueChanged to be called const keys = Object.keys(this); for (const key of keys) { const value = this[key]; if (value instanceof VolumeParameter) { value.__init(); } } } // TODO this is currently not used for post processing effects that are part of Volume stacks, // since these handle that already. onEditorModification(modification) { // Handle a property modification if the property is a VolumeParameter and the modification is just a plain value const key = modification.propertyName; if (this[key] instanceof VolumeParameter) { const value = modification.value; this[key].value = value; return true; } } } __decorate([ serializable() ], PostProcessingEffect.prototype, "active", void 0); //# sourceMappingURL=PostProcessingEffect.js.map