Custom Draw
The Draw API provides immediate-mode 2D drawing primitives. All draw commands are cleared each frame, making it ideal for debug visualization, custom UI overlays, and dynamic graphics.
Draw Callbacks
Register a draw callback to execute drawing commands each frame. The engine calls your function automatically during the render pass:
import { registerDrawCallback, Draw } from 'esengine';
registerDrawCallback('my-debug', (elapsed) => { Draw.line({ x: 0, y: 0 }, { x: 100, y: 100 }, { r: 1, g: 0, b: 0, a: 1 }, 2);});Remove callbacks when no longer needed:
import { unregisterDrawCallback, clearDrawCallbacks } from 'esengine';
unregisterDrawCallback('my-debug');clearDrawCallbacks();Drawing Primitives
Lines
Draw.line( { x: 0, y: 0 }, // from { x: 200, y: 150 }, // to { r: 1, g: 1, b: 0, a: 1 }, // yellow 2 // thickness);Rectangles
Draw.rect( { x: 100, y: 100 }, // center position { x: 80, y: 60 }, // size { r: 0, g: 0.5, b: 1, a: 0.5 }, // semi-transparent blue true // filled (default));
Draw.rectOutline( { x: 100, y: 100 }, { x: 80, y: 60 }, { r: 1, g: 0, b: 0, a: 1 }, // red 2 // thickness);Circles
Draw.circle( { x: 200, y: 200 }, // center 50, // radius { r: 0, g: 1, b: 0, a: 1 }, // green true, // filled 32 // segments);
Draw.circleOutline( { x: 200, y: 200 }, 50, { r: 1, g: 1, b: 1, a: 1 }, // white 1, // thickness 32 // segments);Textures
Draw.texture( { x: 300, y: 200 }, // position { x: 64, y: 64 }, // size textureHandle, { r: 1, g: 1, b: 1, a: 1 } // tint (default: white));
Draw.textureRotated( { x: 300, y: 200 }, { x: 64, y: 64 }, Math.PI / 4, // rotation in radians textureHandle, { r: 1, g: 1, b: 1, a: 1 });Primitives Reference
| Method | Parameters | Description |
|---|---|---|
line(from, to, color, thickness?) | Vec2, Vec2, Color, number=1 | Line segment |
rect(position, size, color, filled?) | Vec2, Vec2, Color, bool=true | Rectangle |
rectOutline(position, size, color, thickness?) | Vec2, Vec2, Color, number=1 | Rectangle outline |
circle(center, radius, color, filled?, segments?) | Vec2, number, Color, bool=true, number=32 | Circle |
circleOutline(center, radius, color, thickness?, segments?) | Vec2, number, Color, number=1, number=32 | Circle outline |
texture(position, size, textureHandle, tint?) | Vec2, Vec2, number, Color=white | Textured quad |
textureRotated(position, size, rotation, textureHandle, tint?) | Vec2, Vec2, number, number, Color=white | Rotated textured quad |
Render State
Control how subsequent primitives are rendered:
Draw.setLayer(5); // render layer (higher = on top)Draw.setDepth(0.5); // depth sorting within a layerDraw.setBlendMode(BlendMode.Additive); // blend modeDraw.setDepthTest(true); // enable depth testing| Method | Description |
|---|---|
setLayer(layer) | Set render layer index |
setDepth(depth) | Set depth value for sorting |
setBlendMode(mode) | Set blend mode (Normal, Additive, Multiply, Screen, PremultipliedAlpha) |
setDepthTest(enabled) | Enable or disable depth testing |
Custom Mesh Drawing
For advanced rendering, draw custom geometry with shaders or materials:
import { Geometry, Draw, Material } from 'esengine';
const quad = Geometry.createQuad(100, 100);const transform = new Float32Array([ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,]);
Draw.drawMesh(quad, shaderHandle, transform);Draw.drawMeshWithMaterial(quad, materialHandle, transform);drawMeshWithMaterial automatically applies the material’s blend mode, depth test, and uniforms.
See Geometry & Meshes for creating custom meshes and Materials & Shaders for shader setup.
Performance Stats
const drawCalls = Draw.getDrawCallCount();const primitives = Draw.getPrimitiveCount();Example: Debug Collision Boxes
import { registerDrawCallback, Draw } from 'esengine';import { defineSystem, addSystem, Query, LocalTransform, Collider } from 'esengine';
const colliders: Array<{ x: number; y: number; w: number; h: number }> = [];
addSystem(defineSystem( [Query(LocalTransform, Collider)], (query) => { colliders.length = 0; for (const [entity, transform, collider] of query) { colliders.push({ x: transform.position.x, y: transform.position.y, w: collider.width, h: collider.height, }); } }));
registerDrawCallback('debug-colliders', () => { const green = { r: 0, g: 1, b: 0, a: 0.5 }; for (const c of colliders) { Draw.rectOutline( { x: c.x, y: c.y }, { x: c.w, y: c.h }, green, 1 ); }});Next Steps
- Post-Processing — full-screen effects pipeline
- Geometry & Meshes — custom mesh creation
- Materials & Shaders — shader and material management