UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

121 lines (113 loc) 3.89 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _AnalyticLightNode = _interopRequireDefault(require("./AnalyticLightNode.js")); var _LightUtils = require("./LightUtils.js"); var _UniformNode = require("../core/UniformNode.js"); var _MathNode = require("../math/MathNode.js"); var _UniformGroupNode = require("../core/UniformGroupNode.js"); var _Lights = require("../accessors/Lights.js"); var _TextureNode = require("../accessors/TextureNode.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Module for representing spot lights as nodes. * * @augments AnalyticLightNode */ class SpotLightNode extends _AnalyticLightNode.default { static get type() { return 'SpotLightNode'; } /** * Constructs a new spot light node. * * @param {?SpotLight} [light=null] - The spot light source. */ constructor(light = null) { super(light); /** * Uniform node representing the cone cosine. * * @type {UniformNode<float>} */ this.coneCosNode = (0, _UniformNode.uniform)(0).setGroup(_UniformGroupNode.renderGroup); /** * Uniform node representing the penumbra cosine. * * @type {UniformNode<float>} */ this.penumbraCosNode = (0, _UniformNode.uniform)(0).setGroup(_UniformGroupNode.renderGroup); /** * Uniform node representing the cutoff distance. * * @type {UniformNode<float>} */ this.cutoffDistanceNode = (0, _UniformNode.uniform)(0).setGroup(_UniformGroupNode.renderGroup); /** * Uniform node representing the decay exponent. * * @type {UniformNode<float>} */ this.decayExponentNode = (0, _UniformNode.uniform)(0).setGroup(_UniformGroupNode.renderGroup); } /** * Overwritten to updated spot light specific uniforms. * * @param {NodeFrame} frame - A reference to the current node frame. */ update(frame) { super.update(frame); const { light } = this; this.coneCosNode.value = Math.cos(light.angle); this.penumbraCosNode.value = Math.cos(light.angle * (1 - light.penumbra)); this.cutoffDistanceNode.value = light.distance; this.decayExponentNode.value = light.decay; } /** * Computes the spot attenuation for the given angle. * * @param {Node<float>} angleCosine - The angle to compute the spot attenuation for. * @return {Node<float>} The spot attenuation. */ getSpotAttenuation(angleCosine) { const { coneCosNode, penumbraCosNode } = this; return (0, _MathNode.smoothstep)(coneCosNode, penumbraCosNode, angleCosine); } setupDirect(builder) { const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this; const lightVector = this.getLightVector(builder); const lightDirection = lightVector.normalize(); const angleCos = lightDirection.dot((0, _Lights.lightTargetDirection)(light)); const spotAttenuation = this.getSpotAttenuation(angleCos); const lightDistance = lightVector.length(); const lightAttenuation = (0, _LightUtils.getDistanceAttenuation)({ lightDistance, cutoffDistance: cutoffDistanceNode, decayExponent: decayExponentNode }); let lightColor = colorNode.mul(spotAttenuation).mul(lightAttenuation); if (light.map) { const spotLightCoord = (0, _Lights.lightProjectionUV)(light, builder.context.positionWorld); const projectedTexture = (0, _TextureNode.texture)(light.map, spotLightCoord.xy).onRenderUpdate(() => light.map); const inSpotLightMap = spotLightCoord.mul(2.).sub(1.).abs().lessThan(1.).all(); lightColor = inSpotLightMap.select(lightColor.mul(projectedTexture), lightColor); } return { lightColor, lightDirection }; } } var _default = exports.default = SpotLightNode;