Namespace internalInternal

WebGLRenderer Internals


Internal documentation for xeokit developers



This module documents the internal architecture of xeokit’s WebGL2 rendering backend. It is intended for contributors and maintainers of the renderer, not for public API usage.

The WebGLRenderer follows SOLID principles and is structured as a hierarchy of specialized managers, each responsible for a clearly defined aspect of the rendering pipeline.


The public WebGLRenderer owns a set of high-level facilities and a single internal ViewManager, which coordinates all rendering work.

WebGLRenderer
├── Capabilities -- Read-only, describes WebGL2 capabilities
├── MemoryUsage -- Memory usage info
├── MemoryConfigs -- GPU memory budgeting configs
├── WebGLRendererEvents -- Renderer lifecycle and error events
└── internal
    ├── ViewManager -- Internal coordinator for per-View rendering
    ├── MeshManager -- Manages mesh batching and renderer-side representations
    ├── GPUMemoryManager -- Manages GPU-resident memory
    ├── RenderManager -- Executes the render pipeline
    ├── PickManager -- Manages GPU picking
    ├── DrawOps -- Low-level WebGL draw infrastructure
    └── inspectors -- Diagnostics and runtime inspection utilities

The following class diagram shows the main internal components and how they interact. Ownership relationships are shown as compositions, while data flow and notifications are shown as directed associations.



%%{init:{"theme":"dark"}}%% classDiagram Scene *--> SceneEvents : emits Viewer --> SceneEvents : subscribes Viewer *--> ViewerEvents : emits WebGLRenderer --> ViewerEvents : subscribes WebGLRenderer:memoryConfigs WebGLRenderer:memoryUsage WebGLRenderer:memoryInspector WebGLRenderer:shaderInspector WebGLRenderer:drawInspector WebGLRenderer:events WebGLRenderer:viewer Viewer:scene Viewer o--> Scene: attached WebGLRenderer o--> Viewer: attached WebGLRenderer --> SceneEvents : subscribes WebGLRenderer *--> ViewManager : delegates ViewManager *--> MeshManager : scene & view changes MeshManager *--> GPUMemoryManager : write ViewManager *--> RenderManager : repaint ViewManager *--> PickManager : pick MeshManager *--> "*" MeshBatchImpl MeshBatchImpl *--> "*" RendererObject MeshBatchImpl *--> "*" RendererMesh MeshBatchImpl *--> "*" RendererGeometry RendererGeometry --> GPUMemoryManager : write RendererObject --> GPUMemoryManager : write GPUMemoryManager *--> DataTextures RenderManager --> DrawOps : draw PickManager --> DrawOps : pick DrawOps *--> "*" RenderPassDrawOps RenderPassDrawOps *--> "*" DrawOp DrawOp *--> DrawTechnique DrawOp --> MeshBatchImpl : draw DrawOp:drawBatch() RendererMesh --> GPUMemoryManager : write DrawTechnique --> DataTextures : bind/read WebGLRendererEvents <--* WebGLRenderer : emits WebGLRendererEvents:onError() WebGLRendererEvents:onWebGLContextLost() WebGLRendererEvents:onWebGLContextRestored() WebGLRendererEvents:onViewerAttached() WebGLRendererEvents:onViewerDetached() WebGLRendererEvents:onRendererStarted() WebGLRendererEvents:onRendererStopped() WebGLRendererEvents:onRendererDestroyed()
%%{init:{"theme":"default"}}%% classDiagram Scene *--> SceneEvents : emits Viewer --> SceneEvents : subscribes Viewer *--> ViewerEvents : emits WebGLRenderer --> ViewerEvents : subscribes WebGLRenderer:memoryConfigs WebGLRenderer:memoryUsage WebGLRenderer:memoryInspector WebGLRenderer:shaderInspector WebGLRenderer:drawInspector WebGLRenderer:events WebGLRenderer:viewer Viewer:scene Viewer o--> Scene: attached WebGLRenderer o--> Viewer: attached WebGLRenderer --> SceneEvents : subscribes WebGLRenderer *--> ViewManager : delegates ViewManager *--> MeshManager : scene & view changes MeshManager *--> GPUMemoryManager : write ViewManager *--> RenderManager : repaint ViewManager *--> PickManager : pick MeshManager *--> "*" MeshBatchImpl MeshBatchImpl *--> "*" RendererObject MeshBatchImpl *--> "*" RendererMesh MeshBatchImpl *--> "*" RendererGeometry RendererGeometry --> GPUMemoryManager : write RendererObject --> GPUMemoryManager : write GPUMemoryManager *--> DataTextures RenderManager --> DrawOps : draw PickManager --> DrawOps : pick DrawOps *--> "*" RenderPassDrawOps RenderPassDrawOps *--> "*" DrawOp DrawOp *--> DrawTechnique DrawOp --> MeshBatchImpl : draw DrawOp:drawBatch() RendererMesh --> GPUMemoryManager : write DrawTechnique --> DataTextures : bind/read WebGLRendererEvents <--* WebGLRenderer : emits WebGLRendererEvents:onError() WebGLRendererEvents:onWebGLContextLost() WebGLRendererEvents:onWebGLContextRestored() WebGLRendererEvents:onViewerAttached() WebGLRendererEvents:onViewerDetached() WebGLRendererEvents:onRendererStarted() WebGLRendererEvents:onRendererStopped() WebGLRendererEvents:onRendererDestroyed()
classDiagram
    Scene *--> SceneEvents : emits
    Viewer --> SceneEvents : subscribes
    Viewer *--> ViewerEvents : emits
    WebGLRenderer --> ViewerEvents : subscribes
    WebGLRenderer:memoryConfigs
    WebGLRenderer:memoryUsage
    WebGLRenderer:memoryInspector
    WebGLRenderer:shaderInspector
    WebGLRenderer:drawInspector
    WebGLRenderer:events
    WebGLRenderer:viewer
    Viewer:scene
    Viewer o--> Scene: attached
    WebGLRenderer o--> Viewer: attached
    WebGLRenderer --> SceneEvents : subscribes
    WebGLRenderer *--> ViewManager : delegates
    ViewManager *--> MeshManager : scene & view changes
    MeshManager *--> GPUMemoryManager : write
    ViewManager *--> RenderManager : repaint
    ViewManager *--> PickManager : pick
    MeshManager *--> "*" MeshBatchImpl
    MeshBatchImpl *--> "*" RendererObject
    MeshBatchImpl *--> "*" RendererMesh
    MeshBatchImpl *--> "*" RendererGeometry
    RendererGeometry --> GPUMemoryManager : write
    RendererObject --> GPUMemoryManager : write
    GPUMemoryManager *--> DataTextures
    RenderManager --> DrawOps : draw
    PickManager --> DrawOps : pick
    DrawOps *--> "*" RenderPassDrawOps
    RenderPassDrawOps *--> "*" DrawOp
    DrawOp *--> DrawTechnique
    DrawOp --> MeshBatchImpl : draw
    DrawOp:drawBatch()
    RendererMesh --> GPUMemoryManager : write
    DrawTechnique --> DataTextures : bind/read
    WebGLRendererEvents <--* WebGLRenderer : emits
    WebGLRendererEvents:onError()
    WebGLRendererEvents:onWebGLContextLost()
    WebGLRendererEvents:onWebGLContextRestored()
    WebGLRendererEvents:onViewerAttached()
    WebGLRendererEvents:onViewerDetached()
    WebGLRendererEvents:onRendererStarted()
    WebGLRendererEvents:onRendererStopped()
    WebGLRendererEvents:onRendererDestroyed()



  • MeshManager
  • Translates scene and view changes into GPU-ready render state.
  • Owns renderer-side representations:
  • Maintains mesh batches for efficient draw submission.
  • Coordinates GPU updates with GPUMemoryManager.

  • GPUMemoryManager
  • Allocates, updates, and releases all GPU-resident memory.
  • Manages geometry buffers, attributes, and DataTextures.
  • Implements the tiled RTC (Relative To Center) coordinate system for high-precision rendering.
  • Provides diagnostics and inspection APIs.

  • RenderManager
  • Executes the render pipeline for the active View.
  • Manages render passes, frame state, and draw submission.
  • Integrates mesh batches and GPU memory into per-frame rendering.
  • Handles WebGL context restoration.

  • PickManager
  • Manages GPU-backed picking resources.
  • Performs object hit-testing via screen-space or ray-based picking.
  • Shares mesh batches and GPU memory infrastructure with rendering.

Low-level WebGL2 draw infrastructure used by both rendering and picking.

  • DrawTechnique

    • Abstract rendering technique.
    • Defines shader generation, program setup, uniform loading, and draw calls.
    • Subclasses implement specific techniques (color, highlight, x-ray, etc.) for specific primitive types.
  • DrawOp

  • RenderPassDrawOps

    • Collection of DrawOp instances for all render passes of a single primitive type.
  • DrawOps

    • Complete set of draw operations for all primitive types.
  • getDrawOps / putDrawOps

    • Internal pooling APIs for caching and reusing DrawOps instances.


The WebGLRenderer provides read-only diagnostics APIs for inspecting all GPU-resident renderer state. These APIs are intended for debugging, profiling, and validation by xeokit developers, and are not part of the public API surface.


  • MemoryUsage via WebGLRenderer.getMemoryUsage

    • Returns high-level GPU memory statistics: allocated and used memory in MB/KB.
    • Example:
      const usage = webglRenderer.getMemoryUsage();
      console.log(`GPU: ${usage.usedMB} MB used of ${usage.allocatedMB} MB allocated`);
  • MemoryInspector via WebGLRenderer.getMemoryInspector

    • Provides a structured, read-only view of all GPU-resident data textures and their contents.
    • Allows mapping between GPU indices and scene objects/geometries.
    • Example:
      const inspector = webglRenderer.getMemoryInspector();
      const mesh = inspector.getMeshAtIndex(batchIndex, meshIndex);
      const geometry = inspector.getGeometryAtIndex(batchIndex, geometryIndex);
      const dataTextures = inspector.dataTextures;
    • See inspectors/MemoryInspector for a detailed usage example.

The WebGLRenderer exposes read-only APIs for inspecting the generated WebGL shader programs and techniques.

  • ShaderInspector via WebGLRenderer.getShaderInspector
    • Provides structured access to all shader source code used by the renderer, organized by primitive type and render pass.
    • Example:
      const shaderInspector = webglRenderer.getShaderInspector();
      const src = shaderInspector.techniques.triangles.opaque.vertexSrc;
      console.log("Opaque triangles vertex shader:", src);
    • See inspectors/ShaderInspector for details.

The WebGLRenderer includes a Draw List Inspector for logging and analyzing all draw calls issued during rendering.

  • DrawInspector via WebGLRenderer.getDrawInspector
    • Captures detailed information about each rendered frame, including draw calls, primitive types, shader techniques, batch and pass details, and timing.
    • Provides per-frame logs and frame rate statistics for each view.
    • Example:
      const drawInspector = webglRenderer.getDrawInspector();
      drawInspector.enabled = true;
      // After rendering:
      const frameLog = drawInspector.frameLogs[viewIndex];
      console.log(JSON.stringify(frameLog, null, 2));
    • See inspectors/DrawInspector and related types for log structure.


The following selected workflows help illustrate how the core components interact during key operations.


This is when the WebGLRenderer gets initialized, ready for action.

  1. Viewer is created.
  2. WebGLRenderer.attach(viewer)
  3. WebGLRenderer initializes rendering state for the Viewer.
  4. WebGLRenderer creates a ViewManager for the Viewer.
  5. ViewManager initializes:
    • MeshManager
    • GPUMemoryManager
    • RenderManager
    • PickManager
  6. WebGLRenderer subscribes to Viewer and Scene events.
  7. Viewer is now ready for rendering.

Whenever geometries are created, they get pre-loaded into the renderer.

  1. A SceneGeometry is created in the Scene.
  2. WebGLRenderer is notified via SceneEvents.onGeometryCreated.
  3. ViewManager.sceneGeometryCreated(sceneGeometry)
  4. MeshManager.sceneGeometryCreated(sceneGeometry)
  5. MeshManager creates a RendererGeometry instance for the SceneGeometry.
  6. RendererGeometry requests GPU memory allocation: GPUMemoryManager.createGeometryBuffers()
  7. GPUMemoryManager allocates buffers and uploads geometry data.
  8. RendererGeometry is ready for use by subsequently-created RendererMesh instances.

Whenever meshes are created, they get loaded into the renderer, and are attached to RendererMesh instances.

  1. A SceneMesh is created in the Scene.
  2. WebGLRenderer is notified via SceneEvents.onSceneMeshCreated.
  3. ViewManager.sceneMeshCreated(sceneMesh)
  4. MeshManager.sceneMeshCreated(sceneMesh)
  5. MeshManager creates a RendererMesh instance for the SceneMesh.
  6. MeshManager requests GPU memory allocation: GPUMemoryManager.createBatch()
  7. GPUMemoryManager allocates buffers and uploads geometry data.
  8. MeshManager adds RendererMesh to MeshBatch.
  9. RendererMesh is ready for use by any subsequently-created RendererObject.

Whenever SceneObjects are created, they automatically get loaded into the Viewer and the WebGLRenderer.

  1. A SceneObject is created in the Scene.
  2. Viewer is notified via SceneEvents.onSceneObjectCreated.
  3. The Viewer creates a ViewObject in each existing View for the SceneObject.
  4. WebGLRenderer is also notified via SceneEvents.onSceneObjectCreated.
  5. ViewManager.sceneObjectCreated(sceneObject)
  6. MeshManager.sceneObjectCreated(sceneObject)
  7. MeshManager finds pre-created RendererMesh instances for each of the SceneObject's SceneMeshes (see SceneMesh Creation).
  8. MeshManager creates a RendererObject and links it to the RendererMesh instances.
  9. On the next render, the new object will appear in the view.

Whenever SceneObjects are deleted, they get automatically get unloaded from the Viewer and the WebGLRenderer. The RendererMesh and RendererObject instances are not unloaded immediately, but are instead kept in memory for potential reuse. This is actually a useful way to cache content for any objects that repeatedly get created and destroyed.

  1. A SceneObject is destroyed.
  2. Viewer is notified via SceneEvents.onSceneObjectDestroyed.
  3. The Viewer destroys the corresponding ViewObject.
  4. WebGLRenderer is notified of deletion.
  5. ViewManager.sceneObjectDestroyed(sceneObject)
  6. MeshManager.sceneObjectDestroyed(sceneObject)
  7. MeshManager destroys corresponding RendererObject.
  8. MeshManager notifies GPUMemoryManager to release GPU memory.
  9. GPUMemoryManager releases GPU memory used by the object.
  10. On the next render, the object will no longer appear in the view.

Whenever a ViewObject's visibility is changed, the renderer updates the visibility state in GPU memory, so that only visible objects are rendered.

  1. The visibility of a ViewObject is changed in a View.
  2. WebGLRenderer is notified via ViewEvents.onViewObjectVisibilityChanged.
  3. ViewManager.viewObjectVisibilityChanged(viewObject)
  4. MeshManager.viewObjectVisibilityChanged(viewObject)
  5. MeshManager marks the RendererObject as visible/invisible, which updates the visibility states of its RendererMesh instances, which each their visibility states to GPUMemoryManager.
  6. On next render, the object will be rendered or skipped based on its visibility.

Whenever a SceneMesh's matrix is updated, the renderer updates the matrix data in GPU memory.

  1. The matrix of a SceneMesh is updated in the Scene.
  2. WebGLRenderer is notified via SceneEvents.onSceneMeshMatrixUpdated.
  3. ViewManager.sceneMeshMatrixChanged(sceneMesh)
  4. MeshManager.sceneMeshMatrixChanged(sceneMesh)
  5. MeshManager updates matrix data in GPUMemoryManager.
  6. GPUMemoryManager uploads updated matrix to GPU.
  7. On next render, the mesh will be transformed using the updated matrix.

Whenever a SceneMesh's color is updated, the renderer updates the color data in GPU memory.

  1. The color of a SceneMesh is updated in the Scene.
  2. WebGLRenderer is notified via SceneEvents.onSceneMeshColorUpdated.
  3. ViewManager.sceneMeshColorChanged(sceneMesh)
  4. MeshManager.sceneMeshColorChanged(sceneMesh)
  5. MeshManager updates color data in GPUMemoryManager.
  6. GPUMemoryManager uploads updated color to GPU.
  7. On next render, the mesh will be rendered using the updated color.

When a View signals that it's been updated, the renderer re-renders the View. All the minor updates that have happened (such as object visibility changes, matrix updates, color updates etc) are already reflected in GPU memory, so the renderer can just go ahead and render the current state.

  1. A View signals that it's "updated", meaning that it has a batch of minor updates to render.
  2. WebGLRenderer is notified via ViewerEvents.onViewUpdated.
  3. ViewManager initiates render via RenderManager.render.
  4. RenderManager retrieves visible RendererObjects from MeshManager.
  5. RenderManager sets up render passes and state.
  6. RenderManager issues draw calls using DrawOps for each visible RendererObject.
  7. Frame is rendered to the canvas.

When a user initiates a picking operation (e.g., clicking on the canvas), the renderer performs GPU-based picking to identify the selected object.

The rationale for implementing picking via the WebGLRenderer API, and not via the Viewer API (which would really be semantically nicer), is because we need the renderer's GPU resources to perform picking, and we don't want to do it using the renderer through the Viewer (like a facade), because the Viewer needs to remain agnostic of the renderer.

  1. User initiates picking on a View canvas.
  2. WebGLRenderer.pick(...) is called.
  3. ViewManager delegates to PickManager.
  4. PickManager sets up picking render targets and state.
  5. PickManager issues draw calls using DrawOps to render to picking buffer.
  6. PickManager reads picking results from GPU.
  7. PickManager identifies picked ViewObject and notifies WebGLRenderer.
  8. WebGLRenderer.pick returns result to caller.
  9. Caller can find picked SceneObject via ViewObject.

Namespaces

drawOps
gpuMemoryManager
inspectors
meshManager
pickManager
renderManager

Classes

RenderBuffers
RenderContext
ViewManager
ViewRenderState

Type Aliases

RenderPassValue

Variables

RENDER_BINS
RENDER_PASSES