cosmosgl/graph

GPU-accelerated force graph layout and rendering

TypeScript

1,295

779 commits

updated Oct 12, 2026

See the code

README

cosmos.gl logo

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.

๐Ÿ“บ Comparison with other libraries

๐ŸŽฎ Check out our storybook for examples


Quick Start

Install the package:

npm install @cosmos.gl/graph

Note: luma.gl (@luma.gl/core, @luma.gl/engine, @luma.gl/shadertools, @luma.gl/webgl, compatible range ~9.3.0) is a peer dependency. npm 7+ installs it automatically; with Yarn, or pnpm configurations that skip auto-installing peers, add the four packages explicitly at ~9.3.0 โ€” a bare install gets a newer luma.gl. Keeping luma.gl as a peer lets cosmos.gl share one luma.gl installation โ€” and one GPU Device โ€” with hosts like deck.gl.

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()

What's New in v3.0?

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.

What's New in v2.0?

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.


Examples


Showcase (via cosmograph.app)


Known Issues

  • 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.

Documentation


License

MIT


Contact

GitHub Discussions

embeddings
force
graph
network
simulation
visualization
webgl

cosmosgl/graph

GPU-accelerated force graph layout and rendering

TypeScript

1,295

779 commits

updated Oct 12, 2026

See the code

README

cosmos.gl logo

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.

๐Ÿ“บ Comparison with other libraries

๐ŸŽฎ Check out our storybook for examples


Quick Start

Install the package:

npm install @cosmos.gl/graph

Note: luma.gl (@luma.gl/core, @luma.gl/engine, @luma.gl/shadertools, @luma.gl/webgl, compatible range ~9.3.0) is a peer dependency. npm 7+ installs it automatically; with Yarn, or pnpm configurations that skip auto-installing peers, add the four packages explicitly at ~9.3.0 โ€” a bare install gets a newer luma.gl. Keeping luma.gl as a peer lets cosmos.gl share one luma.gl installation โ€” and one GPU Device โ€” with hosts like deck.gl.

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()

What's New in v3.0?

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.

What's New in v2.0?

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.


Examples


Showcase (via cosmograph.app)


Known Issues

  • 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.

Documentation


License

MIT


Contact

GitHub Discussions

embeddings
force
graph
network
simulation
visualization
webgl

Significant stargazers

(top 24 of 28)

Volodymyr Agafonkin

6,260 followers ยท starred Jul 2026

Paul Taylor

639 followers ยท starred Sep 2022

Ash Vardanian

1,452 followers ยท starred Mar 2024

Max Graey

338 followers ยท starred Jul 2026