UNPKG

polygonjs-engine

Version:

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

153 lines (138 loc) 5.28 kB
import {Constructor, valueof} from '../../../../types/GlobalTypes'; import {WebGLRenderer} from 'three/src/renderers/WebGLRenderer'; import {WebGLRenderTarget, WebGLRenderTargetOptions} from 'three/src/renderers/WebGLRenderTarget'; import {EffectComposer} from '../../../../modules/three/examples/jsm/postprocessing/EffectComposer'; import {RenderPass} from '../../../../modules/three/examples/jsm/postprocessing/RenderPass'; import {DisplayNodeController, DisplayNodeControllerCallbacks} from '../../utils/DisplayNodeController'; import {PostNodeChildrenMap} from '../../../poly/registers/nodes/Post'; import {TypedNode, BaseNodeType} from '../../_Base'; import {BasePostProcessNodeType} from '../_Base'; import {Scene} from 'three/src/scenes/Scene'; import {Camera} from 'three/src/cameras/Camera'; import {Vector2} from 'three/src/math/Vector2'; import {BaseCameraObjNodeType} from '../../obj/_BaseCamera'; import {NodeParamsConfig, ParamConfig} from '../../utils/params/ParamsConfig'; import {RGBFormat} from 'three/src/constants'; import {Poly} from '../../../Poly'; import { MAG_FILTER_DEFAULT_VALUE, MAG_FILTER_MENU_ENTRIES, MIN_FILTER_DEFAULT_VALUE, MIN_FILTER_MENU_ENTRIES, } from '../../../../core/cop/ConstantFilter'; export class PostProcessNetworkParamsConfig extends NodeParamsConfig { prepend_render_pass = ParamConfig.BOOLEAN(1); useRenderTarget = ParamConfig.BOOLEAN(1); tmagFilter = ParamConfig.BOOLEAN(0, { visibleIf: {useRenderTarget: 1}, }); magFilter = ParamConfig.INTEGER(MAG_FILTER_DEFAULT_VALUE, { visibleIf: {useRenderTarget: 1, tmagFilter: 1}, menu: { entries: MAG_FILTER_MENU_ENTRIES, }, }); tminFilter = ParamConfig.BOOLEAN(0, { visibleIf: {useRenderTarget: 1}, }); minFilter = ParamConfig.INTEGER(MIN_FILTER_DEFAULT_VALUE, { visibleIf: {useRenderTarget: 1, tminFilter: 1}, menu: { entries: MIN_FILTER_MENU_ENTRIES, }, }); stencilBuffer = ParamConfig.BOOLEAN(0, { visibleIf: {useRenderTarget: 1}, }); sampling = ParamConfig.INTEGER(1, { range: [1, 4], rangeLocked: [true, false], }); } export interface BaseNetworkPostProcessNodeType extends TypedNode<any, PostProcessNetworkParamsConfig> { readonly display_node_controller: DisplayNodeController; createNode<S extends keyof PostNodeChildrenMap>(node_class: S): PostNodeChildrenMap[S]; createNode<K extends valueof<PostNodeChildrenMap>>(node_class: Constructor<K>): K; children(): BasePostProcessNodeType[]; nodesByType<K extends keyof PostNodeChildrenMap>(type: K): PostNodeChildrenMap[K][]; readonly effects_composer_controller: EffectsComposerController; } interface CreateEffectsComposerOptions { renderer: WebGLRenderer; scene: Scene; camera: Camera; resolution: Vector2; // render_target?: WebGLRenderTarget; requester: BaseNodeType; camera_node?: BaseCameraObjNodeType; // useRenderTarget?: boolean; // prepend_render_pass?: boolean; } export class EffectsComposerController { constructor(private node: BaseNetworkPostProcessNodeType) {} display_node_controller_callbacks(): DisplayNodeControllerCallbacks { return { on_display_node_remove: () => {}, on_display_node_set: () => { this.node.setDirty(); }, on_display_node_update: () => { this.node.setDirty(); }, }; } create_effects_composer(options: CreateEffectsComposerOptions) { const renderer = options.renderer; let composer: EffectComposer; if (this.node.pv.useRenderTarget) { const render_target = this._create_render_target(renderer); composer = new EffectComposer(renderer, render_target); } else { composer = new EffectComposer(renderer); } // to achieve better antialiasing // while using post: composer.setPixelRatio(window.devicePixelRatio * this.node.pv.sampling); // be careful, as this messes up with the renderer // and when using in cop/post has the output texture be 2x as large // composer.setPixelRatio(window.devicePixelRatio * 1); this._build_passes(composer, options); return composer; } private _renderer_size = new Vector2(); private _create_render_target(renderer: WebGLRenderer) { let render_target: WebGLRenderTarget | undefined; renderer.autoClear = false; const parameters: WebGLRenderTargetOptions = { // format: RGBFormat, format: RGBFormat, stencilBuffer: this.node.pv.stencilBuffer, }; if (this.node.pv.tminfilter) { parameters.minFilter = this.node.pv.minFilter; } if (this.node.pv.tminfilter) { parameters.magFilter = this.node.pv.magFilter; } renderer.getDrawingBufferSize(this._renderer_size); render_target = Poly.renderersController.renderTarget(this._renderer_size.x, this._renderer_size.y, parameters); return render_target; } private _build_passes(composer: EffectComposer, options: CreateEffectsComposerOptions) { if (this.node.pv.prepend_render_pass == true) { const render_pass = new RenderPass(options.scene, options.camera); composer.addPass(render_pass); } const post_node = this.node.display_node_controller.display_node as BasePostProcessNodeType; if (post_node) { post_node.setup_composer({ composer: composer, camera: options.camera, resolution: options.resolution, camera_node: options.camera_node, scene: options.scene, requester: options.requester, }); } } }