UNPKG

@polygonjs/polygonjs

Version:

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

151 lines (150 loc) 4.76 kB
"use strict"; import { TypeAssert } from "./../../poly/Assert"; import { Vector2, PointLight, DirectionalLight } from "three"; import { TypedPostNode, PostParamOptions } from "./_Base"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { GodraysPass } from "./utils/GodRaysVolumetric/GodRaysPass"; const tmpPointLight = new PointLight(); const tmpDirectionalLight = new DirectionalLight(); for (const l of [tmpPointLight, tmpDirectionalLight]) { l.intensity = 1e-4; l.castShadow = true; l.shadow.mapSize.width = 1024; l.shadow.mapSize.height = 1024; l.shadow.autoUpdate = true; l.shadow.camera.near = 0.1; l.shadow.camera.far = 1e3; l.shadow.camera.updateProjectionMatrix(); } var LightType = /* @__PURE__ */ ((LightType2) => { LightType2["POINT"] = "point"; LightType2["DIRECTIONAL"] = "directional"; return LightType2; })(LightType || {}); const LIGHT_TYPES = ["directional" /* DIRECTIONAL */, "point" /* POINT */]; function _findLightSource(scene, objectMask, lightType) { let foundLigthObject = void 0; const objects = scene.objectsByMask(objectMask); function _isExpectedLightType(object) { switch (lightType) { case "point" /* POINT */: { return object.isPointLight; } case "directional" /* DIRECTIONAL */: { return object.isDirectionalLight; } } TypeAssert.unreachable(lightType); } for (const object of objects) { if (_isExpectedLightType(object)) { foundLigthObject = object; break; } } return foundLigthObject; } class GodRaysVolumetricPostParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param light type */ this.lightType = ParamConfig.INTEGER(LIGHT_TYPES.indexOf("point" /* POINT */), { menu: { entries: LIGHT_TYPES.map((name, value) => ({ name, value })) } }); /** @param light to emit godrays from. Note that while the mask can resolve multiple objects, only the first light will be used */ this.lightMask = ParamConfig.STRING("*Light*", { objectMask: true, ...PostParamOptions }); /** @param color */ this.color = ParamConfig.COLOR([1, 1, 1], { ...PostParamOptions }); /** @param density */ this.density = ParamConfig.FLOAT(6e-3, { range: [0, 1], rangeLocked: [true, true], ...PostParamOptions }); /** @param maxDensity */ this.maxDensity = ParamConfig.FLOAT(0.67, { range: [0, 1], rangeLocked: [true, true], ...PostParamOptions }); /** @param distanceAttenuation */ this.distanceAttenuation = ParamConfig.FLOAT(2, { range: [0, 10], rangeLocked: [true, false], ...PostParamOptions }); /** @param edgeStrength */ this.edgeStrength = ParamConfig.INTEGER(2, { range: [0, 10], rangeLocked: [true, false], ...PostParamOptions }); /** @param edgeRadius */ this.edgeRadius = ParamConfig.INTEGER(2, { range: [0, 10], rangeLocked: [true, false], ...PostParamOptions }); } } const ParamsConfig = new GodRaysVolumetricPostParamsConfig(); export class GodRaysVolumetricPostNode extends TypedPostNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this._rendererSize = new Vector2(); } static type() { return "godRaysVolumetric"; } createPass(context) { context.renderer.getSize(this._rendererSize); this.scene().threejsScene().add(this._tmpLightSource()); const pass = new GodraysPass(this._tmpLightSource(), context.camera, { color: this.pv.color, density: this.pv.density, maxDensity: this.pv.maxDensity, distanceAttenuation: this.pv.distanceAttenuation, edgeStrength: this.pv.edgeStrength, edgeRadius: this.pv.edgeRadius }); this.updatePass(pass); return pass; } updatePass(pass) { pass.setParams({ color: this.pv.color, density: this.pv.density, maxDensity: this.pv.maxDensity, distanceAttenuation: this.pv.distanceAttenuation, edgeStrength: this.pv.edgeStrength, edgeRadius: this.pv.edgeRadius }); const lightType = LIGHT_TYPES[this.pv.lightType]; const lightSource = _findLightSource(this.scene(), this.pv.lightMask, lightType); if (lightSource) { lightSource.add(this._tmpLightSource()); } else { pass.light = this._tmpLightSource(); } } _tmpLightSource() { const lightType = LIGHT_TYPES[this.pv.lightType]; switch (lightType) { case "point" /* POINT */: { return tmpPointLight; } case "directional" /* DIRECTIONAL */: { return tmpDirectionalLight; } } TypeAssert.unreachable(lightType); } }