Skip to content

New: Add WebGL renderer#109

Merged
AlexIchenskiy merged 10 commits into
release/1.0.0from
new/add-webgl-renderer
Jul 16, 2026
Merged

New: Add WebGL renderer#109
AlexIchenskiy merged 10 commits into
release/1.0.0from
new/add-webgl-renderer

Conversation

@AlexIchenskiy

Copy link
Copy Markdown

This PR introduces an alternative WebGL renderer alongside the existing Canvas renderer, plus a refactor of the layout/simulator engine to support it. The Canvas renderer remains the default, WebGL is fully optional.

The goal is better rendering performance on larger graphs by offloading node/edge/label drawing to the GPU via custom GLSL shaders, and optionally running force-directed layout on the GPU as well.

What's included

  • WebGL renderer (RendererType.WEBGL) — selectable per view, drawn with custom GLSL shaders for nodes, edges, and labels (src/renderer/webgl/).
  • Node images & labels on the GPU — image atlas (image-atlas.ts) and label cache (label-cache.ts) so textures/text can be batched.
  • Improved node/shape geometry options for the WebGL path.
  • GPU force layout engine (gpu-force-layout-engine.ts) — runs the force simulation in WebGL2 with a quadtree/Barnes-Hut approximation. Automatically falls back to the CPU force engine if WebGL2 is unavailable.
  • Layout engine refactor — the old d3-simulator-engine is replaced by a set of pluggable engines (force, circular, grid, hierarchical) behind a factory.

Documentation

Documentation for the WebGL renderer and the new layout engines is still lacking - the APIs may still change while this stabilizes, so docs will be filled in once everything is done and confirmed.

Usage

Opt into the WebGL renderer when creating a view:

const orb = new Orb.OrbView(container, {
  render: { type: 'webgl' },
});

Opt into GPU layout:

const orb = new Orb.OrbView(container, {
  render: { type: 'webgl' },
  layout: { type: 'force', options: { useGPU: true } },
});

Note on stability

This adds a WebGL rendering path, which should be considered experimental and potentially fragile. It depends on GPU/driver behavior and WebGL2 support, so rendering may differ across browsers, GPUs, parameters, and device pixel ratios, and can fail, look different or require cherry-picking for stable results where the Canvas renderer would not. The Canvas renderer remains the stable default and is unchanged in behavior.

@AlexIchenskiy AlexIchenskiy self-assigned this Jun 16, 2026
@AlexIchenskiy AlexIchenskiy changed the base branch from main to release/1.0.0 June 16, 2026 09:17

@tonilastre tonilastre left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really cool! Great job! Btw add yourself to package.json contributors :D

I've added some comments, but mostly nitpicking.

I was playing with the large number of nodes and edges :D Btw if you have some html examples, feel free to add them to server.

Image

Comment thread src/utils/program.utils.ts Outdated

const program = gl.createProgram();
if (!program) {
throw new OrbError('Failed to create program.');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new OrbError('Failed to create program.');
throw new OrbError('Failed to create GL program.');

Having only program seems too generic. Same for the error below.

Comment thread src/renderer/webgl/utils/image-atlas.ts Outdated
Comment on lines +33 to +34
private _dirty = false;
private _textureAllocated = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicking, but do want these to start with _is...

Comment thread src/renderer/webgl/utils/color.utils.ts Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw do you need this file because it is empty?

Comment thread src/renderer/webgl/utils/label-cache.ts Outdated
Comment on lines +8 to +17
export interface LabelAtlasEntry {
u0: number;
v0: number;
u1: number;
v1: number;
pxWidth: number;
pxHeight: number;
}

interface Shelf {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I

Comment thread src/renderer/webgl/utils/label-cache.ts Outdated
Comment on lines +30 to +31
private _dirty = false;
private _textureAllocated = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment as with previous class about boolean vars

super.terminate();

const gl = this._gl;
if (gl) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe an early return here.

@AlexIchenskiy AlexIchenskiy merged commit 617ba93 into release/1.0.0 Jul 16, 2026
2 checks passed
@AlexIchenskiy AlexIchenskiy deleted the new/add-webgl-renderer branch July 16, 2026 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants