FogLightEffectDesc
The FogLightEffectDesc class is a Descriptor that generates volumetric lighting effects. It calculates volumetric fog from point lights and expresses light scattering effects.
Properties
Section titled “Properties”visible
Section titled “visible”Type: boolean | undefined
Description: Controls the visibility of the effect descriptor.
Default: true
lights
Section titled “lights”Type: FogLightDefinition[] | undefined
Description: Specifies an array of fog lights. Each light has a position, color, intensity, and an optional influence radius (radius, default 500). Positions are world (ECEF) coordinates. Build them with geodeticToVector3(). color accepts either a numeric hex value or a Color.
Default: []
Example:
import { geodeticToVector3 } from "@navaramap/three";
const position = geodeticToVector3({ lat: 35.68, lng: 139.76, height: 60,});
view.addEffect({ fogLight: { lights: [ { position: { x: position.x, y: position.y, z: position.z }, color: 0xffb45c, intensity: 1, radius: 500, }, ], },});maxLights
Section titled “maxLights”Type: number | undefined
Description: Initial light capacity hint. The internal light textures grow automatically when more lights are set, so this only pre-sizes them - passing the expected light count avoids a reallocation later.
Default: 100
Example:
{ fogLight: { maxLights: 200, }}fogDensity
Section titled “fogDensity”Type: number | undefined
Description: Specifies the density of the volumetric fog. Higher values brighten the scattering and also extend each light’s automatically derived reach.
Default: 5
Example:
{ fogLight: { fogDensity: 10, }}useSurfaceLighting
Section titled “useSurfaceLighting”Type: boolean | undefined
Description: Specifies whether lights also illuminate surfaces, in addition to the fog itself.
Default: true
Example:
{ fogLight: { useSurfaceLighting: true, }}downsample
Section titled “downsample”Type: number | undefined
Description: Fog render scale divisor: 1 = full resolution, 2 = half, 4 = quarter. The low-resolution fog is composited back with depth-aware upsampling, so higher divisors stay clean along silhouettes while cutting the GPU cost by the divisor squared.
Default: 4
Example:
{ fogLight: { downsample: 2, }}maxLightsPerTile
Section titled “maxLightsPerTile”Type: number | undefined
Description: Maximum number of lights evaluated per screen tile on the GPU. This is the main quality/cost dial: shader cost scales roughly linearly with it, and lights beyond the cap are folded into a smooth residual haze rather than dropped, so lowering it dims the weakest halos instead of producing seams.
Default: 64
Example:
{ fogLight: { maxLightsPerTile: 32, }}haloFalloff
Section titled “haloFalloff”Type: number | undefined
Description: Falloff coefficient of the halo attenuation 1 / (1 + haloFalloff * h), where h is the ray’s closest distance to the light in meters. Higher values tighten halos around their lights. Useful to suppress ghost-like glow from lights hidden behind terrain, which the fog model cannot shadow.
Default: 0.1
Example:
{ fogLight: { haloFalloff: 0.3, }}extentScale
Section titled “extentScale”Type: number | undefined
Description: Safety scale applied to each light’s effective range when registering it on screen tiles. Values below 1.0 risk cutting fog at tile borders.
Default: 1.0
Example:
{ fogLight: { extentScale: 1.0, }}tileSize
Section titled “tileSize”Type: number | undefined
Description: Screen tile size in pixels (at the fog render resolution) used for the tiled light culling.
Default: 32
Example:
{ fogLight: { tileSize: 32, }}maxFar
Section titled “maxFar”Type: number | undefined
Description: Maximum distance from the camera at which fog lights are considered. Lights that are farther than this value are culled on the CPU.
Default: the camera’s far value at effect creation
Example:
{ fogLight: { maxFar: 5000, }}debugShowGrid
Section titled “debugShowGrid”Type: boolean | undefined
Description: Specifies whether to display the tile grid and its per-tile light occupancy as a debug overlay.
Default: false
Example:
{ fogLight: { debugShowGrid: true, }}Performance
Section titled “Performance”downsampleis the biggest lever. The default4renders the fog at quarter resolution. The depth-aware upsampling keeps silhouettes clean. Use2(or1) only when the fog needs to stay crisp on close inspection.maxLightsPerTiletrades halo completeness for shader cost almost linearly. With many broad-radius lights, lowering it to32roughly halves the fog pass. The weakest halos blend into the residual haze.radiuscaps each light’s reach. The effective reach is derived automatically fromintensity,fogDensity, andhaloFalloff, then clamped byradius, so tighteningradius(or raisinghaloFalloff) directly shrinks how many tiles each light touches.- Pass the expected light count as
maxLightsto avoid a texture reallocation when lights are added later. - The tile grid only rebuilds when the camera, lights, or fog parameters change. A static view costs no CPU time.
Usage Examples
Section titled “Usage Examples”Adding a basic fog light effect
Section titled “Adding a basic fog light effect”import ThreeView, { geodeticToVector3 } from "@navaramap/three";import { FogLightEffectDesc } from "@navaramap/three-default-descs";
const view = new ThreeView();await view.init();
const position = geodeticToVector3({ lat: 35.68, lng: 139.76, height: 60,});
// Add fog light effect descriptorview.addEffect<FogLightEffectDesc>({ fogLight: { lights: [ { position: { x: position.x, y: position.y, z: position.z }, color: 0xffffff, intensity: 10, radius: 500, }, ], fogDensity: 5, useSurfaceLighting: true, },});Street light effect in a night scene
Section titled “Street light effect in a night scene”import ThreeView, { geodeticToVector3 } from "@navaramap/three";import { FogLightEffectDesc, type FogLightDefinition,} from "@navaramap/three-default-descs";
const view = new ThreeView();await view.init();
// One warm lamp per road point ([lng, lat, ground elevation in meters]);// lift each above the pavement so it reads as a glowing orbconst roadPoints: [number, number, number][] = [ [139.7601, 35.6805, 30], [139.7612, 35.6811, 31], [139.7623, 35.6816, 33],];const streetLights: FogLightDefinition[] = roadPoints.map( ([lng, lat, elevation]) => { const position = geodeticToVector3({ lat, lng, height: elevation + 14, }); return { position: { x: position.x, y: position.y, z: position.z }, color: 0xffaa00, intensity: 1, radius: 200, }; },);
view.addEffect<FogLightEffectDesc>({ fogLight: { lights: streetLights, fogDensity: 2, useSurfaceLighting: true, maxFar: view.camera.raw.far, }, visible: true,});Dynamically adding lights to a scene
Section titled “Dynamically adding lights to a scene”import ThreeView, { geodeticToVector3 } from "@navaramap/three";import { FogLightEffectDesc, type FogLightDefinition,} from "@navaramap/three-default-descs";
const view = new ThreeView();await view.init();
// Initial light arrayconst fogLights: FogLightDefinition[] = [];
// Add fog light descriptor; pre-size the capacity for the lights added laterconst fogDesc = view.addEffect<FogLightEffectDesc>({ fogLight: { lights: fogLights, fogDensity: 2, maxLights: 400, },});
// Add lights laterfunction addLight(lng: number, lat: number, height: number) { const position = geodeticToVector3({ lat, lng, height, }); fogLights.push({ position: { x: position.x, y: position.y, z: position.z }, color: 0xffffff, intensity: 10, radius: 300, });
fogDesc.update({ fogLight: { lights: fogLights, }, });}Fog lights visible only at night
Section titled “Fog lights visible only at night”import ThreeView, { geodeticToVector3 } from "@navaramap/three";import { FogLightEffectDesc } from "@navaramap/three-default-descs";
const view = new ThreeView();await view.init();
const position = geodeticToVector3({ lat: 35.68, lng: 139.76, height: 60,});
const isNight = view.atmosphere.isAtNight(view.camera.positionECEF); // Determined based on time
const fogDesc = view.addEffect<FogLightEffectDesc>({ fogLight: { lights: [ { position: { x: position.x, y: position.y, z: position.z }, color: 0xffffff, intensity: 10, radius: 500, }, ], fogDensity: 2, }, visible: isNight,});
// Toggle visibility based on timefunction updateVisibility(nightMode: boolean) { fogDesc.update({ visible: nightMode, });}- This effect supports multiple lights, and since
allowDuplicationis set totrue, multiple FogLightEffectDesc instances can be created. - The fog is not shadowed by geometry: a light hidden behind terrain still brightens the fog around it, which can read as a faint glow above a ridge. Raise
haloFalloffto suppress it. - The camera can enter the fog: scattering stays continuous when lights move beside or behind the viewer.