UNPKG

@polygonjs/polygonjs

Version:

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

161 lines (160 loc) 5.62 kB
"use strict"; import { TypedCopNode } from "./_Base"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { WebGLRenderer } from "three"; import { Light } from "three"; import { LightMapController } from "./utils/LightMapController"; import { Mesh } from "three"; import { isBooleanTrue } from "../../../core/BooleanValue"; import { DataTextureController, DataTextureControllerBufferType } from "./utils/DataTextureController"; import { CopRendererController } from "./utils/RendererController"; import { CopType } from "../../poly/registers/nodes/types/Cop"; class LightMapCopParamConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param click to update shadow, when mode is manual */ this.update = ParamConfig.BUTTON(null, { callback: (node) => { LightMapCopNode.PARAM_CALLBACK_updateManual(node); } }); /** @param defines if the shader is rendered via the same camera used to render the scene */ this.useCameraRenderer = ParamConfig.BOOLEAN(1); // needs to be 1, as it does not work on firefox otherwise /** @param shadow resolution */ this.lightMapRes = ParamConfig.INTEGER(1024, { range: [1, 2048], rangeLocked: [true, false] }); /** @param iterations */ this.iterations = ParamConfig.INTEGER(512, { range: [1, 2048], rangeLocked: [true, false] }); /** @param blendWindow */ // iterationBlend = ParamConfig.FLOAT(DEFAULT_ITERATION_BLEND, { // range: [0, 1], // rangeLocked: [true, true], // }); /** @param blurEdges */ this.blur = ParamConfig.BOOLEAN(1); /** @param blurAmount */ this.blurAmount = ParamConfig.FLOAT(1, { visibleIf: { blur: 1 }, range: [0, 1], rangeLocked: [true, false] }); /** @param lightPositionVariation */ this.lightRadius = ParamConfig.FLOAT(1, { range: [0, 10] }); this.objectsMask = ParamConfig.STRING("", { objectMask: true }); this.lightsMask = ParamConfig.STRING("*", { objectMask: true }); } } const ParamsConfig = new LightMapCopParamConfig(); export class LightMapCopNode extends TypedCopNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this._includedObjects = []; this._includedLights = []; } static type() { return CopType.LIGHT_MAP; } async cook() { await this._render(); } async _createLightMapController() { const renderer = await this.scene().renderersRegister.waitForRenderer(); if (!renderer) { console.warn("no renderer found"); return; } if (!(renderer instanceof WebGLRenderer)) { this.states.error.set("renderer found is not WebGLRenderer"); return; } const lightMapController = new LightMapController(renderer); return lightMapController; } // // // ACTIVE // // // static PARAM_CALLBACK_update_updateMode(node: LightMapCopNode) { // // node._updateRenderHook(); // } // // // UPDATE // // async _render() { this.lightMapController = this.lightMapController || await this._createLightMapController(); if (!this.lightMapController) { return; } const mainCamera = await this.scene().mainCamera(); if (!mainCamera) { return; } this._updateObjectsAndLightsList(); this.lightMapController.setState(this._includedObjects, this._includedLights); this.lightMapController.setParams({ resolution: this.pv.lightMapRes, lightRadius: this.pv.lightRadius, totalIterationsCount: this.pv.iterations, // iterationBlend: this.pv.iterationBlend, blur: this.pv.blur, blurAmount: this.pv.blurAmount }); this.lightMapController.runUpdates(mainCamera); this.lightMapController.restoreState(); const renderTarget = this.lightMapController.textureRenderTarget(); if (isBooleanTrue(this.pv.useCameraRenderer)) { this.setTexture(renderTarget.texture); } else { this._dataTextureController = this._dataTextureController || new DataTextureController(DataTextureControllerBufferType.Float32Array); this._rendererController = this._rendererController || new CopRendererController(this); const renderer = await this._rendererController.waitForRenderer(); if (!(renderer instanceof WebGLRenderer)) { this.states.error.set("renderer found is not WebGLRenderer"); this.cookController.endCook(); return; } const texture = this._dataTextureController.fromRenderTarget(renderer, renderTarget); this.setTexture(texture); } } static PARAM_CALLBACK_updateManual(node) { node.setDirty(); } // // // UPDATE OBJECTS LIST // // _updateObjectsAndLightsList() { let matchedObjects = []; let matchedLights = []; this._includedLights = []; this._includedObjects = []; const lightsByUuid = /* @__PURE__ */ new WeakSet(); if (this.pv.lightsMask != "") { matchedLights = this.scene().objectsByMask(this.pv.lightsMask); for (const matchedLight of matchedLights) { if (matchedLight instanceof Light) { this._includedLights.push(matchedLight); lightsByUuid.add(matchedLight); } } } if (this.pv.objectsMask != "") { matchedObjects = this.scene().objectsByMask(this.pv.objectsMask); for (const matchedObject of matchedObjects) { if (!(matchedObject instanceof Light)) { if (!lightsByUuid.has(matchedObject) && matchedObject instanceof Mesh) { this._includedObjects.push(matchedObject); } } } } } }