@openhps/core
Version:
Open Hybrid Positioning System - Core component
264 lines (242 loc) • 7.84 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.LightShadow = void 0;
var _Matrix = require("../math/Matrix4.js");
var _Vector = require("../math/Vector2.js");
var _Vector2 = require("../math/Vector3.js");
var _Vector3 = require("../math/Vector4.js");
var _Frustum = require("../math/Frustum.js");
const _projScreenMatrix = /*@__PURE__*/new _Matrix.Matrix4();
const _lightPositionWorld = /*@__PURE__*/new _Vector2.Vector3();
const _lookTarget = /*@__PURE__*/new _Vector2.Vector3();
/**
* Abstract base class for light shadow classes. These classes
* represent the shadow configuration for different light types.
*
* @abstract
*/
class LightShadow {
/**
* Constructs a new light shadow.
*
* @param {Camera} camera - The light's view of the world.
*/
constructor(camera) {
/**
* The light's view of the world.
*
* @type {Camera}
*/
this.camera = camera;
/**
* The intensity of the shadow. The default is `1`.
* Valid values are in the range `[0, 1]`.
*
* @type {number}
* @default 1
*/
this.intensity = 1;
/**
* Shadow map bias, how much to add or subtract from the normalized depth
* when deciding whether a surface is in shadow.
*
* The default is `0`. Very tiny adjustments here (in the order of `0.0001`)
* may help reduce artifacts in shadows.
*
* @type {number}
* @default 0
*/
this.bias = 0;
/**
* Defines how much the position used to query the shadow map is offset along
* the object normal. The default is `0`. Increasing this value can be used to
* reduce shadow acne especially in large scenes where light shines onto
* geometry at a shallow angle. The cost is that shadows may appear distorted.
*
* @type {number}
* @default 0
*/
this.normalBias = 0;
/**
* Setting this to values greater than 1 will blur the edges of the shadow.
* High values will cause unwanted banding effects in the shadows - a greater
* map size will allow for a higher value to be used here before these effects
* become visible.
*
* The property has no effect when the shadow map type is `PCFSoftShadowMap` and
* and it is recommended to increase softness by decreasing the shadow map size instead.
*
* The property has no effect when the shadow map type is `BasicShadowMap`.
*
* @type {number}
* @default 1
*/
this.radius = 1;
/**
* The amount of samples to use when blurring a VSM shadow map.
*
* @type {number}
* @default 8
*/
this.blurSamples = 8;
/**
* Defines the width and height of the shadow map. Higher values give better quality
* shadows at the cost of computation time. Values must be powers of two.
*
* @type {Vector2}
* @default (512,512)
*/
this.mapSize = new _Vector.Vector2(512, 512);
/**
* The depth map generated using the internal camera; a location beyond a
* pixel's depth is in shadow. Computed internally during rendering.
*
* @type {?RenderTarget}
* @default null
*/
this.map = null;
/**
* The distribution map generated using the internal camera; an occlusion is
* calculated based on the distribution of depths. Computed internally during
* rendering.
*
* @type {?RenderTarget}
* @default null
*/
this.mapPass = null;
/**
* Model to shadow camera space, to compute location and depth in shadow map.
* This is computed internally during rendering.
*
* @type {Matrix4}
*/
this.matrix = new _Matrix.Matrix4();
/**
* Enables automatic updates of the light's shadow. If you do not require dynamic
* lighting / shadows, you may set this to `false`.
*
* @type {boolean}
* @default true
*/
this.autoUpdate = true;
/**
* When set to `true`, shadow maps will be updated in the next `render` call.
* If you have set {@link LightShadow#autoUpdate} to `false`, you will need to
* set this property to `true` and then make a render call to update the light's shadow.
*
* @type {boolean}
* @default false
*/
this.needsUpdate = false;
this._frustum = new _Frustum.Frustum();
this._frameExtents = new _Vector.Vector2(1, 1);
this._viewportCount = 1;
this._viewports = [new _Vector3.Vector4(0, 0, 1, 1)];
}
/**
* Used internally by the renderer to get the number of viewports that need
* to be rendered for this shadow.
*
* @return {number} The viewport count.
*/
getViewportCount() {
return this._viewportCount;
}
/**
* Gets the shadow cameras frustum. Used internally by the renderer to cull objects.
*
* @return {Frustum} The shadow camera frustum.
*/
getFrustum() {
return this._frustum;
}
/**
* Update the matrices for the camera and shadow, used internally by the renderer.
*
* @param {Light} light - The light for which the shadow is being rendered.
*/
updateMatrices(light) {
const shadowCamera = this.camera;
const shadowMatrix = this.matrix;
_lightPositionWorld.setFromMatrixPosition(light.matrixWorld);
shadowCamera.position.copy(_lightPositionWorld);
_lookTarget.setFromMatrixPosition(light.target.matrixWorld);
shadowCamera.lookAt(_lookTarget);
shadowCamera.updateMatrixWorld();
_projScreenMatrix.multiplyMatrices(shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse);
this._frustum.setFromProjectionMatrix(_projScreenMatrix);
shadowMatrix.set(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0);
shadowMatrix.multiply(_projScreenMatrix);
}
/**
* Returns a viewport definition for the given viewport index.
*
* @param {number} viewportIndex - The viewport index.
* @return {Vector4} The viewport.
*/
getViewport(viewportIndex) {
return this._viewports[viewportIndex];
}
/**
* Returns the frame extends.
*
* @return {Vector2} The frame extends.
*/
getFrameExtents() {
return this._frameExtents;
}
/**
* Frees the GPU-related resources allocated by this instance. Call this
* method whenever this instance is no longer used in your app.
*/
dispose() {
if (this.map) {
this.map.dispose();
}
if (this.mapPass) {
this.mapPass.dispose();
}
}
/**
* Copies the values of the given light shadow instance to this instance.
*
* @param {LightShadow} source - The light shadow to copy.
* @return {LightShadow} A reference to this light shadow instance.
*/
copy(source) {
this.camera = source.camera.clone();
this.intensity = source.intensity;
this.bias = source.bias;
this.radius = source.radius;
this.mapSize.copy(source.mapSize);
return this;
}
/**
* Returns a new light shadow instance with copied values from this instance.
*
* @return {LightShadow} A clone of this instance.
*/
clone() {
return new this.constructor().copy(this);
}
/**
* Serializes the light shadow into JSON.
*
* @return {Object} A JSON object representing the serialized light shadow.
* @see {@link ObjectLoader#parse}
*/
toJSON() {
const object = {};
if (this.intensity !== 1) object.intensity = this.intensity;
if (this.bias !== 0) object.bias = this.bias;
if (this.normalBias !== 0) object.normalBias = this.normalBias;
if (this.radius !== 1) object.radius = this.radius;
if (this.mapSize.x !== 512 || this.mapSize.y !== 512) object.mapSize = this.mapSize.toArray();
object.camera = this.camera.toJSON(false).object;
delete object.camera.matrix;
return object;
}
}
exports.LightShadow = LightShadow;