@needle-tools/engine
Version:
Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.
227 lines • 9.65 kB
JavaScript
import { EquirectangularReflectionMapping, SRGBColorSpace, Vector4 } from "three";
import { AssetReference } from "./engine_addressables.js";
import { createFlatTexture, createTrilightTexture } from "./engine_shaders.js";
import { getParam } from "./engine_utils.js";
// import { LightProbeGenerator } from "three/examples/jsm/lights/LightProbeGenerator.js"
const debug = getParam("debugenvlight");
/** @internal */
export var AmbientMode;
(function (AmbientMode) {
AmbientMode[AmbientMode["Skybox"] = 0] = "Skybox";
AmbientMode[AmbientMode["Trilight"] = 1] = "Trilight";
AmbientMode[AmbientMode["Flat"] = 3] = "Flat";
AmbientMode[AmbientMode["Custom"] = 4] = "Custom";
})(AmbientMode || (AmbientMode = {}));
/** @internal */
export var DefaultReflectionMode;
(function (DefaultReflectionMode) {
DefaultReflectionMode[DefaultReflectionMode["Skybox"] = 0] = "Skybox";
DefaultReflectionMode[DefaultReflectionMode["Custom"] = 1] = "Custom";
})(DefaultReflectionMode || (DefaultReflectionMode = {}));
/**
* The RendererData class is used to manage the lighting settings of a scene.
* It is created and used within the Needle Engine Context.
*/
export class RendererData {
context;
constructor(context) {
this.context = context;
this.context.pre_update_callbacks.push(this.preUpdate.bind(this));
}
_currentLightSettingsId;
_sceneLightSettings;
preUpdate() {
const time = this.context.time;
this._timevec4.x = time.time;
this._timevec4.y = Math.sin(time.time);
this._timevec4.z = Math.cos(time.time);
this._timevec4.w = time.deltaTime;
}
_timevec4 = new Vector4();
/** Time data used for custom shaders
* x: time
* y: sin(time)
* z: cos(time)
* w: deltaTime
*/
get timeVec4() {
return this._timevec4;
}
/** the current environment intensity */
get environmentIntensity() {
if (!this._sceneLightSettings)
return 1;
if (!this._currentLightSettingsId)
return 1;
const settings = this._sceneLightSettings.get(this._currentLightSettingsId);
if (settings)
return settings.ambientIntensity; // * Math.PI * .5;
return 1;
}
/** Get all currently registered scene light settings */
get sceneLightSettings() { return this._sceneLightSettings?.values(); }
/** set the scene lighting from a specific scene. Will disable any previously enabled lighting settings */
enable(sourceId) {
if (sourceId instanceof AssetReference)
sourceId = sourceId.url;
const settings = this._sceneLightSettings?.get(sourceId);
if (!settings) {
if (debug)
console.warn("No light settings found for", sourceId);
return false;
}
if (debug)
console.log("Enable scene light settings", sourceId, settings);
if (sourceId !== this._currentLightSettingsId && this._currentLightSettingsId) {
this.disable(this._currentLightSettingsId);
}
this._currentLightSettingsId = sourceId;
settings.enabled = true;
return true;
}
/** disable the lighting of a specific scene, will only have any effect if it is currently active */
disable(sourceId) {
if (sourceId instanceof AssetReference)
sourceId = sourceId.url;
if (sourceId === null || sourceId === undefined)
return false;
const settings = this._sceneLightSettings?.get(sourceId);
if (!settings) {
return false;
}
if (debug)
console.log("Disable scene light settings", sourceId, settings);
settings.enabled = false;
return true;
}
/** Disables the currently active scene lighting (if any), returns the id of the previously active lighting */
disableCurrent() {
if (this._currentLightSettingsId) {
const prev = this._currentLightSettingsId;
this.disable(this._currentLightSettingsId);
return prev;
}
return null;
}
/** @internal */
internalRegisterSceneLightSettings(sceneLightSettings) {
const sourceId = sceneLightSettings.sourceId;
if (!sourceId) {
console.error("Missing source id for scene light settings, can not register:", sceneLightSettings);
return;
}
if (debug)
console.log("Register " + sceneLightSettings?.sourceId + " lighting", sceneLightSettings);
if (!this._sceneLightSettings)
this._sceneLightSettings = new Map();
this._sceneLightSettings.set(sourceId, sceneLightSettings);
}
/** @internal */
internalUnregisterSceneLightSettings(sceneLightSettings) {
const sourceId = sceneLightSettings.sourceId;
if (!sourceId) {
console.error("Missing source id for scene light settings, can not unregister:", sceneLightSettings);
return;
}
if (debug)
console.log("Unregister " + sceneLightSettings?.sourceId + " lighting", sceneLightSettings);
if (!this._sceneLightSettings)
return;
this._sceneLightSettings.delete(sourceId);
}
/** @internal */
internalRegisterReflection(sourceId, reflectionTexture) {
if (debug)
console.log("Register reflection", sourceId, reflectionTexture);
const h = new LightData(this.context, reflectionTexture, 1);
this._lighting[sourceId] = h;
}
/** @internal */
internalGetReflection(sourceId) {
return this._lighting[sourceId];
}
__currentReflectionId = null;
/** @internal */
internalEnableReflection(sourceId) {
this.__currentReflectionId = sourceId;
const settings = this._sceneLightSettings?.get(sourceId);
if (debug) {
console.log("Enable reflection", sourceId, settings ? AmbientMode[settings.ambientMode] : "Unknown ambient mode", settings);
}
switch (settings?.ambientMode) {
case AmbientMode.Skybox:
case AmbientMode.Custom:
// only set environment reflection when ambient mode is skybox or custom
const existing = this.internalGetReflection(sourceId);
if (existing && existing.Source) {
if (debug)
console.log("Setting environment reflection", existing);
const scene = this.context.scene;
const tex = existing.Source;
tex.mapping = EquirectangularReflectionMapping;
scene.environment = tex;
return;
}
else if (debug)
console.warn("Could not find reflection for source", sourceId);
break;
}
if (settings?.environmentReflectionSource === DefaultReflectionMode.Custom) {
switch (settings?.ambientMode) {
case AmbientMode.Trilight:
if (settings.ambientTrilight) {
const colors = settings.ambientTrilight;
const tex = createTrilightTexture(colors[0], colors[1], colors[2], 64, 64);
tex.colorSpace = SRGBColorSpace;
tex.mapping = EquirectangularReflectionMapping;
this.context.scene.environment = tex;
}
else
console.error("Missing ambient trilight", settings.sourceId);
return;
case AmbientMode.Flat:
if (settings.ambientLight) {
const tex = createFlatTexture(settings.ambientLight, 64);
tex.colorSpace = SRGBColorSpace;
tex.mapping = EquirectangularReflectionMapping;
this.context.scene.environment = tex;
}
else
console.error("Missing ambientlight", settings.sourceId);
return;
default:
return;
}
}
}
/** @internal */
internalDisableReflection(sourceId) {
if (sourceId && sourceId !== this.__currentReflectionId) {
if (debug)
console.log("Not disabling reflection for", sourceId, "because it is not the current light settings id", this.__currentReflectionId);
return;
}
if (debug)
console.log("Disable reflection", sourceId);
const scene = this.context.scene;
scene.environment = null;
}
_lighting = {};
}
export class LightData {
get Source() { return this._source; }
// get Array(): number[] | undefined { return this._sphericalHarmonicsArray; }
_source;
// private _sphericalHarmonicsArray?: number[];
// private _context: Context;
// private _sphericalHarmonics: SphericalHarmonics3 | null = null;
// private _ambientScale: number = 1;
// private _lightProbe?: LightProbe;
constructor(_context, tex, _ambientScale = 1) {
// this._context = context;
this._source = tex;
// this._ambientScale = ambientScale;
tex.mapping = EquirectangularReflectionMapping;
}
}
//# sourceMappingURL=engine_scenelighting.js.map