Files

implicitjs

implicitjs is a standalone JavaScript runtime for browser-native implicit CAD models. It defines the .implicit.js model schema, builds GLSL raymarch shaders, renders models with Three.js, evaluates SDFs on the CPU, produces headless PNG/GIF snapshots, samples meshes, checks mesh quality, and exports STL, 3MF, and GLB artifacts.

The package is UI-framework agnostic. Applications provide their own editor, catalog, sidebar, persistence, and product workflow; implicitjs provides the model, rendering, snapshot, and export logic.

Install

npm install implicitjs

Peer usage expects a modern ESM JavaScript environment. Rendering APIs require Three.js-compatible WebGL support. The headless snapshot CLI uses Playwright.

Model Format

An implicit model is an ES module that exports an implicit.js/0.1.0 object. The glsl string must provide float sdf(vec3 p). It may also provide vec3 color(vec3 p, vec3 normal) for procedural color.

const GLSL = `
float sdf(vec3 p) {
  return implicit_sphere(p, vec3(0.0), radius);
}

vec3 color(vec3 p, vec3 normal) {
  return mix(vec3(0.0, 0.65, 1.0), vec3(1.0, 0.3, 0.8), normal.z * 0.5 + 0.5);
}
`;

export default {
  schema: "implicit.js/0.1.0",
  name: "parametric sphere",
  units: "mm",
  params: {
    radius: { type: "number", label: "Radius", min: 5, max: 50, default: 22, unit: "mm" }
  },
  bounds: ({ params }) => {
    const r = params.radius + 2;
    return [[-r, -r, -r], [r, r, r]];
  },
  render: { steps: 192 },
  glsl: GLSL
};

Number, boolean, color, and button params automatically become GLSL uniforms with matching names. Use param names directly in GLSL; a separate uniforms object is not needed.

bounds is optional and can be estimated from the SDF, but explicit bounds are recommended for unusual fields, thin features, periodic models, animated size changes, or export-heavy workflows.

Authored GLSL can use built-in helpers in the implicit_* namespace, such as implicit_sphere, implicit_box_centered, implicit_cylinder_capped, implicit_line_segment2, implicit_union_round, and implicit_intersect_round.

Public APIs

Common imports:

import {
  loadImplicitModuleFromSource,
  normalizeImplicitModel,
  renderImplicitToDataUrl,
  snapshotImplicitCadModel,
  exportImplicitModel,
  exportImplicitAnimatedGlb
} from "implicitjs";

Useful subpath exports:

  • implicitjs/model: schema normalization and parameterized runtime models.
  • implicitjs/loader: loading .implicit.js modules or source strings.
  • implicitjs/render: Three.js shader and camera helpers.
  • implicitjs/snapshot: browser PNG snapshot helpers.
  • implicitjs/mesh: SDF mesh sampling.
  • implicitjs/meshQuality: mesh quality checks.
  • implicitjs/export: STL/3MF/GLB export APIs.
  • implicitjs/sdfEvaluator: CPU SDF evaluator for compatible GLSL.

Rendering

import * as THREE from "three";
import { loadImplicitModuleFromSource, renderImplicitToDataUrl } from "implicitjs";

const model = await loadImplicitModuleFromSource(source);
const pngDataUrl = await renderImplicitToDataUrl(THREE, model, {
  width: 1200,
  height: 900,
  camera: "iso",
  render: { frameMargin: 1.45 },
  graphics: { modelColors: true, detail: 1.2 }
});

Camera presets include iso, front, back, left, right, top, and bottom. Cameras can also be JSON objects with position, target, up, direction, preset, and zoom.

Snapshots

From a package checkout:

npm run snapshot -- --input examples/model.implicit.js --output /tmp/model.png
npm run snapshot -- --input examples/model.implicit.js --output /tmp/model.gif --mode orbit

Orbit GIF jobs default to 6 fps over 12 seconds for a calmer review spin without increasing default render frame count. Override with orbit.fps and orbit.durationSeconds in JSON jobs when needed.

The snapshot CLI also accepts JSON jobs. A single job can include multiple outputs, and --job can load one job, an array of jobs, or { "jobs": [...] }. Prefer one multi-output job when rendering review packets because the browser, module, and runtime model can be reused.

npm run snapshot -- --job - <<'JSON'
{
  "input": "examples/model.implicit.js",
  "render": { "frameMargin": 1.55 },
  "outputs": [
    { "path": "/tmp/model-iso.png", "camera": "iso" },
    { "path": "/tmp/model-front.png", "camera": "front" },
    { "path": "/tmp/model-top.png", "camera": "top" }
  ]
}
JSON

Each output path receives a UTC timestamp before its extension.

Exports

import { exportImplicitModel, exportImplicitAnimatedGlb } from "implicitjs/browser";

const glb = await exportImplicitModel(model, {
  format: "glb",
  resolution: 96,
  params: { radius: 24 }
});

const animated = await exportImplicitAnimatedGlb(model, {
  animationId: "breathe",
  params: { radius: 24 },
  frames: 24,
  resolution: 72
});

From a package checkout:

npm run export -- --input examples/model.implicit.js --format glb --output /tmp/model.glb
npm run export -- --input examples/model.implicit.js --format stl --resolution 96
npm run export -- --input examples/model.implicit.js --format 3mf --params '{"radius":24}'

Exports sample the model's SDF inside its bounds. Higher resolutions produce denser meshes and take longer.

Package Layout

  • src/index.js: public package entrypoint.
  • src/browser.js: browser-oriented entrypoint.
  • src/common/: shared camera, parameter, theme, render-option, and headless snapshot helpers.
  • src/lib/implicitCad/: schema, model normalization, loading, shader rendering, CPU evaluation, mesh sampling, mesh quality, and exporters.
  • src/lib/viewer/: internal render presentation defaults used by shaders.
  • scripts/: snapshot, export, export-verification, and test CLIs.

Tests live beside the modules they cover as *.test.js.

Development

npm test
npm run verify:exports -- --input examples/model.implicit.js

Keep the package reusable and UI-independent. Runtime behavior that applies to model normalization, rendering, snapshots, CPU sampling, mesh export, graphics settings, parameters, and animations belongs here. Product-specific UI state, catalogs, editors, file sheets, routing, and persistence should live in the consuming application.