UNPKG

@polygonjs/polygonjs

Version:

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

71 lines (70 loc) 2.14 kB
"use strict"; 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; } }