npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bitruvius/ptcloud

v0.3.1

Published

Bitruvius point-cloud renderer: RGB/intensity/classification LiDAR rendering on WebGL2

Downloads

318

Readme

@bitruvius/ptcloud

The WebGL2 renderer behind every Bitruvius LiDAR layer.

Internal building block. This package exists so that @bitruvius/sdk-maplibre and the Bitruvius codecs can resolve their dependencies on npm. It has no standalone product story. Unless you are deliberately building against it, install the SDK instead.

Why it is its own package

Point clouds reach Bitruvius from several directions: I3S point scene layers, 3D Tiles point content (.pnts and glTF POINTS), standalone LEPCC captures, BVC scenes. Each has its own codec, each runs off the main thread, and none of them knows anything about drawing.

They converge on one shape: the quantized tile contract in @bitruvius/geo-core (DecodedPointTile for a single cloud, PackedPointTile for a streamed one). Positions on an integer grid, plus optional RGB, intensity and LAS classification. This package is the other side of that contract: it is what draws those tiles as a cloud. (@bitruvius/point-symbols reads the same packed tiles, but draws icons and labels from them rather than points.)

That is the whole reason for the boundary. A codec that emits the contract gets rendering for free and never links against a renderer. The renderer never links against a codec, so a new format costs it nothing. Neither side has to be rebuilt when the other changes.

It is viewer-agnostic for the same reason. PointCloudRenderer implements Renderer<DecodedPointTile> and is driven through a ViewerAdapter; StreamingPointCloudRenderer takes a raw WebGL2RenderingContext and per-frame matrices in the mercator world frame. Neither imports MapLibre or any other viewer. The only dependencies are @bitruvius/geo-core (contracts and matrix math) and @bitruvius/render-runtime (GL helpers and the shared clip, drape and shadow GLSL).

What is in it

Both renderers draw opaque gl.POINTS and dequantize in the vertex shader as world = q * scale + offset, so positions stay compact integers all the way to the GPU. Opaque means no depth sort: the depth buffer resolves occlusion, which is why the streaming path needs no sort worker and no slot allocator, unlike the splat renderer.

  • PointCloudRenderer draws one static cloud, uploaded once.
  • StreamingPointCloudRenderer draws the tiles an LOD engine has selected, each its own VAO with its own dequant offset, uploaded and released as the camera moves. It adds geometric-error distance attenuation, eye-dome lighting (a screen-space pass that shades depth gaps so a sparse cloud reads as a solid surface), layer opacity, clip planes and terrain drape.

Both cast and receive cascaded sun shadows as world-sized depth discs when a shadow coordinator drives them, and both stay byte-identical until one does. Both expose an on-demand GPU pick pass, and a top-down id grid (sampleDepthGrid) that the measure and elevation-profile tools read as a DSM.

Symbology travels with them:

  • Four color modes: rgb, intensity, classification and height.
  • The Turbo ramp (Google's perceptual colormap, used under Apache-2.0) and the ASPRS class palette are defaults, not fixtures. Turbo is a good ramp for LiDAR intensity and a poor one for a color-blind reader, and a site's own class scheme routinely contradicts ASPRS. So buildRampLut takes your stops and buildClassColorLut takes per-code overrides. Both produce the same 256-entry RGBA8 texture the shaders already sample, which is why changing symbology is a texSubImage2D and never a re-decode.
  • getClassificationLabel names LAS codes 0 to 22 from the ASPRS spec and falls back to Class {n} for the reserved and user-defined range, so a UI can label whatever a dataset turns out to contain.
  • perspectivePointSizePx is the unit-tested CPU reference for the shader's 2 * r * focalPx / |z| sizing, alongside the helper that derives focalPx from the projection matrix.
import { PointCloudRenderer } from '@bitruvius/ptcloud';

const renderer = new PointCloudRenderer({ colorMode: 'intensity' });
renderer.init(adapter);                 // adapter.gl is a WebGL2RenderingContext
renderer.setQuantization(tile.scale, tile.offset);
const handle = renderer.upload(decodedTile);
// per frame:
renderer.render(frameState);

Who should depend on it

If you are building an application, install @bitruvius/sdk-maplibre. It wires these renderers into map layers and re-exports PointCloudOptions and the color modes, so you can tune point size, ramps and class visibility without importing this package at all.

Depend on @bitruvius/ptcloud directly only if you are hosting the renderers yourself, in your own viewer or render loop, feeding tiles you have already packed into the @bitruvius/geo-core contract. It versions in lockstep with the SDK, and its surface moves with the SDK's needs.

Trademarks

Esri, I3S and LEPCC are trademarks of Environmental Systems Research Institute, Inc. 3D Tiles is a trademark of Cesium GS, Inc. glTF is a trademark of The Khronos Group Inc. Google is a trademark of Google LLC. MapLibre is a trademark of the MapLibre organization. All other marks are the property of their respective owners.

These names are used solely to describe the data formats this software interoperates with. Bitruvius is not affiliated with, sponsored by, or endorsed by any of them, and no such relationship is implied.

License

Proprietary. The full terms ship as LICENSE inside this package, and are readable before installing at cdn.bitruvius.com/legal/sdk-license-v1.txt.

© Bitruvius, Inc.