UNPKG

@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
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