@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
144 lines (129 loc) • 4.79 kB
text/typescript
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> {}