three-geospatial

repository·main·Indexed 23 days ago

https://github.com/takram-design-engineering/three-geospatial

A collection of tools for high-fidelity atmospheric rendering in Web GIS applications, featuring @takram/three-atmosphere. It implements Eric Bruneton's Precomputed Atmospheric Scattering for Three.js and React Three Fiber, supporting post-process, light-source, and mixed lighting modes. The library includes components for Atmosphere, Sky, Stars, SunLight, and AerialPerspective, as well as utilities for ECEF coordinate transformations and precomputed texture generation.

Tokens
47.2K
Snippets
87
Records
240
Agent score
81%

What's inside three-geospatial

  1. Limitations of @takram/three-clouds

    main

    When using @takram/three-clouds, be aware of the following constraints:

    • Layer Limit: A maximum of 4 cloud layers is supported because coverage is packed into a vec4 in the shaders.
    • Temporal Upscaling: The current implementation is basic and may cause ghosting, smearing (especially in sparse clouds), or disocclusion errors on scene objects.
    • Aerial Perspective Approximation: Uses transmittance-weighted mean depth, which can cause artifacts in areas where distant sparse clouds overlap.
    • Weather Tiling: Local weather is tiled using cube-sphere UV, which can result in visible seams (including at the poles).
  2. How post-process lighting works in @takram/three-atmosphere

    main

    Post-process lighting is suitable for large-scale scenes but only supports the Lambertian BRDF.

    In this mode, lighting is applied via the AerialPerspective effect. Materials must be unlit (e.g., MeshBasicMaterial) because the render buffer is treated as the surface albedo.

    Rules of thumb:

    • Use MeshBasicMaterial under post-process lighting.
    • Enable sunLight and skyLight on the AerialPerspective effect.
    • Do not enable sunLight or skyLight on AerialPerspective when using SunDirectionalLight and SkyLightProbe unless you are using a LightingMaskPass to mask them.
    import { EffectComposer } from '@react-three/postprocessing'
    import {
      AerialPerspective,
      Atmosphere,
      Sky
    } from '@takram/three-atmosphere/r3f'
    
    const Scene = () => (
      <Atmosphere date={/* Date object or timestamp */}>
        <Sky />
        <mesh>
          <meshBasicMaterial />
        </mesh>
        <EffectComposer enableNormalPass>
          <AerialPerspective sunLight skyLight />
        </EffectComposer>
      </Atmosphere>
    )
  3. Use CloudsEffect for volumetric clouds

    main

    The CloudsEffect is a post-processing effect that renders volumetric clouds. While it can be used as a standalone effect, it is primarily designed to render clouds into buffers to be composited using the AerialPerspectiveEffect from the @takram/three-atmosphere package.

    Important Compatibility Note: This effect requires the postprocessing library's EffectComposer. It is not compatible with the EffectComposer provided in the Three.js examples.

  4. How light-source lighting works in @takram/three-atmosphere

    main

    Light-source lighting is compatible with built-in Three.js materials (like MeshPhysicalMaterial) and shadows. However, both direct and indirect irradiance are only approximated for small-scale scenes.

    Objects are lit by SunDirectionalLight, SkyLightProbe, and potentially other light sources. In this mode, the render buffer stores the outgoing radiance (lit surface) rather than albedo.

    Rules of thumb:

    • Any materials can be used under light-source lighting.
    import { EffectComposer } from '@react-three/postprocessing'
    import {
      AerialPerspective,
      Atmosphere,
      Sky,
      SkyLight,
      SunLight
    } from '@takram/three-atmosphere/r3f'
    
    const Scene = () => (
      <Atmosphere date={/* Date object or timestamp */}>
        <Sky />
        <group position={/* ECEF coordinate in meters */}>
          <SkyLight />
          <SunLight />
        </group>
        <mesh>
          <meshPhysicalMaterial />
        </mesh>
        <EffectComposer>
          <AerialPerspective />
        </EffectComposer>
      </Atmosphere>
    )
  5. How CloudLayer works and how to use it

    main

    A CloudLayer represents a single layer of clouds. You can define up to 4 layers within a <Clouds /> component. If you want to define your own custom cloud setup, set disableDefaultLayers to true on the <Clouds /> component first.

    To animate layers (e.g., changing altitude), you can use a ref to the underlying CloudLayer implementation from @takram/three-clouds and modify its properties inside a useFrame loop.

    import { EffectComposer } from '@react-three/postprocessing'
    import { AerialPerspective, Atmosphere } from '@takram/three-atmosphere/r3f'
    import { CloudLayer as CloudLayerImpl } from '@takram/three-clouds'
    import { CloudLayer, Clouds } from '@takram/three-clouds/r3f'
    import { useRef } from 'react'
    import { useFrame } from '@react-three/fiber'
    
    const Scene = () => {
      // Modify an instance of the CloudLayer class transiently if props change
      // frequently.
      const layerRef = useRef<CloudLayerImpl>(null)
      useFrame(({ clock }) => {
        const layer = layerRef.current
        if (layer != null) {
          layer.height += clock.getDelta()
        }
      })
    
      return (
        <Atmosphere>
          <EffectComposer enableNormalPass>
            {/* Set disableDefaultLayers to remove the default cloud layers.
            Otherwise, CloudLayer props patches the default cloud layers. */}
            <Clouds disableDefaultLayers>
              <CloudLayer
                channel='r'
                altitude={1000}
                height={1000}
                shadow
              />
              <CloudLayer
                ref={layerRef}
                channel='r'
                altitude={2000}
                height={800}
                shadow
              />
              {/* Create fog near the ground, for example. */}
              <CloudLayer
                channel='a'
                height={300}
                densityScale={0.05}
                shapeAmount={0.2}
                shapeDetailAmount={0}
                shapeAlteringBias={0.5}
                coverageFilterWidth={1}
                densityProfile={{
                  expTerm: 1,
                  exponent: 1e-3,
                  constantTerm: 0,
                  linearTerm: 0
                }}
              />
              {/* The number of cloud layers is limited to 4. */}
            </Clouds>
            <AerialPerspective sky sunLight skyLight />
          </EffectComposer>
        </Atmosphere>
      )
    }
  6. How mixed lighting works in @takram/three-atmosphere

    main

    Mixed lighting allows you to selectively apply post-process and light-source lighting using LightingMaskPass or an MRT texture. This combines the advantages of both methods, though transparency over post-process lighting is not supported.

    To use it, assign specific meshes to a Three.js Layers object. The LightingMask component in the EffectComposer will then determine which meshes are treated as albedo (post-process) and which are treated as lit surfaces (light-source).

    import { EffectComposer } from '@react-three/postprocessing'
    import {
      AerialPerspective,
      Atmosphere,
      LightingMask,
      Sky,
      SkyLight,
      SunLight
    } from '@takram/three-atmosphere/r3f'
    import { Layers } from 'three'
    
    const LIGHTING_MASK_LAYER = 10
    const layers = new Layers()
    layers.enable(LIGHTING_MASK_LAYER)
    
    const Scene = () => (
      <Atmosphere date={/* Date object or timestamp */}>
        <Sky />
        <group position={/* ECEF coordinate in meters */}>
          <SkyLight />
          <SunLight />
        </group>
        <mesh>
          {/* This mesh is lit in post-process. */
          <meshBasicMaterial />
        </mesh>
        <mesh layers={layers}>
          {/* This mesh is lit by light sources. */
          <meshPhysicalMaterial />
        </mesh>
        <EffectComposer enableNormalPass>
          <LightingMask selectionLayer={LIGHTING_MASK_LAYER} />
          <AerialPerspective sunLight skyLight />
        </EffectComposer>
      </Atmosphere>
    )
  7. Understand the PrecomputedTextures interface

    main

    The PrecomputedTextures interface defines a collection of Look-Up Tables (LUTs) used to simulate atmospheric scattering and lighting. These textures are essential for high-fidelity atmospheric rendering.

    Key properties include:

    • transmittanceTexture: A 2D LUT containing transmittance between a point and the atmosphere's top boundary, parameterized by view height and zenith angle.
    • scatteringTexture: A 4D LUT packed into a 3D texture containing Rayleigh scattering and the red component of single Mie scattering. Parameterized by view height, zenith angle, sun zenith angle, and view-sun angle.
    • irradianceTexture: A 2D LUT containing indirect irradiance on horizontal surfaces, parameterized by view height and sun zenith angle.
    • singleMieScatteringTexture (Optional): A 3D LUT containing full RGB components of single Mie scattering to reduce artifacts.
    • higherOrderScatteringTexture (Optional): A 3D LUT containing higher-order (N ≥ 2) scattering terms. Required if using the clouds package with lightShafts enabled.
    interface PrecomputedTextures {
      irradianceTexture: Texture
      scatteringTexture: Data3DTexture
      transmittanceTexture: Texture
      singleMieScatteringTexture?: Data3DTexture
      higherOrderScatteringTexture?: Data3DTexture
    }
  8. Generate textures procedurally with ProceduralTexture and Procedural3DTexture

    main

    You can replace static texture files with classes that implement the ProceduralTexture or Procedural3DTexture interfaces. This approach reduces network payload by generating texture data on the fly, though it introduces additional computational overhead during initialization and every frame via the render method.

    Interface Properties

    • size: A readonly number representing the output texture size (assumed to be square or cubic).
    • texture: A readonly Texture | Data3DTexture representing the generated output.

    Interface Methods

    • render(renderer: WebGLRenderer, deltaTime?: number): Renders data to the output texture using the provided renderer. This method is called every frame.
    • dispose(): Frees the GPU-related resources allocated by the instance.
  9. Optimize cloud performance with quality presets

    main

    Volumetric clouds are computationally expensive. Use the qualityPreset prop on the Clouds component to adjust performance.

    Available Presets:

    • low: Disables shape detail, light shafts, and turbulence; uses lower precision for ray marching. Recommended for mobile devices.
    • medium: Disables light shafts and turbulence; uses lower precision for ray marching.
    • high: The baseline setting.
    • ultra: Increases the resolution of Beer shadow maps (BSM).

    Performance Tips:

    • Total Layer Height: Increasing the total height of cloud layers increases computational cost.
    • Erosion: Excessive erosion can reduce efficiency by causing rays to miss clouds, leading to unnecessary weather texture sampling.
  10. Add AtmosphereLight to the renderer

    main

    To use atmospheric lighting, you must register the AtmosphereLight and its corresponding AtmosphereLightNode with the renderer's library. This ensures lighting is physically correct at large scales.

    AtmosphereLight extends DirectionalLight and includes:

    • distance: The distance from the target to the light position. Adjust this to ensure shadow cameras cover intended objects.
    • direct (Uniform): Enables/disables direct sunlight. Turn off if using an environment map that already includes direct sunlight.
    • indirect (Uniform): Enables/disables indirect sunlight. Turn off if using an environment map.
    import {
      AtmosphereLight,
      AtmosphereLightNode
    } from '@takram/three-atmosphere/webgpu'
    
    renderer.library.addLight(AtmosphereLightNode, AtmosphereLight)
  11. Install @takram/three-atmosphere

    main

    Install the package using your preferred package manager. Note that three is a peer dependency, and if you are using React Three Fiber, @react-three/fiber is also required. To maintain compatibility with the WebGL codebase, ensure three is version 0.182.0 or higher.

    npm install @takram/three-atmosphere
    pnpm add @takram/three-atmosphere
    yarn add @takram/three-atmosphere