@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
161 lines (160 loc) • 5.62 kB
JavaScript
"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);
}
}
}
}
}
}