or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

application-management.mdattribute-management.mdcontrollers.mdcoordinate-systems.mdeffects-and-lighting.mdindex.mdlayer-system.mdtransitions-and-animation.mdutilities-and-helpers.mdviews-and-viewports.md
tile.json

effects-and-lighting.mddocs/

Effects and Lighting

Visual enhancement system with lighting effects and post-processing capabilities for photorealistic rendering and advanced visual effects in 3D visualizations.

Capabilities

Effect Base Class

Abstract base class for all visual effects applied during rendering.

/**
 * Abstract base class for visual effects
 * Provides hooks for pre-render and post-render processing
 */
abstract class Effect {
  /** Initialize effect with properties */
  constructor(props?: any);
  
  /** Pre-render setup and preparation */
  preRender(gl: WebGL2RenderingContext, opts: PreRenderOptions): void;
  
  /** Post-render processing and cleanup */
  postRender(gl: WebGL2RenderingContext, opts: PostRenderOptions): void;
  
  /** Get shader modules required by this effect */
  getModules(): ShaderModule[];
  
  /** Get effect parameters for shader uniforms */
  getParameters(): any;
  
  /** Clean up effect resources */
  cleanup(): void;
  
  /** Effect configuration properties */
  readonly props: any;
}

interface PreRenderOptions {
  /** Current viewport */
  viewport: Viewport;
  
  /** Effect manager instance */
  effectManager: any;
  
  /** Current render pass */
  renderPass: string;
  
  /** Whether this is a picking pass */
  isPicking: boolean;
  
  /** Layers being rendered */
  layers: Layer[];
}

interface PostRenderOptions {
  /** Current viewport */
  viewport: Viewport;
  
  /** Effect manager instance */
  effectManager: any;
  
  /** Current render pass */
  renderPass: string;
  
  /** Whether this is a picking pass */
  isPicking: boolean;
  
  /** Rendered layers */
  layers: Layer[];
  
  /** Target framebuffer */
  target?: Framebuffer;
}

interface EffectContext {
  /** WebGL rendering context */
  gl: WebGL2RenderingContext;
  
  /** Luma.gl device */
  device: Device;
  
  /** Current viewport */
  viewport: Viewport;
  
  /** Render pass identifier */
  renderPass: string;
  
  /** Effect manager */
  effectManager: any;
}

LightingEffect

Comprehensive lighting system managing multiple light sources for realistic 3D rendering.

/**
 * Lighting effect managing multiple light sources
 * Provides ambient, directional, and point lighting for 3D scenes
 */
class LightingEffect extends Effect {
  /** Initialize lighting effect with light sources */
  constructor(props: LightingEffectProps);
  
  /** Add a light source */
  addLight(light: AmbientLight | DirectionalLight | PointLight): void;
  
  /** Remove a light source */
  removeLight(light: AmbientLight | DirectionalLight | PointLight): void;
  
  /** Update light configuration */
  setProps(props: Partial<LightingEffectProps>): void;
  
  /** Get shader modules for lighting */
  getModules(): ShaderModule[];
  
  /** Get lighting uniforms */
  getParameters(): any;
  
  /** Currently active lights */
  readonly lights: (AmbientLight | DirectionalLight | PointLight)[];
}

interface LightingEffectProps {
  /** Array of light sources */
  lights?: (AmbientLight | DirectionalLight | PointLight)[];
  
  /** Ambient light color when no ambient lights provided */
  ambientLightColor?: [number, number, number];
  
  /** Shadow mapping configuration */
  shadowMaps?: boolean;
  
  /** Number of shadow maps */
  numberOfShadowMaps?: number;
}

Usage Examples:

import { 
  LightingEffect, 
  AmbientLight, 
  DirectionalLight, 
  PointLight 
} from "@deck.gl/core";

// Create comprehensive lighting setup
const ambientLight = new AmbientLight({
  color: [255, 255, 255],
  intensity: 0.3
});

const directionalLight = new DirectionalLight({
  color: [255, 255, 255],
  intensity: 1.0,
  direction: [-1, -3, -1]
});

const pointLight = new PointLight({
  color: [255, 255, 255],
  intensity: 2.0,
  position: [0, 0, 1000],
  attenuation: [1, 0, 0.0001]
});

const lightingEffect = new LightingEffect({
  lights: [ambientLight, directionalLight, pointLight]
});

// Use in Deck
const deck = new Deck({
  effects: [lightingEffect],
  // ... other props
});

// Dynamic lighting changes
const timeOfDay = (hour) => {
  const sunIntensity = Math.max(0, Math.cos((hour - 12) * Math.PI / 12));
  const sunColor = [255, 255 - 50 * (1 - sunIntensity), 200 + 55 * sunIntensity];
  
  directionalLight.setProps({
    color: sunColor,
    intensity: sunIntensity,
    direction: [
      Math.sin((hour - 6) * Math.PI / 12),
      -Math.cos((hour - 6) * Math.PI / 12), 
      -0.5
    ]
  });
};

Light Sources

AmbientLight

Uniform ambient lighting affecting all surfaces equally.

/**
 * Ambient light providing uniform illumination
 * Affects all surfaces equally with no directionality
 */
class AmbientLight {
  /** Initialize ambient light */
  constructor(props: AmbientLightOptions);
  
  /** Update light properties */
  setProps(props: Partial<AmbientLightOptions>): void;
  
  /** Light color RGB */
  readonly color: [number, number, number];
  
  /** Light intensity multiplier */
  readonly intensity: number;
}

interface AmbientLightOptions {
  /** Light color in RGB [0-255] */
  color?: [number, number, number];
  
  /** Light intensity [0-1+] */
  intensity?: number;
}

DirectionalLight

Directional light source simulating distant light like the sun.

/**
 * Directional light simulating distant light sources
 * Provides parallel light rays from a specific direction (like sunlight)
 */
class DirectionalLight {
  /** Initialize directional light */
  constructor(props: DirectionalLightOptions);
  
  /** Update light properties */
  setProps(props: Partial<DirectionalLightOptions>): void;
  
  /** Light color RGB */
  readonly color: [number, number, number];
  
  /** Light intensity multiplier */
  readonly intensity: number;
  
  /** Light direction vector */
  readonly direction: [number, number, number];
  
  /** Shadow map configuration */
  readonly shadow: boolean;
}

interface DirectionalLightOptions {
  /** Light color in RGB [0-255] */
  color?: [number, number, number];
  
  /** Light intensity [0-1+] */
  intensity?: number;
  
  /** Direction vector [x, y, z] */
  direction?: [number, number, number];
  
  /** Enable shadow casting */
  shadow?: boolean;
  
  /** Shadow map size */
  shadowMapSize?: number;
  
  /** Shadow bias to prevent shadow acne */
  shadowBias?: number;
}

PointLight

Point light source with position and attenuation.

/**
 * Point light source with position-based attenuation
 * Emits light in all directions from a specific point
 */
class PointLight {
  /** Initialize point light */
  constructor(props: PointLightOptions);
  
  /** Update light properties */
  setProps(props: Partial<PointLightOptions>): void;
  
  /** Light color RGB */
  readonly color: [number, number, number];
  
  /** Light intensity multiplier */
  readonly intensity: number;
  
  /** Light position in world coordinates */
  readonly position: [number, number, number];
  
  /** Attenuation coefficients [constant, linear, quadratic] */
  readonly attenuation: [number, number, number];
}

interface PointLightOptions {
  /** Light color in RGB [0-255] */
  color?: [number, number, number];
  
  /** Light intensity [0-1+] */
  intensity?: number;
  
  /** Light position [x, y, z] */
  position?: [number, number, number];
  
  /** Attenuation [constant, linear, quadratic] */
  attenuation?: [number, number, number];
}

_CameraLight (Experimental)

Experimental light source attached to camera position.

/**
 * Experimental camera-attached light source
 * Light follows camera position and direction
 */
class _CameraLight {
  /** Initialize camera light */
  constructor(props: CameraLightOptions);
  
  /** Update light properties */
  setProps(props: Partial<CameraLightOptions>): void;
  
  /** Light color RGB */
  readonly color: [number, number, number];
  
  /** Light intensity multiplier */
  readonly intensity: number;
}

interface CameraLightOptions {
  /** Light color in RGB [0-255] */
  color?: [number, number, number];
  
  /** Light intensity [0-1+] */
  intensity?: number;
}

_SunLight (Experimental)

Experimental sun light with time-based positioning calculations.

/**
 * Experimental sun light with astronomical calculations
 * Automatically positions sun based on time and location
 */
class _SunLight {
  /** Initialize sun light */
  constructor(props: SunLightOptions);
  
  /** Update sun properties */
  setProps(props: Partial<SunLightOptions>): void;
  
  /** Calculate sun position for given time and location */
  getSunPosition(timestamp: number, latitude: number, longitude: number): {
    azimuth: number;
    elevation: number;
  };
  
  /** Light color RGB */
  readonly color: [number, number, number];
  
  /** Light intensity multiplier */
  readonly intensity: number;
  
  /** Current sun direction */
  readonly direction: [number, number, number];
  
  /** Timestamp for sun calculation */
  readonly timestamp: number;
}

interface SunLightOptions {
  /** Light color in RGB [0-255] */
  color?: [number, number, number];
  
  /** Light intensity [0-1+] */
  intensity?: number;
  
  /** Timestamp for sun position (Unix timestamp) */
  timestamp?: number;
  
  /** Latitude for sun calculation */
  latitude?: number;
  
  /** Longitude for sun calculation */
  longitude?: number;
}

Usage Examples:

import { _SunLight } from "@deck.gl/core";

// Realistic sun lighting based on time and location
const sunLight = new _SunLight({
  color: [255, 255, 240],
  intensity: 1.0,
  timestamp: Date.now(),
  latitude: 37.7749,  // San Francisco
  longitude: -122.4194
});

// Animate sun through the day
const animateSun = () => {
  const now = Date.now();
  sunLight.setProps({
    timestamp: now
  });
  
  const sunPos = sunLight.getSunPosition(now, 37.7749, -122.4194);
  console.log(`Sun elevation: ${sunPos.elevation}°, azimuth: ${sunPos.azimuth}°`);
};

setInterval(animateSun, 60000); // Update every minute

PostProcessEffect

Abstract base class for post-processing effects applied after layer rendering.

/**
 * Abstract base class for post-processing effects
 * Applied after all layers are rendered to the screen
 */
abstract class PostProcessEffect extends Effect {
  /** Initialize post-process effect */
  constructor(props?: any);
  
  /** Setup render targets and resources */
  abstract setup(context: EffectContext): void;
  
  /** Render the post-processing effect */
  abstract render(context: EffectContext): void;
  
  /** Whether effect modifies the color buffer */
  abstract getModuleParameters(): any;
  
  /** Clean up effect resources */
  cleanup(): void;
}

Usage Examples:

// Custom post-processing effect
class BloomEffect extends PostProcessEffect {
  constructor(props = {}) {
    super(props);
    this.threshold = props.threshold || 0.7;
    this.intensity = props.intensity || 1.0;
    this.radius = props.radius || 1.0;
  }
  
  setup({device, viewport}) {
    // Create framebuffers and shaders for bloom effect
    this.bloomFramebuffer = device.createFramebuffer({
      width: viewport.width,
      height: viewport.height
    });
    
    this.blurFramebuffers = [
      device.createFramebuffer({width: viewport.width / 2, height: viewport.height / 2}),
      device.createFramebuffer({width: viewport.width / 4, height: viewport.height / 4})
    ];
  }
  
  render({gl, viewport, effectManager}) {
    // 1. Extract bright areas
    // 2. Apply Gaussian blur
    // 3. Combine with original scene  
    // Implementation details...
  }
  
  getModuleParameters() {
    return {
      bloomThreshold: this.threshold,
      bloomIntensity: this.intensity,
      bloomRadius: this.radius
    };
  }
}

// Use custom effect
const deck = new Deck({
  effects: [
    new LightingEffect({lights: [...]}),
    new BloomEffect({
      threshold: 0.8,
      intensity: 1.5,
      radius: 2.0
    })
  ]
});

Shader Integration

Lighting Shader Modules

Built-in shader modules for lighting calculations.

// Shader modules for lighting (imported from shaderlib)
const gouraudLighting: ShaderModule;
const phongLighting: ShaderModule;
const shadow: ShaderModule;

interface ShaderModule {
  /** Module name */
  name: string;
  
  /** Vertex shader code */
  vs?: string;
  
  /** Fragment shader code */
  fs?: string;
  
  /** Uniform definitions */
  uniforms?: any;
  
  /** Module dependencies */
  dependencies?: ShaderModule[];
}

Effect Management

Effect System Integration

How effects integrate with the rendering pipeline.

interface EffectManager {
  /** Add effect to manager */
  addEffect(effect: Effect): void;
  
  /** Remove effect from manager */
  removeEffect(effect: Effect): void;
  
  /** Process all pre-render effects */
  preDraw(opts: PreRenderOptions): void;
  
  /** Process all post-render effects */
  postDraw(opts: PostRenderOptions): void;
  
  /** Get combined shader modules from all effects */
  getModules(): ShaderModule[];
  
  /** Get combined parameters from all effects */
  getParameters(): any;
}

Usage Examples:

import { 
  Deck, 
  LightingEffect, 
  AmbientLight, 
  DirectionalLight, 
  PointLight 
} from "@deck.gl/core";

// Complex lighting scenario
const createDynamicLighting = () => {
  // Base ambient lighting
  const ambient = new AmbientLight({
    color: [30, 30, 60],
    intensity: 0.4
  });
  
  // Key light (main directional)
  const keyLight = new DirectionalLight({
    color: [255, 245, 235],
    intensity: 1.2,
    direction: [-1, -2, -1],
    shadow: true
  });
  
  // Fill light (softer directional)
  const fillLight = new DirectionalLight({
    color: [235, 245, 255],
    intensity: 0.6,
    direction: [1, -1, 0.5]
  });
  
  // Accent point lights
  const accentLights = [
    new PointLight({
      color: [255, 100, 100],
      intensity: 2.0,
      position: [-1000, -1000, 500],
      attenuation: [1, 0, 0.0001]
    }),
    new PointLight({
      color: [100, 255, 100],
      intensity: 2.0,
      position: [1000, 1000, 500],
      attenuation: [1, 0, 0.0001]
    })
  ];
  
  return new LightingEffect({
    lights: [ambient, keyLight, fillLight, ...accentLights],
    shadowMaps: true,
    numberOfShadowMaps: 2
  });
};

// Create deck with dynamic lighting
const deck = new Deck({
  effects: [createDynamicLighting()],
  views: [new MapView({id: 'map'})],
  initialViewState: {
    longitude: -122.4,
    latitude: 37.8,
    zoom: 12,
    pitch: 45
  }
});

// Animate lighting based on time of day
const animateLighting = (hour) => {
  const sunAngle = (hour - 6) * Math.PI / 12; // 6 AM = 0, 6 PM = π
  const sunIntensity = Math.max(0.1, Math.sin(Math.max(0, sunAngle)));
  
  // Update sun color based on angle
  const sunColor = [
    255,
    255 - 80 * (1 - sunIntensity),
    200 + 55 * sunIntensity
  ];
  
  const lightingEffect = deck.props.effects[0];
  const keyLight = lightingEffect.lights.find(light => light instanceof DirectionalLight);
  
  keyLight.setProps({
    color: sunColor,
    intensity: sunIntensity,
    direction: [
      Math.sin(sunAngle),
      -Math.cos(sunAngle),
      -0.3
    ]
  });
  
  deck.redraw();
};

// Simulate day/night cycle
let currentHour = 6;
setInterval(() => {
  currentHour = (currentHour + 0.25) % 24; // 15 minutes = 1 hour
  animateLighting(currentHour);
}, 1000);