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

@ifc-lite/renderer

v6.3.0

Published

WebGPU renderer for IFC-Lite

Downloads

14,719

Readme

@ifc-lite/renderer

WebGPU-based 3D renderer for IFClite. Zero-copy from WASM linear memory to GPU buffers, hardware frustum culling, GPU-accelerated picking, section planes, multi-model federation.

Installation

npm install @ifc-lite/renderer

Render an IFC model

import { Renderer } from '@ifc-lite/renderer';
import { GeometryProcessor } from '@ifc-lite/geometry';

const renderer = new Renderer(canvas);
const geometry = new GeometryProcessor();
await Promise.all([renderer.init(), geometry.init()]);

const meshes = [];
for await (const event of geometry.processAdaptive(new Uint8Array(buffer))) {
  if (event.type === 'batch') meshes.push(...event.meshes);
}
renderer.loadGeometry(meshes);
renderer.requestRender();

loadGeometry() accepts a GeometryResult from @ifc-lite/geometry or a raw MeshData[]. The renderer keeps geometry in GPU buffers; subsequent requestRender() calls coalesce into a single frame.

Inspect GPU pass timing

Timestamp queries are opt-in. Enable them before rendering, then read resolved samples after frames have submitted:

renderer.setGpuFrameTiming(true);
renderer.render();
const timing = renderer.getGpuFrameTiming();
console.log(timing.mode, timing.frames);

gpu-queries samples report each render pass in milliseconds. unsupported means the actual device lacks timestamp queries; no CPU or queue-completion value is substituted. Readback is asynchronous, so the first snapshot can be empty. Frames arriving during a pending map are skipped, and the bounded sample history reports overwritten frames. Errors and resource epochs identify invalid or interrupted captures. Device loss clears old samples before observers run; recovery preserves the opt-in setting and starts a new epoch. Disable with renderer.setGpuFrameTiming(false) to release the timing resources.

Recover from GPU device loss

renderer.onDeviceLost(async () => {
  const result = await renderer.recoverDevice();
  if (result.ok === false) {
    console.error('Renderer recovery failed:', result.reason);
  } else if (result.omissions.length > 0) {
    console.warn('Recovered with transient layers cleared:', result.omissions);
  }
});

recoverDevice() requests a replacement adapter/device and rebuilds the GPU scene in place, preserving the Renderer, camera, IFC geometry, model placements, visibility, selection and colour overrides. Concurrent calls share one attempt. It returns a typed failure instead of presenting an incomplete scene when CPU geometry has been released, streaming has not settled, cold geometry cannot be restored, or public addMesh() content has no CPU source. Point clouds, reference images and transient overlay layers are reported in omissions when they must be reloaded by the host.

Pick an entity

canvas.addEventListener('click', async (e) => {
  const rect = canvas.getBoundingClientRect();
  const hit = await renderer.pick(e.clientX - rect.left, e.clientY - rect.top);

  if (hit) {
    console.log(`Clicked expressId ${hit.expressId} at`, hit.worldXYZ);
    // Selection is a per-frame render option, not a stateful setter.
    renderer.render({ selectedIds: new Set([hit.expressId]) });
  }
});

For exact world-space hits with surface normals, use raycastScene(x, y) — slower but returns the precise intersection point, normal and, where provenance is unambiguous, the federation model, representation item and canonical evaluated-surface triangle.

Section planes

// Cut the model with an axis-aligned section plane (a per-frame render option)
renderer.render({
  sectionPlane: {
    axis: 'down',          // 'side' | 'down' | 'front' (X / Y / Z)
    position: 50,          // 0-100 percentage of model bounds
    enabled: true,
    flipped: false,
  },
});

// Disable
renderer.render({ sectionPlane: { axis: 'down', position: 50, enabled: false } });

Visibility + colour overrides

// Hide a list of entities (per-frame render option)
renderer.render({ hiddenIds: new Set([12345, 12346, 12347]) });

// Solo a subset (everything else gets the ghost treatment)
renderer.render({ isolatedIds: new Set([42]) });

// Tint specific entities (RGBA 0-1) via the scene's color overrides
renderer.getScene().setColorOverrides(
  new Map([
    [42, [1, 0, 0, 1]],   // bright red
    [99, [0, 1, 0, 0.4]], // semi-transparent green
  ]),
  renderer.getGPUDevice()!,
  renderer.getPipeline()!,
);
renderer.requestRender();

Multi-model federation

import { federationRegistry } from '@ifc-lite/renderer';

// The highest expressId in each model decides the offset spacing
const maxArchExpressId = 500_000;
const maxStructExpressId = 250_000;

// Register each model with a unique ID offset
federationRegistry.registerModel('arch', maxArchExpressId);
federationRegistry.registerModel('struct', maxStructExpressId);

// Now picks return globalIds; resolve back to (modelId, expressId)
const hit = await renderer.pick(x, y);
const { modelId, expressId } = federationRegistry.fromGlobalId(hit.expressId);

API

See the Rendering Guide and API Reference.

License

MPL-2.0

Registered raster references are available through renderer.getReferenceImages(); see the rendering guide for identity, coordinates, resource ownership and picking.

Exact surface tools and clipping

renderer.hasActiveClipping() reports whether the last rendered frame applied section, terrain or box clipping. It reads the retained render snapshot, so mutating a previous options object does not change the answer. raycastScene() applies that same clip state while walking triangles, so a clipped front face cannot hide a visible face behind it.