Skip to content

Commit eb1002c

Browse files
committed
docs: add RenderTexture guide, Commands API, render stats, v0.4.1 changelog
- add RenderTexture off-screen rendering guide (EN/ZH) - expand Commands section with full EntityCommands builder API - add Render Stats and Render Stages to rendering guide - add ECS interaction mapping table (Query/Commands/Res) - rewrite scene examples to use system patterns instead of direct World access - add v0.4.1 changelog (EN/ZH) - add Render Texture and v0.4.1 to sidebar
1 parent 2626f92 commit eb1002c

13 files changed

Lines changed: 638 additions & 94 deletions

File tree

docs/astro/astro.config.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export default defineConfig({
7171
{ label: 'Bitmap Text', translations: { 'zh-CN': '位图文本' }, slug: 'guides/bitmap-text' },
7272
{ label: 'Custom Draw', translations: { 'zh-CN': '自定义绘制' }, slug: 'guides/custom-draw' },
7373
{ label: 'Post-Processing', translations: { 'zh-CN': '后处理效果' }, slug: 'guides/post-processing' },
74+
{ label: 'Render Texture', translations: { 'zh-CN': '渲染纹理' }, slug: 'guides/render-texture' },
7475
],
7576
},
7677
{ label: 'Scenes', translations: { 'zh-CN': '场景' }, slug: 'guides/scenes' },
@@ -87,6 +88,7 @@ export default defineConfig({
8788
label: 'Changelog',
8889
translations: { 'zh-CN': '更新日志' },
8990
items: [
91+
{ label: 'v0.4.1', slug: 'changelog-v041' },
9092
{ label: 'v0.4.0', slug: 'changelog-v040' },
9193
{ label: 'v0.3.0', slug: 'changelog' },
9294
],
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
title: v0.4.1
3+
description: ESEngine v0.4.1 release notes
4+
---
5+
6+
import { Aside } from '@astrojs/starlight/components';
7+
8+
## Multi-Camera Rendering
9+
10+
- Added viewport fields (`viewportX`, `viewportY`, `viewportW`, `viewportH`) and `clearFlags` to Camera component
11+
- Per-camera render pipeline with viewport/scissor support for split-screen and minimap use cases
12+
- Camera priority-based render ordering
13+
- Editor scene view with per-camera color coding, camera icons, priority labels, and viewport preview overlay
14+
15+
## BitmapText & BMFont
16+
17+
- Added `BitmapText` component for GPU-rendered bitmap font text with color, fontSize, alignment, spacing, and layer sorting
18+
- BMFont parser (`.fnt` text format) and LabelAtlas creation via the batch renderer
19+
- Editor support: font loading, inspector UI, thumbnail preview, click-to-navigate, and Tab navigation in BitmapFont glyph list
20+
21+
## UIMask
22+
23+
- Added `UIMask` clip rect component for rectangular UI clipping
24+
- Clip rect computation with proper hierarchy support
25+
26+
## Spine Runtime Optional
27+
28+
- Spine runtime is now optional — `none` is the default when no Spine assets are used
29+
- Reduces build size for projects that don't use Spine animation
30+
31+
## Name Component
32+
33+
- Added `Name` component, automatically assigned to entities loaded from scenes
34+
- Added `findEntityByName()` utility for entity lookup by name
35+
36+
## Editor Improvements
37+
38+
- File rename support with `.meta` file handling
39+
- Duplicate filename and illegal character validation
40+
- Error toast notifications for all file operations
41+
- Improved entity duplicate naming from `_copy` to `(N)` pattern
42+
43+
## Performance
44+
45+
- Cached `entityCount()` with O(1) counter instead of O(n) scan
46+
- Replaced Camera/Canvas linear scans with C++ ECS view queries, eliminating ~4000 WASM bridge calls per frame
47+
- Reuse `ext_vertex_storage_` buffers instead of clear+realloc each frame
48+
- Replaced O(n²) selection sort with `std::sort` in `Registry::sort()`
49+
- SpineRenderer: pre-allocate VAO/VBO/EBO, reuse with dynamic capacity
50+
- BatchRenderer: only bind active texture slots instead of all 8
51+
- Nine-slice: hoist texture slot lookup outside loop
52+
- TransformSystem: merge double iteration into single pass
53+
- SystemRunner: cache args array per system to avoid per-frame allocation
54+
55+
## Documentation
56+
57+
- Added Commands API reference with full `EntityCommands` builder API
58+
- Added RenderTexture off-screen rendering guide
59+
- Added Render Stats and Render Stages to the rendering guide
60+
- Added ECS interaction guide — mapping from user intent to system parameters
61+
- Added BitmapText, UIMask, Name, LabelAtlas component docs
62+
- Rewrote scene examples to use proper system patterns (`Query`, `Commands`)
63+
64+
## Bug Fixes
65+
66+
- Fixed use-after-free on registry disposal by adding `disconnectCpp`
67+
- Fixed unnecessary scene reloads on entity selection
68+
- Fixed WASM error handling for missing modules
69+
- Fixed SpineExtension memory leak by using static local instances

docs/astro/src/content/docs/core-concepts/ecs.mdx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,24 @@ See [Systems](/microes/core-concepts/systems/) for the full API.
133133
4. **Update loop** — systems query and process scene entities every frame
134134
5. **Render** — the C++ backend automatically renders all entities with `Sprite` and `Camera` components
135135

136+
## How You Interact with ECS
137+
138+
The `World` stores all entities and components. In your scripts, you interact with it through system parameters:
139+
140+
| What you want to do | System parameter |
141+
|---------------------|-----------------|
142+
| Iterate entities with specific components | `Query(ComponentA, ComponentB)` |
143+
| Read component data | `Query(Component)` — data comes with iteration |
144+
| Mutate component data | `Query(Mut(Component))` — wrap with `Mut` |
145+
| Spawn a new entity | `Commands()``cmds.spawn()` |
146+
| Despawn an entity | `Commands()``cmds.despawn(entity)` |
147+
| Add a component at runtime | `Commands()``cmds.entity(e).insert(Component, data)` |
148+
| Remove a component at runtime | `Commands()``cmds.entity(e).remove(Component)` |
149+
| Read a resource | `Res(ResourceType)` |
150+
| Mutate a resource | `ResMut(ResourceType)` |
151+
152+
See [Systems](/microes/core-concepts/systems/) and [Queries](/microes/core-concepts/queries/) for detailed usage.
153+
136154
## Next Steps
137155

138156
- [Components](/microes/core-concepts/components/) — builtin and custom components

docs/astro/src/content/docs/core-concepts/systems.mdx

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,54 @@ addSystemToSchedule(Schedule.FixedUpdate, physicsSystem);
6464

6565
### Commands
6666

67-
Spawn and despawn entities at runtime:
67+
Create, modify, and destroy entities at runtime:
6868

6969
```typescript
70-
import { Commands } from 'esengine';
70+
import { Commands, Sprite, LocalTransform } from 'esengine';
7171

7272
defineSystem([Commands()], (cmds) => {
73-
cmds.spawn()
74-
.insert(Sprite, { size: { x: 50, y: 50 } })
75-
.insert(LocalTransform, { position: { x: 0, y: 0, z: 0 } });
76-
77-
cmds.despawn(entity);
73+
// Spawn a new entity with components (chainable)
74+
const bullet = cmds.spawn()
75+
.insert(LocalTransform, { position: { x: 0, y: 0, z: 0 } })
76+
.insert(Sprite, { size: { x: 8, y: 8 } })
77+
.id();
78+
79+
// Modify an existing entity
80+
cmds.entity(bullet)
81+
.insert(Velocity, { linear: { x: 100, y: 0 } })
82+
.remove(Sprite);
83+
84+
// Despawn an entity
85+
cmds.despawn(bullet);
86+
87+
// Insert a resource
88+
cmds.insertResource(Score, { value: 0 });
7889
});
7990
```
8091

92+
#### Commands API
93+
94+
| Method | Returns | Description |
95+
|--------|---------|-------------|
96+
| `cmds.spawn()` | `EntityCommands` | Create a new entity, returns a builder |
97+
| `cmds.entity(entity)` | `EntityCommands` | Get a builder for an existing entity |
98+
| `cmds.despawn(entity)` | `Commands` | Queue entity for destruction |
99+
| `cmds.insertResource(res, value)` | `Commands` | Insert or overwrite a resource |
100+
101+
#### EntityCommands API
102+
103+
`spawn()` and `entity()` return an `EntityCommands` builder. All methods are chainable:
104+
105+
| Method | Returns | Description |
106+
|--------|---------|-------------|
107+
| `.insert(component, data?)` | `this` | Add or update a component |
108+
| `.remove(component)` | `this` | Remove a component |
109+
| `.id()` | `Entity` | Get the entity ID |
110+
111+
<Aside type="note">
112+
Commands are buffered and applied at the end of the current schedule stage, not immediately. The exception is `.id()` — calling it triggers immediate entity creation so the ID is available right away.
113+
</Aside>
114+
81115
### Query
82116

83117
Iterate entities with specific components:
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
title: Render Texture
3+
description: Off-screen rendering with RenderTexture in ESEngine
4+
---
5+
6+
import { Aside } from '@astrojs/starlight/components';
7+
8+
A **RenderTexture** lets you render a scene (or part of it) to an off-screen texture instead of the screen. This is useful for minimaps, mirrors, portals, post-processing inputs, and any effect that requires capturing rendered output.
9+
10+
## Creating a RenderTexture
11+
12+
```typescript
13+
import { RenderTexture, type RenderTextureHandle } from 'esengine';
14+
15+
const rt: RenderTextureHandle = RenderTexture.create({
16+
width: 512,
17+
height: 512,
18+
depth: true,
19+
filter: 'linear',
20+
});
21+
```
22+
23+
### RenderTextureOptions
24+
25+
| Field | Type | Default | Description |
26+
|-------|------|---------|-------------|
27+
| `width` | `number` || Texture width in pixels |
28+
| `height` | `number` || Texture height in pixels |
29+
| `depth` | `boolean` | `false` | Attach a depth buffer |
30+
| `filter` | `'nearest' \| 'linear'` | `'nearest'` | Texture filtering mode |
31+
32+
## Rendering to Texture
33+
34+
Wrap your draw calls between `begin()` and `end()`. Everything rendered in between goes to the texture instead of the screen:
35+
36+
```typescript
37+
import { RenderTexture, Draw } from 'esengine';
38+
39+
RenderTexture.begin(rt, viewProjectionMatrix);
40+
41+
Draw.rect(0, 0, 100, 100, { r: 1, g: 0, b: 0, a: 1 });
42+
43+
RenderTexture.end();
44+
```
45+
46+
The `viewProjection` parameter is a `Float32Array` containing the 4x4 view-projection matrix that defines the camera for this off-screen render pass.
47+
48+
<Aside type="note">
49+
`begin()` sets the render target and viewport. `end()` restores the previous render target. Always call `end()` after `begin()`.
50+
</Aside>
51+
52+
## Using the Result
53+
54+
After rendering, `rt.textureId` holds the GPU texture ID. Use it anywhere a texture is expected:
55+
56+
```typescript
57+
import { Draw, Sprite } from 'esengine';
58+
59+
Draw.texture(rt.textureId, 0, 0, rt.width, rt.height);
60+
```
61+
62+
You can also assign it to a Sprite's texture for entity-based rendering.
63+
64+
## Depth Texture
65+
66+
If the RenderTexture was created with `depth: true`, retrieve the depth texture for effects like shadow mapping:
67+
68+
```typescript
69+
const depthTextureId = RenderTexture.getDepthTexture(rt);
70+
```
71+
72+
## Lifecycle
73+
74+
### Resizing
75+
76+
When the target resolution changes (e.g. window resize), resize the RenderTexture:
77+
78+
```typescript
79+
const resized = RenderTexture.resize(rt, newWidth, newHeight);
80+
```
81+
82+
`resize()` returns a new `RenderTextureHandle`. Use the returned handle going forward.
83+
84+
### Releasing
85+
86+
Release GPU resources when the RenderTexture is no longer needed:
87+
88+
```typescript
89+
RenderTexture.release(rt);
90+
```
91+
92+
## API Reference
93+
94+
| Method | Returns | Description |
95+
|--------|---------|-------------|
96+
| `RenderTexture.create(options)` | `RenderTextureHandle` | Create a new render texture |
97+
| `RenderTexture.begin(rt, viewProjection)` | `void` | Begin rendering to texture |
98+
| `RenderTexture.end()` | `void` | End rendering to texture |
99+
| `RenderTexture.getDepthTexture(rt)` | `number` | Get depth texture ID |
100+
| `RenderTexture.resize(rt, width, height)` | `RenderTextureHandle` | Resize render texture |
101+
| `RenderTexture.release(rt)` | `void` | Release GPU resources |
102+
103+
### RenderTextureHandle
104+
105+
| Field | Type | Description |
106+
|-------|------|-------------|
107+
| `textureId` | `number` | GPU texture ID for the color attachment |
108+
| `width` | `number` | Current width in pixels |
109+
| `height` | `number` | Current height in pixels |
110+
111+
## Next Steps
112+
113+
- [Custom Draw](/microes/guides/custom-draw/) — immediate-mode drawing API
114+
- [Post-Processing](/microes/guides/post-processing/) — full-screen effects
115+
- [Materials & Shaders](/microes/guides/materials/) — custom shaders

docs/astro/src/content/docs/guides/rendering.mdx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,47 @@ Set these values in the inspector when placing entities, or modify them at runti
133133
The C++ backend handles all WebGL rendering. You just set component data and the engine draws everything automatically each frame.
134134
</Aside>
135135

136+
## Render Stats
137+
138+
Use `Renderer.getStats()` to get per-frame rendering statistics, useful for profiling and debug overlays:
139+
140+
```typescript
141+
import { Renderer, type RenderStats } from 'esengine';
142+
143+
const stats: RenderStats = Renderer.getStats();
144+
console.log(`Draw calls: ${stats.drawCalls}, Triangles: ${stats.triangles}`);
145+
```
146+
147+
| Field | Type | Description |
148+
|-------|------|-------------|
149+
| `drawCalls` | `number` | Total WebGL draw calls this frame |
150+
| `triangles` | `number` | Total triangles rendered |
151+
| `sprites` | `number` | Sprites drawn |
152+
| `text` | `number` | Text elements drawn |
153+
| `spine` | `number` | Spine skeletons drawn |
154+
| `meshes` | `number` | Custom meshes drawn |
155+
| `culled` | `number` | Objects culled (not drawn) |
156+
157+
## Render Stages
158+
159+
The rendering pipeline is divided into stages that execute in order. Each stage draws a category of objects:
160+
161+
| Stage | Value | Description |
162+
|-------|-------|-------------|
163+
| `Background` | 0 | Background layers (skyboxes, backgrounds) |
164+
| `Opaque` | 1 | Opaque geometry (no transparency) |
165+
| `Transparent` | 2 | Transparent/alpha-blended objects |
166+
| `Overlay` | 3 | UI and overlay elements (drawn on top) |
167+
168+
When using [Custom Draw](/microes/guides/custom-draw/), specify a `RenderStage` to control when your draw commands execute relative to the built-in rendering:
169+
170+
```typescript
171+
import { Draw, RenderStage } from 'esengine';
172+
173+
Draw.bindStage(RenderStage.Overlay);
174+
Draw.rect(0, 0, 100, 50, { r: 0, g: 0, b: 0, a: 0.5 });
175+
```
176+
136177
## Next Steps
137178

138179
- [Canvas & Resolution](/microes/guides/canvas/) — screen adaptation and scale modes
@@ -141,4 +182,5 @@ Set these values in the inspector when placing entities, or modify them at runti
141182
- [Bitmap Text](/microes/guides/bitmap-text/) — GPU-rendered bitmap font text
142183
- [Custom Draw](/microes/guides/custom-draw/) — immediate-mode drawing for debug visualization and dynamic graphics
143184
- [Post-Processing](/microes/guides/post-processing/) — full-screen effects (blur, vignette, grayscale)
185+
- [Render Texture](/microes/guides/render-texture/) — off-screen rendering for minimaps, mirrors, and effects
144186
- [Geometry & Meshes](/microes/guides/geometry/) — custom mesh creation for advanced rendering

0 commit comments

Comments
 (0)