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