@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
71 lines (70 loc) • 2.14 kB
JavaScript
;
import { Mesh, ShaderMaterial, Color, Matrix4, ConeGeometry } from "three";
import VERTEX from "./glsl/vert.glsl";
import FRAGMENT from "./glsl/frag.glsl";
import { isBooleanTrue } from "../../Type";
import { CoreSpotLightHelper } from "./CoreSpotLightHelper";
export class VolumetricSpotLight {
constructor(container) {
this.container = container;
}
update(params) {
const light = this.container.light();
if (isBooleanTrue(params.tvolumetric)) {
const object = this.object();
CoreSpotLightHelper.transformObject(object, {
sizeMult: 1,
distance: light.distance,
angle: light.angle
});
const uniforms = object.material.uniforms;
uniforms.lightColor.value.copy(light.color);
uniforms.attenuation.value = params.volAttenuation;
uniforms.anglePower.value = params.volAnglePower;
light.add(object);
} else {
if (this._mesh) {
light.remove(this._mesh);
}
}
}
object() {
return this._mesh = this._mesh || this._createMesh();
}
_createMesh() {
const radius = 1;
const height = 1;
const radialSegments = 128;
const heightSegments = 32;
const geometry = new ConeGeometry(radius, height, radialSegments, heightSegments);
geometry.applyMatrix4(new Matrix4().makeTranslation(0, -0.5 * height, 0));
geometry.applyMatrix4(new Matrix4().makeRotationX(-Math.PI / 2));
const material = this._createMaterial();
const mesh = new Mesh(geometry, material);
mesh.matrixAutoUpdate = false;
mesh.name = `VolumetricSpotLight_${this.container.nodeName}`;
material.uniforms.lightColor.value.set("white");
return mesh;
}
_createMaterial() {
const material = new ShaderMaterial({
uniforms: {
attenuation: {
value: 5
},
anglePower: {
value: 1.2
},
lightColor: {
value: new Color("cyan")
}
},
vertexShader: VERTEX,
fragmentShader: FRAGMENT,
// blending : THREE.AdditiveBlending,
transparent: true,
depthWrite: false
});
return material;
}
}