UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

144 lines (129 loc) 4.79 kB
import {Camera, Scene, WebGLRenderer} from 'three'; import {TypedNode, BaseNodeType} from '../_Base'; import {EffectComposer, Pass} from 'postprocessing'; import {NodeContext} from '../../poly/NodeContext'; import {NodeParamsConfig} from '../utils/params/ParamsConfig'; import {FlagsControllerDB} from '../utils/FlagsController'; import {BaseParamType} from '../../params/_Base'; import {ParamOptions} from '../../params/utils/OptionsController'; import {BaseNetworkPostProcessNodeType, EffectComposerController} from './utils/EffectComposerController'; import {CoreCameraPostProcessController} from '../../../core/camera/CoreCameraPostProcessController'; import {isArray} from '../../../core/Type'; import {BaseViewerType} from '../../viewers/_Base'; export interface TypedPostNodeContext { composerController: EffectComposerController; composer: EffectComposer; camera: Camera; renderer: WebGLRenderer; // resolution: Vector2; scene: Scene; // requester: BaseNodeType; viewer: BaseViewerType; } function PostParamCallback(node: BaseNodeType, param: BaseParamType) { TypedPostNode.PARAM_CALLBACK_updatePasses(node as BasePostProcessNodeType); } export const PostParamOptions: ParamOptions = { cook: false, callback: PostParamCallback, computeOnDirty: true, // important if an expression drives a param }; /** * * * TypedPostNode is the base class for all nodes that create post-processing passes. This inherits from [TypedNode](/docs/api/TypedNode). * */ export class TypedPostNode<P extends Pass, K extends NodeParamsConfig> extends TypedNode<NodeContext.POST, K> { static override context(): NodeContext { return NodeContext.POST; } public override readonly flags: FlagsControllerDB = new FlagsControllerDB(this); protected _passesByEffectsComposer: Map<EffectComposer, P | P[]> = new Map(); override initializeNode() { this.flags.display.set(false); this.flags.display.onUpdate(() => { if (!this.flags.display.active()) { return; } const parent = this.parent(); if (!(parent && parent.displayNodeController)) { return; } parent.displayNodeController.setDisplayNode(this); }); this.io.inputs.setCount(0, 1); this.io.outputs.setHasOneOutput(); } override cook() { this.cookController.endCook(); } setupComposer(context: TypedPostNodeContext) { this._addPassFromInput(0, context); if (!this.flags.bypass.active()) { this._setupComposerIfActive(context); } } protected _setupComposerIfActive(context: TypedPostNodeContext) { const pass = this.createPassForContext(context); if (pass) { const array = isArray(pass) ? pass : [pass]; for (const p of array) { context.composerController.addPassByNodeInBuildPassesProcess(this, p, context.composer); } } } passesByComposer(composer: EffectComposer) { return this._passesByEffectsComposer.get(composer); } protected _addPassFromInput(index: number, context: TypedPostNodeContext) { const input = this.io.inputs.input(index); if (input) { input.setupComposer(context); } } createPassForContext(context: TypedPostNodeContext) { let pass = this._passesByEffectsComposer.get(context.composer); if (!pass) { pass = this.createPass(context); if (pass) { this._passesByEffectsComposer.set(context.composer, pass); } } return pass; } createPass(context: TypedPostNodeContext): P | P[] | undefined { return undefined; } static PARAM_CALLBACK_updatePasses(node: BasePostProcessNodeType) { node._updatePasses(); } protected _updatePasses() { this._passesByEffectsComposer.forEach((passOrPasses) => { const passes = isArray(passOrPasses) ? passOrPasses : [passOrPasses]; for (const pass of passes) { this.updatePass(pass); } }); } protected updatePass(pass: P) {} protected _postProcessNetworkNode(): BaseNetworkPostProcessNodeType { const parentNode = this.parent()!; if (CoreCameraPostProcessController.isPostProcessNetworkNode(parentNode)) { return parentNode as BaseNetworkPostProcessNodeType; } else { console.error('parent is neither a POST NETWORK or a POST node', parentNode); const parentPostNode = parentNode as BasePostProcessNodeType; return parentPostNode._postProcessNetworkNode(); } } // protected _createRenderTarget(renderer: WebGLRenderer, options?: RenderTargetCreateOptions) { // const parentNode = this._postProcessNetworkNode(); // return parentNode.effectsComposerController.createRenderTarget(renderer); // } // protected _createEffectComposer(renderer: WebGLRenderer, renderTarget?: WebGLRenderTarget) { // return new EffectComposer(renderer, renderTarget); // } } export type BasePostProcessNodeType = TypedPostNode<Pass, NodeParamsConfig>; export class BasePostProcessNodeClass extends TypedPostNode<Pass, NodeParamsConfig> {}