README.md

August 24, 2026 · View on GitHub

GoGPU Logo

g3d

Pure Go 3D rendering library
Scene graph, PBR materials, forward renderer. Zero CGO.
Built on gogpu/wgpu (Vulkan/Metal/DX12/GLES/Software).

CI Go Reference Go Report Card License Zero CGO


What is g3d?

g3d is a 3D rendering library — not a game engine. It provides the building blocks (scene graph, cameras, lights, materials, geometry primitives) that game engines, CAD viewers, data visualizers, and AR/VR applications build upon.

Think of it like Three.js for Go: simple API, powerful rendering, zero opinion about your application architecture.

package main

import (
    "log"

    "github.com/gogpu/g3d"
    "github.com/gogpu/gogpu"
)

func main() {
    app := gogpu.NewApp(gogpu.DefaultConfig().
        WithTitle("g3d Hello Cube").
        WithSize(800, 600))

    scene := g3d.NewScene()
    scene.SetBackground(g3d.RGB(0.1, 0.1, 0.15))

    // Ambient light (no spatial properties — attached via UserData on a container node)
    ambient := g3d.NewAmbientLight(g3d.WithLightColor(g3d.White), g3d.WithLightIntensity(0.3))
    ambientNode := g3d.NewNode()
    ambientNode.SetUserData(ambient)
    scene.Add(ambientNode)

    // Directional light (sun-like, from upper-right)
    sun := g3d.NewDirectionalLight(g3d.WithLightColor(g3d.White), g3d.WithLightIntensity(1.0))
    sun.LightNode().SetRotation(g3d.Euler{X: g3d.Radians(-45), Y: g3d.Radians(30)})
    scene.Add(sun.LightNode())

    // Cube mesh with PBR material
    cube := g3d.NewMesh(
        g3d.NewBoxGeometry(1, 1, 1),
        g3d.NewStandardMaterial(
            g3d.WithColor(g3d.RGB(0.4, 0.7, 1.0)),
            g3d.WithRoughness(0.6),
        ),
    )
    scene.Add(cube.MeshNode())

    // Camera
    camera := g3d.NewPerspectiveCamera(75, 800.0/600.0, 0.1, 1000)
    camera.CameraNode().SetPosition(g3d.Vec3{X: 0, Y: 0.5, Z: 3})

    var renderer *g3d.Renderer

    app.OnUpdate(func(dt float64) {
        r := cube.MeshNode().Rotation
        r.Y += float32(dt)
        cube.MeshNode().SetRotation(r)
    })
    app.OnDraw(func(ctx *gogpu.Context) {
        if renderer == nil {
            var err error
            renderer, err = g3d.NewRenderer(app.GPUContextProvider())
            if err != nil {
                log.Fatal(err)
            }
        }
        fbW, fbH := ctx.FramebufferSize()
        renderer.SetSize(uint32(fbW), uint32(fbH))
        if view := ctx.SurfaceView(); view != nil {
            _ = renderer.Render(scene, camera, view)
        }
    })
    app.OnClose(func() {
        if renderer != nil {
            renderer.Release()
        }
    })
    if err := app.Run(); err != nil {
        log.Fatal(err)
    }
}

Features

Core (v0.1.0)

  • Scene graph — hierarchical Node tree with parent-child transform propagation and dirty flags
  • Cameras — Perspective and Orthographic with frustum extraction
  • Geometries — Box, Sphere, Plane + custom BufferGeometry
  • Forward renderer — 4-bucket sorting (background, opaque, transmissive, transparent)
  • Frustum culling — automatic AABB visibility testing against camera frustum

Materials (v0.1.0)

  • BasicMaterial — unlit, for prototyping and data visualization
  • StandardMaterial — PBR metallic-roughness with Blinn-Phong shading

Lighting (v0.1.0)

  • AmbientLight — uniform environment lighting
  • DirectionalLight — sun-like parallel light

Performance (v0.1.0)

  • Zero-alloc render path — no GC pressure during frame rendering
  • Pipeline cache — compile shader variants once, reuse forever
  • 3-key opaque sort — PipelineKey → MaterialID → Distance (minimizes GPU state changes)
  • Persistent GPU buffers — uniform buffers reused across frames with queue.WriteBuffer()

Integration (v0.1.4)

  • GPUView widget — embed 3D viewport inside gogpu/ui applications
  • 2D overlay compositing — fullscreen 3D with gogpu/gg HUD overlay via MarkExternalContent
  • RenderTo — record into caller-owned command encoder for multi-pass composition

Planned

  • Full PBR — Cook-Torrance BRDF, shadow mapping, normal maps (Phase 2)
  • GLTF 2.0 — binary (.glb) and JSON (.gltf) with PBR materials, animations (Phase 3)
  • Instance batching — thousands of objects with minimal draw calls (Phase 4)
  • Post-processing — bloom, tone mapping, FXAA (Phase 4)

Not a Game Engine

g3d deliberately does not include:

FeatureWhy NotWhere to Get It
Entity Component SystemGame engine concernBuild on top, or use external ECS
PhysicsSimulation concernIntegrate Bullet, ODE, or Pure Go physics
AudioUnrelated to renderingUse gogpu/audio or Oto
NetworkingUnrelated to renderingUse net/http, gRPC, WebSocket
ScriptingEngine concernUse Lua/Wasm/Yaegi on top
Scene editorTool concernBuild with gogpu/ui + g3d

This separation means g3d is reusable everywhere — game engines, CAD tools, scientific visualizations, AR/VR, data dashboards.

GPU Backends

g3d renders through gogpu/wgpu, which supports:

BackendPlatformsStatus
VulkanWindows, LinuxStable
MetalmacOSStable
DirectX 12WindowsStable
OpenGL ESWindows, LinuxStable
SoftwareAllFallback (CI/testing)

All backends are Pure Go — zero CGO, single binary deployment.

# Select backend via environment variable
GOGPU_GRAPHICS_API=vulkan   go run ./examples/hello-cube/
GOGPU_GRAPHICS_API=dx12     go run ./examples/hello-cube/
GOGPU_GRAPHICS_API=software go run ./examples/hello-cube/

Examples

ExampleDescription
hello-cubeRotating PBR cube — minimal g3d + gogpu integration
gopherGo Gopher mascot from primitives — scene graph grouping, multiple materials
fullscreen-overlayFullscreen 3D scene with 2D HUD overlay (g3d + gg)
viewport3d3D viewport embedded inside gogpu/ui application

Integration

g3d is designed to compose with the gogpu ecosystem — embed 3D in UI apps, overlay 2D on 3D, or use standalone.

Embedded 3D widget (g3d + ui)

Render 3D content inside a gogpu/ui widget using the GPUView widget. The renderer draws into an offscreen GPU texture that the ui compositor blits into the widget tree.

vp := gpuview.New(
    gpuview.Size(600, 400),
    gpuview.Continuous(true),
    gpuview.OnRender(func(view gpucontext.TextureView) {
        wgpuView := (*wgpu.TextureView)(view.Pointer())
        renderer.Render(scene, camera, wgpuView)
    }),
)

See examples/viewport3d for a complete working example.

Fullscreen 3D + 2D overlay (g3d + gg)

Render a 3D scene full-window, then draw 2D HUD elements on top with gogpu/gg. Uses the enterprise multi-pass pattern (Unity, Bevy+egui, ImGui): 3D pass with LoadOp::Clear, then 2D pass with LoadOp::Load.

app.OnDraw(func(dc *gogpu.Context) {
    renderer.Render(scene, camera, dc.SurfaceView())
    dc.MarkExternalContent()
    canvas.Draw(func(cc *gg.Context) { /* HUD elements */ })
    canvas.Render(dc.RenderTarget())
})

See examples/fullscreen-overlay for a complete working example with FPS counter, crosshair, and status bar.

Shared command encoder (RenderTo)

Record g3d render passes into a caller-owned command encoder for single-submit composition with other renderers:

encoder, _ := device.CreateCommandEncoder(nil)
renderer.RenderTo(encoder, scene, camera, targetView)
// Record additional passes...
commands, _ := encoder.Finish()
queue.Submit(commands)

Standalone Usage

g3d works without the gogpu application framework. Bring your own window and GPU device:

// Use g3d with any wgpu.Device — no gogpu dependency required
renderer, err := g3d.NewRendererFromDevice(device, queue, surfaceFormat)

scene := g3d.NewScene()
// ... build your scene
renderer.Render(scene, camera, targetView)

To combine g3d with additional render passes in one queue submission, record into a caller-owned command encoder:

encoder, err := device.CreateCommandEncoder(nil)
if err != nil {
	return err
}
if err := renderer.RenderTo(encoder, scene, camera, targetView); err != nil {
	encoder.DiscardEncoding()
	return err
}
// Record other render passes into encoder here.
commands, err := encoder.Finish()
if err != nil {
	return err
}
_, err = queue.Submit(commands)
return err

Architecture

Your Application (game engine, CAD viewer, data viz, AR/VR)
         |
    gogpu/g3d  — Scene Graph + Materials + Render Pipeline
         |
    gogpu/wgpu — Pure Go WebGPU (Vulkan/Metal/DX12/GLES/Software)
         |
    gogpu/naga — Shader Compiler (WGSL → SPIR-V/MSL/GLSL/HLSL)

g3d depends down (wgpu, naga), never up (gogpu, gg, ui). This ensures it can be used in any context.

See docs/ARCHITECTURE.md for full architecture documentation.

Installation

go get github.com/gogpu/g3d

Requirements: Go 1.25+

Roadmap

PhaseFeaturesStatus
Phase 1Scene graph, cameras, materials, box/sphere/plane, forward rendererComplete
Phase 2Full PBR (Cook-Torrance), shadows, normal maps, texturesPlanned
Phase 3GLTF 2.0 loader, skeletal animation, morph targetsPlanned
Phase 4Instance batching, environment maps, post-processing, skyboxPlanned
Phase 5Frustum culling BVH, LOD, SIMD mathPlanned

Design Principles

  1. Simple API — rotating lit cube in ~20 lines. Progressive complexity.
  2. Zero CGO — Pure Go on all platforms. Single binary deployment.
  3. Reusable — rendering library, not a framework. No opinions about your architecture.
  4. PBR from day one — metallic-roughness workflow, GLTF standard.
  5. Zero-alloc rendering — no GC pressure in the hot path.
  6. All GPU backends — Vulkan, Metal, DX12, GLES, Software through wgpu.

Contributing

See CONTRIBUTING.md for development workflow, code standards, and priority areas.

Part of the GoGPU Ecosystem

g3d is part of GoGPU — a Pure Go GPU ecosystem with 1.25M+ lines of code.

LibraryPurpose
gogpuApplication framework, windowing
wgpuPure Go WebGPU (Vulkan/Metal/DX12/GLES)
nagaShader compiler (WGSL → SPIR-V/MSL/GLSL/HLSL)
gg2D graphics with GPU acceleration
g3d3D rendering (this library)
uiGUI toolkit (22+ widgets, 4 themes)
systraySystem tray (Win32/macOS/Linux)
audioPure Go audio engine (WASAPI)

Star History

Star History Chart

License

MIT License — see LICENSE for details.