gpu-curtains
Version:
gpu-curtains is a 3D WebGPU rendering engine. It can be used as a standalone 3D engine, but also includes extra classes focused on mapping 3d objects to DOM elements; It allows users to synchronize values such as position, sizing, or scale between them.
163 lines (162 loc) • 5.24 kB
JavaScript
import { Vec3 } from "../../math/Vec3.mjs";
import { Light } from "./Light.mjs";
import { PointShadow } from "../shadows/PointShadow.mjs";
//#region src/core/lights/PointLight.ts
/**
* Create a point light, that is emitted from a point to all directions with an attenuation. A common use case for this type of light is to replicate the light emitted from a bare light bulb.
*
* This light can cast {@link PointShadow}.
*
* @example
* ```javascript
* // assuming 'renderer' is a valid Camera renderer
*
* // this point light will not cast any shadows
* const pointLight = new PointLight(renderer, {
* color: new Vec3(1),
* intensity: 1,
* position: new Vec3(5, 2, 3),
* })
*
* // this point light will cast shadows
* const pointLightWithShadows = new PointLight(renderer, {
* color: new Vec3(1),
* intensity: 10,
* range: 3,
* position: new Vec3(-10, 10, -5),
* shadow: {
* intensity: 1,
* },
* })
*
* // this point light will ALSO cast shadows!
* const anotherPointLightWithShadows = new PointLight(renderer, {
* color: new Vec3(1),
* intensity: 5,
* range: 100,
* position: new Vec3(12, 0.5, 5),
* shadow: {}, // that's enough to start casting shadows
* })
*
* // this point light will cast shadows as well...
* const lastPointLightWithShadows = new PointLight(renderer, {
* color: new Vec3(1),
* intensity: 1,
* position: new Vec3(10),
* })
*
* // ... because we're telling it here to start casting shadows
* lastPointLightWithShadows.shadow.cast()
* ```
*/
var PointLight = class extends Light {
/** @ignore */
#range;
/**
* PointLight constructor
* @param renderer - {@link CameraRenderer} or {@link GPUCurtains} used to create this {@link PointLight}.
* @param parameters - {@link PointLightBaseParams} used to create this {@link PointLight}.
*/
constructor(renderer, { label = "PointLight", color = new Vec3(1), intensity = 1, position = new Vec3(), range = 0, shadow = null } = {}) {
super(renderer, {
label,
color,
intensity,
type: "pointLights"
});
this.options = {
...this.options,
position,
range,
shadow
};
this.position.copy(position);
this.range = range;
this.parent = this.renderer.scene;
this.shadow = new PointShadow(this.renderer, {
autoRender: false,
light: this
});
if (shadow) this.shadow.cast(shadow);
}
/**
* Set or reset this {@link PointLight} {@link CameraRenderer}.
* @param renderer - New {@link CameraRenderer} or {@link GPUCurtains} instance to use.
*/
setRenderer(renderer) {
super.setRenderer(renderer);
if (this.shadow) this.shadow.setRenderer(renderer);
}
/**
* Resend all properties to the {@link CameraRenderer} corresponding {@link core/bindings/BufferBinding.BufferBinding | BufferBinding}. Called when the maximum number of {@link PointLight} has been overflowed or when updating the {@link PointLight} {@link renderer}.
* @param resetShadow - Whether to reset the {@link PointLight} shadow if any. Set to `true` when the {@link renderer} number of {@link PointLight} has been overflown, `false` when the {@link renderer} has been changed (since the shadow will reset itself).
*/
reset(resetShadow = true) {
super.reset();
this.onPropertyChanged("range", this.range);
this.onPropertyChanged("position", this.actualPosition);
if (this.shadow && resetShadow) this.shadow.reset();
}
/**
* Get this {@link PointLight} intensity.
* @returns - The {@link PointLight} intensity.
*/
get intensity() {
return super.intensity;
}
/**
* Set this {@link PointLight} intensity and clear shadow if intensity is `0`.
* @param value - The new {@link PointLight} intensity.
*/
set intensity(value) {
super.intensity = value;
if (this.shadow && this.shadow.isActive && !value) this.shadow.clearDepthTexture();
}
/**
* Get this {@link PointLight} range.
* @returns - The {@link PointLight} range.
*/
get range() {
return this.#range;
}
/**
* Set this {@link PointLight} range and update the {@link CameraRenderer} corresponding {@link core/bindings/BufferBinding.BufferBinding | BufferBinding}.
* @param value - The new {@link PointLight} range.
*/
set range(value) {
this.#range = Math.max(0, value);
this.onPropertyChanged("range", this.range);
if (this.shadow) this.shadow.camera.far = this.range ? this.range : this.shadow.options.camera.far;
}
/**
* Set the {@link PointLight} position based on the {@link worldMatrix} translation.
*/
setPosition() {
this.onPropertyChanged("position", this.actualPosition);
if (this.shadow) this.shadow.setPosition();
}
/**
* If the {@link modelMatrix | model matrix} has been updated, set the new position from the {@link worldMatrix} translation.
*/
updateMatrixStack() {
super.updateMatrixStack();
if (this.matricesNeedUpdate) this.setPosition();
}
/**
* Tell the {@link renderer} that the maximum number of {@link PointLight} has been overflown.
* @param lightsType - {@link type} of this light.
*/
onMaxLightOverflow(lightsType) {
super.onMaxLightOverflow(lightsType);
this.shadow?.setRendererBinding();
}
/**
* Destroy this {@link PointLight} and associated {@link PointShadow}.
*/
destroy() {
super.destroy();
this.shadow?.destroy();
}
};
//#endregion
export { PointLight };