Skip to content

Utils Module API Reference

This reference covers every public helper exposed from src/utils/, grouped by capability.

Table of Contents

  1. GPU Utilities
  2. Debugging & Profiling
  3. Float16 & SH Packing
  4. Mathematical Utilities
  5. Geometry Helpers
  6. Transform Constants
  7. Renderer & Environment Helpers
  8. Type Definitions

GPU Utilities

align4(n: number): number

Bitwise-aligns n to the next 4-byte boundary. Required for WebGPU buffer copies.

align4(13); // → 16

align8(n: number): number

Bitwise-aligns n to the next 8-byte boundary. Required for buffer mapping.

align8(18); // → 24

readWholeBuffer(device, src, byteLength, srcOffset = 0): Promise<Uint8Array>

Reads byteLength bytes from src into CPU memory. Internally: 1. Rounds copy/map sizes via align4/align8 2. Allocates a staging buffer (COPY_DST | MAP_READ) 3. Copies data and waits for GPU queue completion if supported 4. Maps, slices the requested region, and destroys the staging buffer

Throws if src lacks GPUBufferUsage.COPY_SRC.

dumpU32(bytes: Uint8Array): void / dumpHex(bytes: Uint8Array): void

Log helpers for visualizing readback data either as Uint32 values or hex strings.

keyToNum(code: string): number | undefined

Maps "Digit0""Digit9" keyboard codes to numeric values; returns undefined for non-digit keys.

buildCov(rot: quat, scale: vec3)

Returns the upper triangular elements [m00, m01, m02, m11, m12, m22] of Σ = R S Sᵀ Rᵀ, matching the layout expected by WGSL shaders.

sigmoid(x: number)

Numerically stable sigmoid implementation that avoids overflow for large |x|.

shNumCoefficients(l: number) / shDegreeFromNumCoeffs(n: number)

Utility pair for converting between SH degree and coefficient count. Returns undefined if n is not a perfect square.


Debugging & Profiling

class GPUStopwatch

Timestamp-query based profiler.

const stopwatch = new GPUStopwatch(device, 32);
stopwatch.start(encoder, 'gaussian-pass');
// ...
stopwatch.stop(encoder, 'gaussian-pass');
stopwatch.end(encoder);
const timings = await stopwatch.takeMeasurements(device.queue);
console.log(`${timings['gaussian-pass'] / 1e6} ms`);
  • start / stop accept string labels and throw if labels repeat or exceed capacity.
  • end resolves all queries into the internal buffer.
  • takeMeasurements maps the query buffer, converts ticks to nanoseconds (using queue.getTimestampPeriod() when available), clears internal state, and returns { [label]: durationNS }.

Buffer Debug Helpers (debug-gpu-buffers.ts)

Function Description
readGPUBuffer(device, buffer, offset?, size?) Generic readback helper returning an ArrayBuffer.
readU32FromBuffer(device, buffer, offset?) Convenience wrapper that interprets the readback as a single u32.
readONNXCountBuffer(device, countBuffer) Reads dynamic point counts produced by ONNX inference.
readModelParamsNumPoints(device, modelParamsBuffer) Reads the num_points uniform at byte offset 68.
compareBufferValues(device, buffer1, offset1, buffer2, offset2, label) Logs and returns whether two u32 values match.
debugCountPipeline(device, countBuffer, modelParamsBuffer, maxPoints) High-level trace that prints ONNX count, shader uniform count, and detects fallbacks to maxPoints.
createShaderDebugBuffer(device, size?) Allocates a STORAGE
readShaderDebugBuffer(device, buffer, numValues?) Reads the debug buffer back as Uint32Array and logs the values.

All helpers wait for queue.onSubmittedWorkDone() before mapping buffers and destroy intermediate staging buffers automatically.


Float16 & SH Packing

f32_to_f16(val: number, opts?: F16Opts)

Converts a JS number (float32) into a binary16 value in [0, 65535].

Options (F16Opts): - round: 'rne' (default) or 'rtz' - ftz: flush half subnormals to 0 - saturate: clamp overflow to 0x7BFF instead of ±Inf - canonicalNaN: force NaNs to 0x7E00 - emulateLegacyExpCutoff: zero results when exp < cutoff, matching legacy datasets

f16_to_f32(h: number)

Converts a binary16 payload back to float32 (returned as JS number).

packF16Array(src: Float32Array, opts?: F16Opts) / unpackF16Array(src: Uint16Array)

Batch conversions that respect the same options as f32_to_f16.

makeCopySH_PackedF16(params)

Creates an SH packer tailored to the source dataset:

const { copySH, wordsPerPoint } = makeCopySH_PackedF16({
  props,           // property names, e.g. ['x','y','z','f_dc_0',...]
  iDC0, iDC1, iDC2,// indices of DC coefficients
  k: 0 | 1 | 2 | 3,// SH degree
  shU32            // destination Uint32Array
});

copySH(pointIndex * wordsPerPoint, rowValues);
  • Writes exactly 48 half values (24 u32) per point, padding with zeros when necessary.
  • Reorders channel-first f_rest_* fields into [R0,G0,B0, R1,G1,B1, …] to match WGSL expectations.
  • Returns wordsPerPoint = 24 so callers can advance the destination pointer without recomputing strides.

Mathematical Utilities

Camera Math (camera-math.ts)

  • deg2rad(d: number)
  • focal2fov(focal: number, pixels: number)
  • fov2focal(fov: number, pixels: number)

Example:

const verticalFov = focal2fov(800, canvas.height);
const focalLen = fov2focal(verticalFov, canvas.height);

Bounding Boxes (aabb.ts)

const bbox = new Aabb(vec3.fromValues(-1,-1,-1), vec3.fromValues(1,1,1));
bbox.center(); // vec3
bbox.radius(); // number

Internally Aabb clones the provided vectors, so mutating the inputs later does not affect the stored bounds.


Geometry Helpers

Vec3 Helpers (vector-math.ts)

Function Signature
dot(a, b) Dot product
add(a, b) / sub(a, b) Component-wise addition/subtraction
scale(a, s) Scalar multiply
len(a) Vector length
normalize(a) Returns normalized vector or [NaN,NaN,NaN] if length is zero
isFiniteVec3(a) Validity guard

planeFromPoints(points: Vec3[], forceUp = true)

Fits a plane via covariance + power iteration. Returns { centroid, normal? }. When forceUp is true, the resulting normal is flipped upward if needed.

const upPlane = planeFromPoints(sampledPoints);
if (upPlane.normal) {
  console.log('Up vector:', upPlane.normal);
}

Transform Constants

VIEWPORT_Y_FLIP: mat4

A precomputed matrix that flips Y in clip space:

const flipped = mat4.create();
mat4.multiply(flipped, VIEWPORT_Y_FLIP, originalViewProj);

Kept as a singleton to avoid repeated allocations in render loops.


Renderer & Environment Helpers

EnvMapHelper

Method Description
loadHDRTexture(url) Loads an HDR texture via RGBELoader and sets EquirectangularReflectionMapping.
createPMREMEnvironmentMap(renderer, texture) Generates a PMREM texture for the provided renderer, handling backend/device readiness checks and disposing the generator after use. Returns null on failure.
setupRendererToneMapping(renderer, refRenderer?, toneMapping?, exposure?) Copies tone-mapping settings from another renderer or applies the provided defaults (ACES + 0.8).
updateRendererEnvironment(renderer, scene) Calls renderer.updateEnvironment(scene) when available.
setupSceneEnvironment(scene, envMap, background) Assigns scene.environment and scene.background.

All methods log warnings instead of throwing when running inside partially initialized build artifacts.

RendererInitHelper

Types

interface RendererInitOptions {
  sourceRenderer?: THREE.WebGPURenderer | null;
  originalTexture?: THREE.Texture | null;
  width?: number;
  height?: number;
  pixelRatio?: number;
  fallbackHdrUrl?: string;
}

interface RendererInitResult {
  envMap: THREE.Texture | null;
  background: THREE.Texture | null;
}

initializeRenderer(renderer, scene, options?): Promise<RendererInitResult>

One-stop initialization routine: 1. Copies clear color, tone mapping, color space, shadow, and lighting flags from sourceRenderer, or applies defaults. 2. Sets pixel ratio and size when width/height are provided. 3. Chooses an environment source: - reuses the supplied originalTexture, - clones existing scene.environment, or - loads fallbackHdrUrl (defaults to /public/textures/hdr/daytime.hdr). 4. Builds a PMREM for the target renderer and updates the scene/renderer references.

Returns { envMap, background } so callers can re-use the original HDR texture if needed.

isRendererInitialized(renderer: THREE.WebGPURenderer | null): boolean

Checks whether the renderer has a WebGPU backend and device before attempting GPU work.


Type Definitions

F16Opts

type F16Round = 'rne' | 'rtz';
interface F16Opts {
  round?: F16Round;
  ftz?: boolean;
  saturate?: boolean;
  canonicalNaN?: boolean;
  emulateLegacyExpCutoff?: number;
}

Vec3

type Vec3 = [number, number, number];

GenericGaussianPointCloudTS

Re-exported from the IO module for backward compatibility. Represents the generic interface returned by Gaussian loaders:

type GenericGaussianPointCloudTS = import('../io').GaussianDataSource;

It exposes buffer accessors (gaussianBuffer, shCoefsBuffer), metadata (numPoints, shDegree, bbox), and optional hints (center, up, kernelSize, etc.).


These APIs can be imported from src/utils (or the project-specific alias) and are safe to use on both runtime and tooling paths.