Skip to content

Shape Renderer

The ShapeRenderer component draws GPU-accelerated 2D shapes using signed distance fields (SDF). It supports circles, capsules, and rounded rectangles with antialiased edges at any scale.

Usage

Add ShapeRenderer to an entity alongside Transform:

import { Commands, Transform, ShapeRenderer, ShapeType } from 'esengine';
commands.spawn()
.insert(Transform, { position: { x: 0, y: 0, z: 0 } })
.insert(ShapeRenderer, {
shapeType: ShapeType.Circle,
size: { x: 80, y: 80 },
color: { r: 1, g: 0.5, b: 0, a: 1 },
});

Properties

PropertyTypeDefaultDescription
shapeTypenumber0 (Circle)Shape to render (see Shape Types)
colorColor{r:1, g:1, b:1, a:1}Fill color (RGBA, 0–1)
sizeVec2{x:100, y:100}Width and height in pixels
cornerRadiusnumber0Corner rounding for RoundedRect
layernumber0Render layer for depth sorting (-1000 to 1000)
enabledbooleantrueVisibility toggle

Shape Types

import { ShapeType } from 'esengine';
TypeValueDescription
ShapeType.Circle0Circle inscribed in size
ShapeType.Capsule1Stadium shape — rectangle with hemispherical ends
ShapeType.RoundedRect2Rectangle with rounded corners controlled by cornerRadius

Circle

Uses size as the bounding box. The circle radius is min(size.x, size.y) / 2.

commands.spawn()
.insert(Transform, { position: { x: 0, y: 0, z: 0 } })
.insert(ShapeRenderer, {
shapeType: ShapeType.Circle,
size: { x: 60, y: 60 },
color: { r: 0, g: 0.8, b: 1, a: 1 },
});

Capsule

A rounded rectangle where the shorter axis determines the cap radius. The longer axis defines the overall length.

commands.spawn()
.insert(Transform, { position: { x: 100, y: 0, z: 0 } })
.insert(ShapeRenderer, {
shapeType: ShapeType.Capsule,
size: { x: 30, y: 80 },
color: { r: 0, g: 1, b: 0.5, a: 1 },
});

Rounded Rectangle

A rectangle with rounded corners. The cornerRadius is clamped to half the shorter side.

commands.spawn()
.insert(Transform, { position: { x: 200, y: 0, z: 0 } })
.insert(ShapeRenderer, {
shapeType: ShapeType.RoundedRect,
size: { x: 120, y: 80 },
cornerRadius: 12,
color: { r: 1, g: 0.3, b: 0.6, a: 1 },
});

Modifying at Runtime

Query and modify ShapeRenderer like any other component:

import { defineSystem, addSystem, Query, Mut, ShapeRenderer } from 'esengine';
addSystem(defineSystem(
[Query(Mut(ShapeRenderer))],
(query) => {
for (const [entity, shape] of query) {
shape.color = { r: 0, g: 1, b: 0, a: 0.5 };
shape.enabled = false;
}
}
));

Rendering Details

  • SDF rendering — shapes are rendered using signed distance field functions in a fragment shader, producing clean antialiased edges regardless of zoom level
  • Transform integration — respects position, rotation, and scale from the entity’s Transform
  • Layer sorting — shapes are sorted by layer, then by depth (z-position), matching the same ordering as sprites
  • Frustum culling — shapes outside the camera view are automatically skipped

Editor Integration

  • Hierarchy — right-click → Add Component → ShapeRenderer
  • Inspector — dropdown for shape type, color picker, size vector, and corner radius input
  • Scene View — shapes render in both edit mode and play mode

Next Steps