An SVG renderer for Three.js with hidden line removal - designed for pen plotters and laser cutters.
npm install github:neurofuzzy/three-plotter-renderer threeimport * as THREE from 'three';
import { PlotterRenderer } from 'three-plotter-renderer';
const glRenderer = new THREE.WebGLRenderer();
const plotterRenderer = new PlotterRenderer();
plotterRenderer.setSize(800, 600);
plotterRenderer.setGLRenderer(glRenderer);
// Render your scene to SVG (async to avoid blocking on complex models)
plotterRenderer.clear();
await plotterRenderer.renderGPULayers(scene, camera);
// Export
const svg = plotterRenderer.domElement.outerHTML;- π¨ Hidden line removal - Edge-based occlusion testing produces clean, plottable output
- π Multi-layer SVG output - Separate layers for silhouettes, edges, and hatching
- ποΈ Perspective hatching - GPU-accelerated, depth-aware hatching that converges toward vanishing points
- π§ Configurable styling - Control stroke colors, widths, and hatch spacing per-axis
- π¦ Inkscape compatible - Exports with proper namespace and layer structure
- π TypeScript support - Full type definitions included
npm install three-plotter-renderer three
# or from GitHub:
npm install github:neurofuzzy/three-plotter-renderer threegit clone https://github.com/neurofuzzy/three-plotter-renderer.git
cd three-plotter-renderer
npm install
npm run dev # Start dev server
npm run build # Build for production
npm run test # Run testsOpen http://localhost:5173/ to see the primitives demo.
The hidden line algorithm uses a multi-pass approach for efficient edge classification and occlusion testing:
-
Edge Extraction - Extracts all edges from mesh geometry, tracking which faces share each edge and their normals
-
Backface Filtering - Removes edges where both adjacent faces are facing away from the camera
-
Profile Detection - Marks edges as silhouettes when they border a front-facing and back-facing face (guaranteed to be visible profile edges)
-
Smooth Edge Filtering - Removes edges between faces with similar normals (within configurable threshold), eliminating internal tessellation edges
-
Intersection Splitting - Uses spatial hashing to efficiently find edge intersections; subdivides edges at crossing points so each resulting segment has a single occlusion state
-
Occlusion Testing - Ray-casts from the midpoint of each edge to determine visibility; edges are hidden if the midpoint depth doesn't match the parent face
-
GPU Hatching - Renders normal buffer to extract regions by facing direction; generates perspective-aware hatch lines that converge toward vanishing points
The main renderer class that generates SVG output from Three.js scenes.
const plotterRenderer = new PlotterRenderer();
// Required setup
plotterRenderer.setSize(width, height);
plotterRenderer.setGLRenderer(glRenderer); // WebGLRenderer instance
// Layer toggles
plotterRenderer.showSilhouettes = true; // Region fills based on normal
plotterRenderer.showEdges = true; // Hidden line edges
plotterRenderer.showHatches = true; // Perspective hatching
// Edge styling
plotterRenderer.edgeOptions = {
stroke: 'white',
strokeWidth: '1px'
};
// Hatch styling
plotterRenderer.hatchOptions = {
stroke: 'black',
strokeWidth: '1px',
baseSpacing: 8,
insetPixels: 2, // Erode hatch boundaries
frameBudgetMs: 16, // Yield to browser every ~16ms (60fps)
progressCallback: (p) => console.log(`${Math.round(p*100)}%`),
axisSettings: {
x: { rotation: 0, spacing: 8 },
y: { rotation: 0, spacing: 8 },
z: { rotation: 0, spacing: 8 }
}
};
// Render (async - returns Promise)
plotterRenderer.clear();
await plotterRenderer.renderGPULayers(scene, camera);// Hidden line computation
import { computeHiddenLinesMultiple } from 'three-plotter-renderer';
const result = computeHiddenLinesMultiple(meshes, camera, scene, options);
// GPU silhouette extraction
import { extractNormalRegions } from 'three-plotter-renderer';
const regions = extractNormalRegions(glRenderer, scene, camera, options);
// Perspective hatching
import { generatePerspectiveHatches } from 'three-plotter-renderer';
const hatches = generatePerspectiveHatches(region, camera, options);
// Path optimization
import { Optimize } from 'three-plotter-renderer';
const optimized = Optimize.optimize(segments);The exported SVG contains these layers (Inkscape-compatible):
| Layer | Description |
|---|---|
silhouettes_layer |
Region fills based on normal direction |
shading_layer |
Perspective hatch lines |
edges_layer |
Visible edge lines (rendered on top) |
For best results:
- β
Use
flatShading: trueon materials for distinct faces - β Use CSG (Constructive Solid Geometry) models
- β Keep faces as square as possible
- β Avoid intersecting geometry
- β Avoid extremely stretched faces
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
MIT Β© Geoff Gaudreault
