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.

120 lines 6 kB
import { isDevEnvironment } from "../../engine/debug/index.js"; import { addComponent } from "../../engine/engine_components.js"; import { foreachComponentEnumerator } from "../../engine/engine_gameobject.js"; import { MODULES } from "../../engine/engine_modules.js"; import { getParam } from "../../engine/engine_utils.js"; export const debug = getParam("debugpost"); let PostprocessingManagerType = null; export function setPostprocessingManagerType(type) { PostprocessingManagerType = type; } export function findPostProcessingManager(effect) { let obj = effect.gameObject; while (obj) { for (const comp of foreachComponentEnumerator(obj)) { if (comp.isPostProcessingManager === true) { return comp; } } obj = obj.parent; } return null; } export function getPostProcessingManager(effect) { let manager = findPostProcessingManager(effect); if (!manager) { if (PostprocessingManagerType) { if (debug) console.warn("Adding postprocessing manager to the scene."); const scene = effect.scene; manager = addComponent(scene, PostprocessingManagerType); } else { if (isDevEnvironment()) console.warn("No post processing manager found"); } } return manager; } /** * Default order for post-processing effects. This can be used to sort effects by their rendering order when creating custom effects. * E.g. in your custom effect, you can set `order: PostProcessingEffectOrder.Bloom + 1;` to ensure it gets rendered after the bloom effect. * OR `order: PostProcessingEffectOrder.Bloom - 1;` to ensure it gets rendered before the bloom effect. * @example * ```typescript * import { PostProcessingEffectOrder } from "@needle-tools/engine" * * export class MyCustomEffect extends PostProcessingEffect { * order: PostProcessingEffectPriority.Bloom + 1; // render after bloom * * // ... your effect code * } * ``` */ export const PostProcessingEffectOrder = { /** Used to render effects at the start of the post-processing chain */ AT_START: -10_000, NormalPass: 0, DepthDownsamplingPass: 10, SSAO: 20, SMAA: 30, TiltShift: 40, DepthOfField: 50, ChromaticAberration: 60, Bloom: 70, Vignette: 80, Pixelation: 90, ToneMapping: 100, HueSaturation: 110, BrightnessContrast: 120, Sharpening: 130, /** Used to render effects at the end of the post-processing chain, e.g. for final adjustments or overlays. */ AT_END: 10_000, }; // let effectsOrder: Array<Constructor<Effect | Pass>> | null = null; let builtinOrder = null; export function orderEffects(effects) { if (debug === "verbose") console.debug("Before ordering effects", [...effects]); if (!builtinOrder) { builtinOrder = new Map(); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.NormalPass, PostProcessingEffectOrder.NormalPass); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.DepthDownsamplingPass, PostProcessingEffectOrder.DepthDownsamplingPass); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.SMAAEffect, PostProcessingEffectOrder.SMAA); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.SSAOEffect, PostProcessingEffectOrder.SSAO); builtinOrder.set(MODULES.POSTPROCESSING_AO.MODULE.N8AOPostPass, PostProcessingEffectOrder.SSAO); builtinOrder.set(MODULES.POSTPROCESSING_AO.MODULE.N8AOPass, PostProcessingEffectOrder.SSAO); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.TiltShiftEffect, PostProcessingEffectOrder.TiltShift); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.DepthOfFieldEffect, PostProcessingEffectOrder.DepthOfField); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.ChromaticAberrationEffect, PostProcessingEffectOrder.ChromaticAberration); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.BloomEffect, PostProcessingEffectOrder.Bloom); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.SelectiveBloomEffect, PostProcessingEffectOrder.Bloom); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.VignetteEffect, PostProcessingEffectOrder.Vignette); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.PixelationEffect, PostProcessingEffectOrder.Pixelation); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.ToneMappingEffect, PostProcessingEffectOrder.ToneMapping); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.HueSaturationEffect, PostProcessingEffectOrder.HueSaturation); builtinOrder.set(MODULES.POSTPROCESSING.MODULE.BrightnessContrastEffect, PostProcessingEffectOrder.BrightnessContrast); } // enforce correct order of effects (e.g. DOF before Bloom) effects.sort((a, b) => { // we use find index here because sometimes constructor names are prefixed with `_` // 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) const aidx = typeof a.priority === "number" ? a.priority : builtinOrder.get(a.effect.constructor) ?? Number.NEGATIVE_INFINITY; const bidx = typeof b.priority === "number" ? b.priority : builtinOrder.get(b.effect.constructor) ?? Number.NEGATIVE_INFINITY; // Unknown effects should be rendered first if (aidx === Number.NEGATIVE_INFINITY) { if (debug) console.warn("Unknown effect found: ", a.constructor.name, a); return 1; } else if (bidx === Number.NEGATIVE_INFINITY) { if (debug) console.warn("Unknown effect found: ", b.constructor.name, b); return -1; } return aidx - bidx; }); if (debug === "verbose") console.debug("After ordering effects", [...effects]); } //# sourceMappingURL=utils.js.map