Oxy Engine
A 3D game engine written in pure Go, powered by WebGPU via cogentcore/webgpu.
go get github.com/Carmen-Shannon/oxy-go
Go 1.25.6+ required.
Overview
Oxy is a forward-rendering 3D engine built from scratch in Go. It uses WebGPU for GPU access and GLFW for windowing, with no CGo wrappers beyond those two dependencies. The engine is designed around a modular, interface-first architecture using the option-builder pattern throughout.
Key Features
- Forward+ Rendering — Tiled light culling compute pass followed by a lit forward render pass.
- Skeletal Animation — GPU-driven skeletal animation via compute shaders with bone blending, channel interpolation, and indirect draw.
- Shadow Mapping — Depth-only shadow passes with PCF sampling and configurable shadow uniforms.
- glTF Loader — Full glTF 2.0 import pipeline: meshes, materials, skeletons, and animations.
- WGSL Shader Annotations — A custom pre-processor that embeds resource metadata directly in WGSL source files, enabling declarative GPU resource wiring with zero string-based lookups at runtime. See the Annotation System Documentation.
- Scene Graph — Scenes manage cameras, lights, game objects, pipelines, shaders, and bind group providers in a single composable unit.
- Profiler — Built-in frame timing profiler for engine tick, render, and per-phase metrics.
Architecture
engine/
├── camera/ Camera, CameraController, GPU uniform types
├── game_object/ GameObject with transform, model, and animation state
├── light/ Point/directional lights, shadow maps, forward+ tile culling
├── loader/ glTF 2.0 importer (meshes, materials, skeletons, animations)
├── model/ Model, Mesh, GPU vertex types, instance data
├── physics/ GPU-accelerated rigid body physics (DEM)
├── profiler/ Frame timing profiler
├── renderer/
│ ├── animator/ GPU compute animation backends (simple + skeletal)
│ ├── bind_group_provider/ Bind group creation and buffer writes
│ ├── material/ Material GPU types (overlay, effect params)
│ ├── pipeline/ Render and compute pipeline management
│ └── shader/ Shader loading, WGSL parsing, annotation pre-processor
├── scene/ Scene graph, draw calls, compute dispatch, resource wiring
└── window/ GLFW window abstraction
common/ Shared types, math utilities, key codes, frustum culling
Quick Start
The repository includes several runnable example scenes in the examples directory:
| File |
Description |
scene.go |
Basic unlit scene with a rotating cube |
scene_fox.go |
Animated fox model with skeletal animation |
scene_lit.go |
Full forward+ lit scene with shadows and multiple lights |
physics_scene.go |
Physics simulation with rigid bodies and lighting |
Run any example with:
go run examples/scene_lit.go
Minimal Example
package main
import (
"github.com/Carmen-Shannon/oxy-go/engine"
"github.com/Carmen-Shannon/oxy-go/engine/window"
)
func main() {
eng := engine.NewEngine(
engine.WithProfiler(true), // profiler option
engine.WithTickRate(60), // engine tick rate in hz
engine.WithWindow(window.NewWindow(
window.WithTitle("Oxy Engine"),
window.WithWidth(1280),
window.WithHeight(720),
)),
)
eng.SetTickCallback(func(dt float32) {
// game logic here
})
eng.SetRenderCallback(func(dt float32) {
// render calls here
})
eng.Run()
}
Design Principles
Option-Builder Pattern
All constructors use variadic functional options instead of config structs:
ctrl := camera.NewCameraController(
camera.WithTarget(0, 0, 0),
camera.WithRadius(5),
camera.WithElevation(0.4),
)
cam := camera.NewCamera(
camera.WithFov(45.0 * (math.Pi / 180.0)),
camera.WithAspect(16.0 / 9.0),
camera.WithController(ctrl),
)
Interface-First
Every major system exposes an interface backed by an unexported struct. Compile-time checks enforce implementation compliance:
var _ Renderer = &renderer{}
Shader Annotations
WGSL shaders use @oxy: annotations to declare their resource requirements directly in the shader source. The engine's Scene reads these declarations at load time to wire GPU bind groups automatically. See README_ANNOTATIONS.md for the full specification.
Testing
Running Tests
Run the full test suite with coverage across the common and engine packages:
go test ./tests/... -coverpkg="github.com/Carmen-Shannon/oxy-go/common/...,github.com/Carmen-Shannon/oxy-go/engine/..." -coverprofile="coverage.out"
Then view the per-function coverage report:
go tool cover -func="coverage.out"
Generating Mocks
Test mocks are generated with vektra/mockery (v2.53.5+). The configuration lives in .mockery.yaml at the project root.
Install mockery:
go install github.com/vektra/mockery/[email protected]
Then regenerate all mocks from the project root:
mockery
Mockery reads .mockery.yaml automatically and writes generated mocks to tests/mocks/.
Documentation
The engine package is the main entrypoint of oxy-go. It represents the highest-level instance of the engine itself — the single object that owns the window, manages scenes by z-index, and drives all render and game logic through its concurrent tick and render loops.
- Common — Shared types, math utilities (matrix ops, projection, byte conversions), frustum culling, virtual key codes, and generic helpers.
- Engine — Engine interface, tick/render loops, scene management, profiling, builder options, and shutdown lifecycle.
- Camera System — Camera and CameraController interfaces, builder options, orbit/planar controls, and GPU uniform types.
- GameObject System — GameObject interface, builder options, transform lifecycle, and light attachment.
- Light System — Light types, Forward+ tile culling, shadow mapping, GPU types, and builder options.
- Loader System — Model loading and caching, glTF/GLB support, mesh/material/skeleton/animation extraction, and shader-driven GPU resource initialization.
- Model System — Model interface, GPU vertex types, skeleton and animation data structures, import types, and WGSL assets.
- Physics System — GPU-accelerated rigid body simulation (DEM), particle voxelization, spatial grid collision, fixed-timestep integration, and GPU readback.
- Renderer System — Renderer interface, pipeline cache, frame lifecycle (compute → shadow → render → present), backend types, builder options, and sub-package index.
- Animator — GPU compute animation backends (simple + skeletal), per-instance transform staging, frustum culling, skeletal clip blending, and GPU type definitions.
- Bind Group Provider — GPU bind group abstraction, per-entity resource storage (buffers, textures, samplers), batched buffer writes, and release lifecycle.
- Material — Material interface, surface properties, texture references, GPU uniform types (overlay/effect params), and builder options.
- Pipeline — Render and compute pipeline configuration, depth/blend/cull state, shader attachment, and builder options.
- Shader — WGSL shader loading, annotation pre-processor, bind group layout extraction, vertex layout parsing, and workgroup size resolution.
- Scene System — Scene interface, object management, animator pool, lighting/shadow/Forward+ initialization, frame lifecycle, parallel compute prep, and annotation-driven draw calls.
- Window System — GLFW-based windowing, input callbacks, high-DPI handling, WebGPU surface creation, and builder options.
- Shader Annotation System — Full syntax reference, placement rules, and examples for the
@oxy:include, @oxy:group, and @oxy:provider annotations.
License
MIT