@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
104 lines (103 loc) • 4.14 kB
JavaScript
;
import { BaseSopOperation } from "./_Base";
import { InputCloneMode } from "../../../engine/poly/InputCloneMode";
import { isBooleanTrue } from "../../../core/BooleanValue";
import {
DEFAULT_SPOT_LIGHT_PARAMS,
SpotLightContainer
} from "../../../core/lights/SpotLight";
import { LightUserDataRaymarching } from "../../../core/lights/Common";
import { NodeContext } from "../../poly/NodeContext";
export class SpotLightSopOperation extends BaseSopOperation {
static type() {
return "spotLight";
}
async cook(inputCoreGroups, params) {
const container = this.createLight(params);
container.light().name = params.name;
await this.updateLightParams(container, params);
this.updateShadowParams(container, params);
container.updateParams(params);
container.updateHelper();
container.updateVolumetric();
return this.createCoreGroupFromObjects([container]);
}
createLight(params) {
var _a;
const container = new SpotLightContainer(params, ((_a = this._node) == null ? void 0 : _a.name()) || "_");
const light = container.light();
light.matrixAutoUpdate = false;
light.castShadow = true;
light.shadow.bias = -1e-3;
light.shadow.mapSize.x = 1024;
light.shadow.mapSize.y = 1024;
light.shadow.camera.near = 0.1;
return container;
}
async updateLightParams(container, params) {
const light = container.light();
light.color = params.color;
light.intensity = params.intensity;
light.angle = params.angle * (Math.PI / 180);
light.penumbra = params.penumbra;
light.decay = params.decay;
light.distance = params.distance;
light.userData[LightUserDataRaymarching.PENUMBRA] = params.raymarchingPenumbra;
light.userData[LightUserDataRaymarching.SHADOW_BIAS_ANGLE] = params.raymarchingShadowBiasAngle;
light.userData[LightUserDataRaymarching.SHADOW_BIAS_DISTANCE] = params.raymarchingShadowBiasDistance;
await this._updateLightMap(light, params);
}
async _updateLightMap(light, params) {
var _a, _b, _c;
if (!params.tmap) {
light.map = null;
return;
}
const textureNode = params.map.nodeWithContext(NodeContext.COP, (_a = this.states) == null ? void 0 : _a.error);
if (textureNode) {
const container = await textureNode.compute();
const texture = container.coreContent();
if (!texture) {
(_b = this.states) == null ? void 0 : _b.error.set(`texture invalid. (error: '${textureNode.states.error.message()}')`);
}
light.map = texture || null;
} else {
(_c = this.states) == null ? void 0 : _c.error.set(`no texture node found`);
}
}
updateShadowParams(container, params) {
const light = container.light();
light.castShadow = isBooleanTrue(params.castShadow);
light.shadow.autoUpdate = isBooleanTrue(params.shadowAutoUpdate);
light.shadow.needsUpdate = isBooleanTrue(params.shadowUpdateOnNextRender);
light.shadow.mapSize.copy(params.shadowRes);
const map = light.shadow.map;
if (map) {
map.setSize(params.shadowRes.x, params.shadowRes.y);
}
light.shadow.bias = params.shadowBias;
light.shadow.radius = params.shadowRadius;
light.shadow.camera.near = params.shadowNear;
light.shadow.camera.far = params.shadowFar;
light.shadow.camera.updateProjectionMatrix();
container.updateHelper();
}
// private __debugShadowMesh: Mesh<PlaneGeometry, MeshBasicMaterial> | undefined;
// private _debugShadowMesh(light: SpotLight) {
// return (this.__debugShadowMesh = this.__debugShadowMesh || this._createDebugShadowMesh(light));
// }
// private _createDebugShadowMesh(light: SpotLight) {
// const material = new MeshBasicMaterial({
// color: new Color(1, 1, 1),
// map: light.shadow.map.texture,
// side: DoubleSide,
// });
// const mesh = new Mesh(new PlaneGeometry(5, 5, 2, 2), material);
// mesh.position.z = 1;
// mesh.castShadow = false;
// mesh.receiveShadow = false;
// return mesh;
// }
}
SpotLightSopOperation.DEFAULT_PARAMS = DEFAULT_SPOT_LIGHT_PARAMS;
SpotLightSopOperation.INPUT_CLONED_STATE = InputCloneMode.NEVER;