@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
166 lines (165 loc) • 5.09 kB
JavaScript
"use strict";
import { TypedCopNode } from "./_Base";
import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig";
import { CubeReflectionMapping, CubeRefractionMapping } from "three";
import { CopType } from "../../poly/registers/nodes/types/Cop";
import { isBooleanTrue } from "../../../core/Type";
import { CopRendererController } from "./utils/RendererController";
var MapMode = /* @__PURE__ */ ((MapMode2) => {
MapMode2["REFLECTION"] = "reflection";
MapMode2["REFRACTION"] = "refraction";
return MapMode2;
})(MapMode || {});
const MAP_MODES = ["reflection" /* REFLECTION */, "refraction" /* REFRACTION */];
class CubeCameraCopParamsConfig extends NodeParamsConfig {
constructor() {
super(...arguments);
/** @param cube camera OBJ node */
this.cameraPath = ParamConfig.STRING("*cubeCamera*", {
objectMask: true
});
/** @param objects to render */
// objects = ParamConfig.STRING('/', {
// objectMask: true,
// });
/** @param defines if the texture is used for reflection or refraction */
this.mode = ParamConfig.INTEGER(0, {
menu: {
entries: MAP_MODES.map((name, value) => {
return { name, value };
})
}
});
/** @param transparent background */
this.transparentBackground = ParamConfig.BOOLEAN(1);
/** @param bg Color */
this.backgroundColor = ParamConfig.COLOR([0, 0, 0], {
visibleIf: {
transparentBackground: 0
}
});
/** @param autoRender */
this.autoRender = ParamConfig.BOOLEAN(1);
/** @param render button */
this.render = ParamConfig.BUTTON(null, {
callback: (node) => {
CubeCameraCopNode.PARAM_CALLBACK_render(node);
}
});
}
}
const ParamsConfig = new CubeCameraCopParamsConfig();
export class CubeCameraCopNode extends TypedCopNode {
constructor() {
super(...arguments);
this.paramsConfig = ParamsConfig;
// private previousParentByObject: WeakMap<Object3D, Object3D | null> = new WeakMap();
this._renderOnTargetBound = () => this.renderOnTarget(true);
}
static type() {
return CopType.CUBE_CAMERA;
}
async cook() {
if (isBooleanTrue(this.pv.autoRender)) {
this._addOnBeforeTickCallback();
} else {
this._removeOnBeforeTickCallback();
}
const texture = await this.renderOnTarget(false);
if (texture) {
const mode = MAP_MODES[this.pv.mode];
switch (mode) {
case "reflection" /* REFLECTION */:
texture.mapping = CubeReflectionMapping;
break;
case "refraction" /* REFRACTION */:
texture.mapping = CubeRefractionMapping;
break;
}
} else {
this.cookController.endCook();
}
}
//
//
// AUTO RENDER
//
//
_addOnBeforeTickCallback() {
const callbackName = this._onBeforeRenderCallbackName();
if (this.scene().hasBeforeTickCallback(callbackName)) {
return;
}
this.scene().registerOnBeforeTick(callbackName, this._renderOnTargetBound);
}
_removeOnBeforeTickCallback() {
this.scene().unRegisterOnBeforeTick(this._onBeforeRenderCallbackName());
}
_onBeforeRenderCallbackName() {
return `cop/render_onBeforeTickCallback-${this.graphNodeId()}`;
}
dispose() {
super.dispose();
this._removeOnBeforeTickCallback();
}
//
//
// RENDER + RENDER TARGET
//
//
_getCameraSync() {
return this.scene().objectsController.findObjectByMask(this.pv.cameraPath);
}
async _getCamera() {
const camera = this._getCameraSync();
if (camera) {
return camera;
}
return new Promise((resolve) => {
this.scene().camerasController.onCameraObjectsUpdated(async () => {
const camera2 = this._getCameraSync();
if (camera2) {
resolve(camera2);
}
});
});
}
async renderOnTarget(setDirtyIfChangesDetected) {
const camera = await this._getCamera();
if (!camera) {
console.warn(`${this.path()}: no camera found`);
return;
}
this._rendererController = this._rendererController || new CopRendererController(this);
const renderer = await this._rendererController.waitForRenderer();
if (!renderer) {
return;
}
if (setDirtyIfChangesDetected == true && this._prevCamera != camera || renderer != this._prevRenderer) {
this.setDirty();
this._prevCamera = camera;
this._prevRenderer = renderer;
}
const scene = this.scene().threejsScene();
const prevBackground = scene.background;
scene.background = this.pv.transparentBackground ? null : this.pv.backgroundColor;
camera.update(renderer, scene);
scene.background = prevBackground;
const texture = camera.renderTarget.texture;
this.setTexture(texture);
return texture;
}
// private _renderTarget: WebGLRenderTarget | undefined;
async renderTarget() {
const camera = await this._getCamera();
return camera == null ? void 0 : camera.renderTarget.texture;
}
//
//
// CALLBACK
//
//
static PARAM_CALLBACK_render(node) {
node.renderOnTarget(true);
}
}