GPU-accelerated Force Graph
cosmos.gl is a high-performance WebGL Force Graph algorithm and rendering engine. All the computations and drawing occur on the GPU in fragment and vertex shaders, avoiding expensive memory operations. It enables the real-time simulation of network graphs consisting of hundreds of thousands of points and links on modern hardware.
This engine powers 🪐 Cosmograph — a toolset for exploring complex networks and AI embeddings.
cosmos-reel-720p.mp4
📺 Comparison with other libraries
🎮 Check out our storybook for examples
Install the package:
npm install @cosmos.gl/graph
Get the data, configure the graph and run the simulation:
import { Graph } from '@cosmos.gl/graph'
const div = document.querySelector('div')
const config = {
spaceSize: 4096,
simulationFriction: 0.1, // keeps the graph inert
simulationGravity: 0, // disables the gravity force
simulationRepulsion: 0.5, // increases repulsion between points
curvedLinks: true, // curved links
fitViewOnInit: true, // fit the view to the graph after initialization
fitViewDelay: 1000, // wait 1 second before fitting the view
fitViewPadding: 0.3, // centers the graph with a padding of ~30% of screen
rescalePositions: false, // rescale positions, useful when coordinates are too small
enableDrag: true, // enable dragging points
onClick: (pointIndex) => { console.log('Clicked point index: ', pointIndex) },
/* ... */
}
const graph = new Graph(div, config)
// Points: [x1, y1, x2, y2, x3, y3]
const pointPositions = new Float32Array([
0.0, 0.0, // Point 1 at (0,0)
1.0, 0.0, // Point 2 at (1,0)
0.5, 1.0, // Point 3 at (0.5,1)
]);
graph.setPointPositions(pointPositions)
// Links: [sourceIndex1, targetIndex1, sourceIndex2, targetIndex2]
const links = new Float32Array([
0, 1, // Link from point 0 to point 1
1, 2, // Link from point 1 to point 2
2, 0, // Link from point 2 to point 0
]);
graph.setLinks(links)
graph.render()
cosmos.gl v3.0 brings a new rendering engine, async initialization, and several new features:
- luma.gl (WebGL 2) — rendering ported from regl to luma.gl, with support for sharing a custom Device across multiple graphs via new Graph(div, config, devicePromise).
- Async initialization — the constructor returns immediately; all public methods queue until the device is ready. Use graph.ready / graph.isReady to know when the graph is usable.
- Simulation control — rendering is now separate from simulation. The simulation starts automatically by default; use start(), stop(), pause(), and unpause() to control it independently.
- Link sampling — sample visible links on screen with getSampledLinks() and getSampledLinkPositionsMap() for rendering labels or overlays along links.
- Touch and pen support — tap, drag, and pinch-to-zoom on phones and tablets. Long-press (~500 ms) triggers context menu callbacks. onMouseMove and all click callbacks fire from touch input.
- Context menu support — new callbacks for right-click on desktop and long-press on touch/pen: onContextMenu, onPointContextMenu, onLinkContextMenu, onBackgroundContextMenu.
- Fit viewport to points — setZoomTransformByPointPositions() zooms and pans to fit a set of points into view.
- Config-driven highlighting — imperative selection methods replaced by highlightedPointIndices, highlightedLinkIndices, and outlinedPointIndices config properties. Points and links are highlighted independently. Focused links are rendered wider via focusedLinkIndex / focusedLinkWidthIncrease. New findPointsInRect(), findPointsInPolygon(), getNeighboringPointIndices(), getConnectedLinkIndices(), and getConnectedPointIndices() methods.
- Link blending control — linkBlending: false disables alpha blending for significantly faster link rendering on dense graphs.
- Hover improvements — onPointMouseOver now includes isHighlighted and isOutlined parameters; hover correctly highlights the topmost point when points overlap.
- Config API changes — setConfig() now resets all values to defaults before applying; use the new setConfigPartial() to update individual properties without resetting the rest.
- Init-only config fields — initialZoomLevel, randomSeed, and attribution can only be set during initialization and are preserved across config updates.
- Runtime simulation toggle — enableSimulation can now be changed at runtime via setConfig() or setConfigPartial().
- GPU transitions — point positions, point colors/sizes, and link colors/widths now animate by default (transitionDuration: 800, transitionEasing: TransitionEasing.CubicInOut). Use transitionDuration: 0 to keep snap updates.
- Transition callbacks — use onTransitionStart, onTransition, and onTransitionEnd to track transition lifecycle and progress.
- Default point shape — new pointDefaultShape config property lets you set the fallback shape for all points when no per-point shapes are provided. Accepts a PointShape enum value (e.g., PointShape.Star), a plain number (e.g., 6), or a numeric string (e.g., "6").
- Collision force — new GPU-accelerated collision force keeps points from overlapping, using a spatial-hash grid that scales to large graphs. Enable it with simulationCollision, and tune the spacing with simulationCollisionRadius (fixed radius vs. size-derived) and simulationCollisionPadding (extra gap between points). See the Collision example.
- Exported defaults — defaultConfigValues is now part of the public API.
- Optimized hover detection — skips GPU work when the mouse hasn't moved.
Check the Migration Guide for upgrading from v2.
cosmos.gl v2.0 introduces significant improvements in performance and data handling:
- Enhanced data structures with WebGL-compatible formats.
- Methods like setPointPositions and setLinks replace setData for improved efficiency.
- Direct control over point and link attributes via Float32Array (e.g., colors, sizes, widths).
- Updated event handling based on indices instead of objects.
- New Point Clustering force (setPointClusters, setClusterPositions and setPointClusterStrength).
- Ability to drag points.
Check the Migration Guide for upgrading from v1.
- Starting from version 15.4, iOS has stopped supporting the key WebGL extension powering our Many-Body force implementation (EXT_float_blend). We're investigating this issue and exploring solutions. The latest iOS works again!
- cosmos.gl doesn't work on Android devices that don't support the OES_texture_float WebGL extension.
MIT
GitHub Discussions