# How ImplicitJS Renders SDF CAD Models in the Browser: A Complete Technical Guide

> Learn how ImplicitJS renders SDF CAD models in the browser using WebGL and Three.js. Discover client-side ray marching and GPU-accelerated techniques for seamless visualization.

- Repository: [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)
- Tags: deep-dive
- Published: 2026-08-01

---

**ImplicitJS renders Signed-Distance-Field (SDF) CAD models entirely client-side using WebGL and Three.js by generating custom fragment shaders that perform GPU-based ray marching, coupled with CPU-side bound estimation for optimal camera framing.**

The `earthtojake/text-to-cad` repository contains ImplicitJS, a specialized rendering engine that transforms mathematical SDF descriptions into photorealistic browser-based CAD visualizations. Unlike traditional mesh-based renderers, this system evaluates signed distance functions directly on the GPU through dynamically generated GLSL shaders. Understanding how ImplicitJS renders SDF CAD models in the browser reveals a sophisticated pipeline that balances computational efficiency with visual fidelity.

## The Four-Phase Rendering Pipeline

The rendering process follows a strict sequence that bridges JavaScript preprocessing with high-performance GPU execution. Each phase addresses specific technical requirements for converting raw SDF definitions into interactive visual output.

### Phase 1: Model Normalization

Before any GPU computation begins, raw model descriptors undergo canonical transformation. The `normalizeImplicitCadModel` function in [`packages/implicitjs/src/lib/implicitCad/model.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/implicitjs/src/lib/implicitCad/model.js) ensures structural consistency by injecting default values for missing parameters.

This normalization process coerces vector values to proper arrays, establishes default `radius` and `center` coordinates, and validates the `bounds` property. The function also processes uniform declarations, ensuring that user-defined GLSL variables meet the strict typing requirements for subsequent shader compilation.

### Phase 2: CPU-Side SDF Evaluation for Bounds

Accurate camera framing requires tight axis-aligned bounding boxes computed before shader compilation. The engine employs `createImplicitCadSdfEvaluator` from [`packages/implicitjs/src/lib/implicitCad/sdfEvaluator.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/implicitjs/src/lib/implicitCad/sdfEvaluator.js) to construct a JavaScript sampler that executes the user-supplied GLSL distance function on the CPU.

The functions `estimateImplicitCadFrameBounds` and `estimateImplicitCadFrameBoundsAsync` (lines 71-88 in [`packages/implicitjs/src/lib/implicitCad/render.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/implicitjs/src/lib/implicitCad/render.js)) utilize this evaluator to sample the SDF across spatial regions. These routines cache results in `frameBoundsEstimateCache` to prevent redundant computation during animation loops. The computed bounds directly influence floor-shadow placement and camera positioning, ensuring the model remains centered and properly scaled within the viewport.

### Phase 3: Runtime Fragment Shader Generation

The core rendering logic resides in `implicitCadFragmentShader` (lines 94-140 in [`packages/implicitjs/src/lib/implicitCad/render.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/implicitjs/src/lib/implicitCad/render.js)), which assembles GLSL source code at runtime. This generator constructs a complete fragment program that includes:

- **Uniform declarations** via `implicitCadUniformDeclarations` for all user-defined variables
- **SDF injection** of the user-provided `glslSource` into the shader's distance evaluation function
- **Lighting pipeline** implementing ambient, key, fill, bounce, rim, and floor-shadow illumination matching the mesh viewer's shading model
- **Helper primitives** for common geometric operations (spheres, boxes, tori) and procedural patterns (triangular waves, honeycombs, TPMS structures)

The generated shader exposes a standardized `sdf(p)` entry point utilized by the generic ray-marching routines `implicit_scene_sdf` and `implicit_ray_bounds`.

### Phase 4: Three.js Integration and Rendering

The final phase bridges the generated GLSL with Three.js infrastructure. The engine creates a `ShaderMaterial` instance populated with uniforms resolved through `resolveAppearanceSettings` and `resolveSourceBaseColor`. 

A full-screen quad (`PlaneGeometry`) receives this material, and `implicitCadCameraState` (lines 337-393 in [`render.js`](https://github.com/earthtojake/text-to-cad/blob/main/render.js)) configures the camera based on previously estimated bounds. The rendering loop invokes standard Three.js methods, but the computational heavy lifting—ray marching, normal estimation, ambient occlusion, soft shadows, and tone mapping—executes entirely within the fragment shader across pixel threads.

## Code Implementation Examples

### Basic Sphere Rendering

The following example demonstrates minimal setup for rendering a spherical SDF:

```javascript
import * as THREE from 'three';
import { implicitCadFragmentShader, implicitCadCameraState } from 'implicitjs';

// Define the SDF model descriptor
const sphereModel = {
  glslSource: `float sdf(vec3 p){ return length(p) - 0.5; }`,
  radius: 0.5,
  center: [0, 0, 0],
  uniforms: {
    uKeyColor: { type: 'vec3', value: [1, 0.8, 0.6] },
    uBackgroundColor: { type: 'vec3', value: [0.1, 0.12, 0.15] },
  },
};

// Generate the fragment shader containing the ray marcher
const fragmentSrc = implicitCadFragmentShader(sphereModel);

// Configure Three.js shader material
const material = new THREE.ShaderMaterial({
  fragmentShader: fragmentSrc,
  vertexShader: `void main(){ gl_Position = vec4(position, 1.0); }`,
  uniforms: {
    uResolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
    // Additional camera and lighting uniforms populated here
  },
});

// Create full-screen render quad
const geometry = new THREE.PlaneGeometry(2, 2);
const mesh = new THREE.Mesh(geometry, material);
const scene = new THREE.Scene();
scene.add(mesh);

// Compute camera state from model bounds
const cameraState = implicitCadCameraState(sphereModel, 'iso');
const camera = new THREE.PerspectiveCamera(48, 1, 0.1, 1000);
camera.position.fromArray(cameraState.position);
camera.lookAt(new THREE.Vector3(...cameraState.target));

// Execute render
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.render(scene, camera);

```

### Async Bounds Estimation for Complex Models

For computationally expensive SDFs, use asynchronous bound estimation to maintain UI responsiveness:

```javascript
import {
  implicitCadFragmentShader,
  implicitCadCameraState,
  estimateImplicitCadFrameBoundsAsync,
} from 'implicitjs';

const complexModel = {
  // Complex glslSource with multiple Boolean operations
  glslSource: `float sdf(vec3 p){ /* complex operations */ }`,
  uniforms: { /* extensive uniform definitions */ },
};

// Compute bounds without blocking the main thread
estimateImplicitCadFrameBoundsAsync(complexModel).then((bounds) => {
  complexModel.bounds = bounds;
  
  // Generate shader after bounds are established
  const frag = implicitCadFragmentShader(complexModel);
  const material = new THREE.ShaderMaterial({
    fragmentShader: frag,
    vertexShader: 'void main(){gl_Position=vec4(position,1.0);}',
  });

  // Camera uses refined bounds for precise framing
  const camState = implicitCadCameraState(complexModel, 'iso');
  const cam = new THREE.PerspectiveCamera(48, 1, 0.1, 1000);
  cam.position.fromArray(camState.position);
  cam.lookAt(new THREE.Vector3(...camState.target));
  
  // Proceed with scene construction...
});

```

## Key Source Files and Architecture

Understanding the repository structure clarifies the separation of concerns in the rendering pipeline:

- **[`packages/implicitjs/src/lib/implicitCad/render.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/implicitjs/src/lib/implicitCad/render.js)** – Contains the primary rendering orchestration including `implicitCadFragmentShader`, bound estimation functions, and camera state calculations
- **[`packages/implicitjs/src/lib/implicitCad/sdfEvaluator.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/implicitjs/src/lib/implicitCad/sdfEvaluator.js)** – Implements the CPU-side JavaScript SDF sampler used for spatial bound detection
- **[`packages/implicitjs/src/lib/implicitCad/model.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/implicitjs/src/lib/implicitCad/model.js)** – Provides `normalizeImplicitCadModel` for input validation and default injection
- **[`packages/implicitjs/src/lib/implicitCad/graphicsSettings.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/implicitjs/src/lib/implicitCad/graphicsSettings.js)** – Parses rendering parameters including exposure, lighting intensities, and tone-mapping curves
- **[`packages/implicitjs/src/lib/implicitCad/render.test.js`](https://github.com/earthtojake/text-to-cad/blob/main/packages/implicitjs/src/lib/implicitCad/render.test.js)** – Unit test coverage verifying shader generation accuracy and bound estimation correctness

## Summary

- **ImplicitJS** generates custom GLSL fragment shaders at runtime to evaluate SDFs directly on the GPU via ray marching.
- **CPU pre-processing** using `createImplicitCadSdfEvaluator` computes tight bounding boxes for optimal camera framing without GPU overhead.
- **Model normalization** through `normalizeImplicitCadModel` ensures consistent handling of defaults and vector coercion before shader compilation.
- **Three.js integration** utilizes full-screen quads with `ShaderMaterial` instances, delegating all geometric evaluation to the fragment shader.
- **Asynchronous bound estimation** via `estimateImplicitCadFrameBoundsAsync` prevents UI blocking when processing complex implicit surfaces.

## Frequently Asked Questions

### What is the difference between CPU and GPU evaluation in ImplicitJS?

The CPU evaluation uses `createImplicitCadSdfEvaluator` in [`sdfEvaluator.js`](https://github.com/earthtojake/text-to-cad/blob/main/sdfEvaluator.js) to execute the distance function in JavaScript for spatial sampling and bound estimation only. The GPU evaluation occurs within the generated fragment shader from `implicitCadFragmentShader`, where millions of pixels execute the SDF simultaneously for final rendering, lighting, and shadow calculations.

### How does ImplicitJS handle camera positioning for SDF models?

The `implicitCadCameraState` function (lines 337-393 in [`render.js`](https://github.com/earthtojake/text-to-cad/blob/main/render.js)) calculates camera position, target vectors, and zoom levels based on the axis-aligned bounding box estimated by `estimateImplicitCadFrameBounds`. This ensures the model remains centered and properly scaled regardless of the SDF's geometric complexity or spatial extent.

### Can ImplicitJS render complex Boolean operations and procedural textures?

Yes. The shader generation pipeline supports arbitrary GLSL code injection through the `glslSource` property, enabling Union, Intersection, and Difference Boolean operations. The system also includes built-in helper functions for procedural patterns including triangular waves, honeycomb lattices, and Triply Periodic Minimal Surfaces (TPMS) within the generated fragment shader.

### Why does ImplicitJS use ray marching instead of traditional mesh rasterization?

Ray marching evaluates the SDF directly without tessellation, allowing infinite resolution and perfect curved surfaces regardless of camera proximity. This approach eliminates mesh generation overhead, supports dynamic Boolean operations impossible with static meshes, and maintains consistent performance characteristics for both simple primitives and complex procedural geometries.