1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
|
# Sequence System Documentation
This document describes the `.seq` file format used to define demo timelines.
## Overview
Sequence files (`.seq`) define the timeline and layering of visual effects in the demo. They are compiled by `seq_compiler` into C++ code at build time.
## File Location
- Demo sequence: `assets/demo.seq`
- Compiler: `tools/seq_compiler.cc`
- Generated output: `src/generated/timeline.cc`
## Command Line Usage
### Basic Compilation
```bash
./build/seq_compiler assets/demo.seq src/generated/timeline.cc
```
### Validation Only
```bash
./build/seq_compiler assets/demo.seq
```
Validates syntax without generating code.
### Gantt Chart Visualization
**ASCII Gantt Chart:**
```bash
./build/seq_compiler assets/demo.seq --gantt=timeline.txt
```
**HTML/SVG Gantt Chart (Recommended):**
```bash
./build/seq_compiler assets/demo.seq --gantt-html=timeline.html
```
Open `timeline.html` in browser for interactive visualization with hover tooltips.
**Combined Modes:**
```bash
./build/seq_compiler assets/demo.seq timeline.cc --gantt=t.txt --gantt-html=t.html
```
---
## Syntax Reference
### BPM Declaration
```
# BPM 120
```
Specifies beats per minute for the demo. Used to convert beat notation to seconds.
### END_DEMO Directive
```
END_DEMO <time>
```
Specifies when the demo should automatically exit (optional).
- If not specified, demo runs indefinitely until user closes window
- Supports beat notation (e.g., `64b`) or seconds (e.g., `32.0`)
### SEQUENCE Declaration
```
SEQUENCE <global_start> <priority> [optional_end]
EFFECT <EffectClassName> <local_start> <local_end> <priority> [constructor_args...]
```
**Parameters:**
- `global_start`: When this sequence starts (beats or seconds)
- `priority`: Render order between sequences (higher = rendered later/on top)
- Use 0-9 for scene effects
- Use 10+ for post-processing
- `[optional_end]`: Optional end time in brackets (e.g., `[30.0]`)
- If specified, all effects in the sequence will be forcefully ended at this time
- Time is relative to the sequence start
- If omitted, effects run until their individual end times
### EFFECT Declaration
```
EFFECT <+|=|-> <EffectClassName> <local_start> <local_end> [constructor_args...]
```
**Parameters:**
- Priority modifier (one of):
- `+`: Increment priority (or start at 0 if first effect)
- `=`: Keep same priority as previous effect
- `-`: Decrement priority (or start at -1 if first effect, for background layers)
- `EffectClassName`: C++ class name (must be declared in `demo_effects.h`)
- `local_start`: Start time relative to sequence start (beats or seconds)
- `local_end`: End time relative to sequence start (beats or seconds)
- `constructor_args`: Optional additional parameters (rarely used)
**Priority System:**
- Effects are assigned priorities based on their order in the file
- First effect: `+` starts at 0, `-` starts at -1, `=` starts at 0
- Subsequent effects: `+` increments, `=` keeps same, `-` decrements
- Priorities determine render order (lower = drawn first/background)
- Effects should be listed in desired priority order within each sequence
---
## Time Notation
The sequence file supports flexible time notation:
| Notation | Example | Description |
|----------|---------|-------------|
| Integer beats | `0`, `64`, `128` | No decimal point = beats |
| Explicit beats | `0b`, `64b`, `128b` | Suffix 'b' = beats |
| Decimal seconds | `0.0`, `32.0`, `64.0` | Decimal point = seconds |
| Explicit seconds | `32.0s`, `64.0s` | Suffix 's' = seconds |
**Examples at 120 BPM:**
- Beat 0 = 0.0 seconds
- Beat 64 = 32.0 seconds
- Beat 120 = 60.0 seconds
---
## Effect System
### Constructor Parameters
**Standard Parameters (ALL effects receive these automatically):**
- `WGPUDevice device`: WebGPU device handle
- `WGPUQueue queue`: Command queue for GPU operations
- `WGPUTextureFormat format`: Surface texture format
Most effects only use these standard parameters. If an effect needs custom initialization, parameters are specified after the priority field.
**Example (hypothetical custom effect):**
```
EFFECT CustomEffect 0 10 0 1.5 "param"
```
Translates to:
```cpp
std::make_shared<CustomEffect>(device, queue, format, 1.5, "param")
```
### Runtime Parameters
All effects receive these dynamic parameters every frame in their `render()` method:
| Parameter | Type | Description |
|-----------|------|-------------|
| `time` | float | Global time in seconds (from demo start) |
| `beat` | float | Current beat fraction (0.0 to 1.0 within each beat) |
| `intensity` | float | Audio peak intensity (0.0 to 1.0, for beat detection) |
| `aspect_ratio` | float | Screen width/height ratio |
---
## Available Effects
### Scene Effects
Render 3D geometry to the framebuffer with depth testing.
#### HeptagonEffect
Animated geometric heptagon shape.
- **Uses:** `time` (animation), `beat` (rotation), `aspect_ratio` (projection)
#### ParticlesEffect
GPU-simulated particle system.
- **Uses:** `time` (physics), `intensity` (emission rate)
#### Hybrid3DEffect
3D objects with camera movement.
- **Uses:** `time` (camera paths), `beat` (object animation), `aspect_ratio`
#### FlashCubeEffect
Large background cube with Perlin noise texture.
- **Uses:** `time` (rotation), `intensity` (flash trigger on beat hits)
- **Note:** Typically used with priority -1 for background layer
### Post-Process Effects
Full-screen shaders applied in priority order after scene rendering.
#### GaussianBlurEffect
Gaussian blur with beat pulsation.
- **Uses:** `intensity` (blur size pulsates 0.5x-2.5x based on audio peak)
#### SolarizeEffect
Color inversion with alternating red/blue tints.
- **Uses:** `time` (alternates every 2 seconds between color schemes)
#### ChromaAberrationEffect
RGB channel separation effect.
- **Uses:** `time` (animation), `intensity` (separation amount)
#### ThemeModulationEffect
Brightness cycling (bright/dark alternation).
- **Uses:** `time` (cycles every 8 seconds: 1.0 bright to 0.35 dark)
#### FadeEffect
Fade to/from black.
- **Uses:** `time` (fades in first 2s, fades out after 36s - hardcoded timing)
#### FlashEffect
White flash on strong beat hits.
- **Uses:** `intensity` (triggers flash when > 0.7, exponential decay)
---
## Tips & Best Practices
### Layering
- Scene effects render to framebuffer with depth testing
- Post-processing effects are full-screen shaders applied in sequence priority order
- Use negative priority for background elements (skybox, far objects)
- Higher sequence priority = later in post-process chain (rendered on top)
### Priority Guidelines
- **Scene Effects:** priority 0-9
- Background: -1 (e.g., skybox, distant objects)
- Midground: 0-5 (main geometry)
- Foreground: 6-9 (overlays, particles)
- **Post-Process:** priority 10+
- Apply in order: blur → distortion → color grading
### Timing
- Use beat notation for music-synchronized effects
- Use seconds for absolute timing
- Keep effect durations reasonable (avoid very short < 0.1s unless intentional)
- Use sequence `[end_time]` to forcefully terminate long-running effects
---
## Examples
### Basic Sequence
```
SEQUENCE 0 0
EFFECT + FlashEffect 0.0 0.5 # Priority 0 (first with +)
EFFECT + HeptagonEffect 0.2 10 # Priority 1 (increment)
```
### Same Priority (Layered Effects)
```
SEQUENCE 0 0
EFFECT + Flash 0.0 0.5 # Priority 0
EFFECT = Fade 0.1 0.3 # Priority 0 (same as Flash)
EFFECT + Other 0.2 3 # Priority 1 (increment)
```
### Background Elements
```
SEQUENCE 0 0
EFFECT - FlashCube 0 10 # Priority -1 (background)
EFFECT = BgEffect 0 5 # Priority -1 (same layer)
EFFECT + MainEffect 0 10 # Priority 0 (foreground)
```
### Sequence with Explicit End Time
```
SEQUENCE 8b 0 [5.0]
EFFECT + Particles 0 120 # Would run 120s, but sequence ends at 5s
```
### Post-Processing Chain
```
SEQUENCE 0 10
EFFECT + GaussianBlur 0 60 # Priority 0 (applied first)
EFFECT + ChromaAberration 0 60 # Priority 1 (applied second)
EFFECT + Solarize 0 60 # Priority 2 (applied last)
```
### Music-Synchronized Effects
```
# BPM 120
SEQUENCE 0b 0 # Start at beat 0 (0.0s)
EFFECT + Flash 0b 1b # Flash from beat 0 to beat 1 (0-0.5s)
EFFECT + Heptagon 4b 8b # Main effect from beat 4 to 8 (2-4s)
```
---
## Debugging & Visualization
### Gantt Charts
Gantt charts help visualize the timeline structure:
**ASCII Chart (Terminal-Friendly):**
```
Time (s): 0 5 10 15 20
|----|----|----|----|----|
SEQ@0s [pri=0]
████████████████████████ (0-20s)
FlashEffect [pri=1]
▓▓·················· (0-1s)
HeptagonEffect [pri=0]
▓▓▓▓▓▓▓▓▓▓▓▓········ (0-10s)
```
**HTML/SVG Chart (Interactive):**
- Color-coded sequences and effects
- Hover tooltips with full details
- Invalid time ranges highlighted in red
- Professional dark theme
- Zoom/pan support
- Easy to share or present
### Validation
Run validation without code generation to catch syntax errors:
```bash
./build/seq_compiler assets/demo.seq
# Output: "Validation successful: 14 sequences, explicit end time."
```
### Common Issues Caught by Validation
- Invalid time ranges (end < start)
- Missing effect classes
- Syntax errors
- Malformed time notation
---
## Integration with Build System
The sequence compiler is automatically invoked during build via CMake:
```cmake
add_custom_command(
OUTPUT ${GENERATED_DIR}/timeline.cc
COMMAND seq_compiler assets/demo.seq ${GENERATED_DIR}/timeline.cc
DEPENDS assets/demo.seq
COMMENT "Compiling demo sequence..."
)
```
Editing `assets/demo.seq` triggers automatic recompilation and rebuilds affected targets.
---
## See Also
- `doc/HOWTO.md` - Building and running the demo
- `doc/CONTRIBUTING.md` - Coding guidelines
- `assets/demo.seq` - Current demo timeline
- `src/gpu/demo_effects.h` - Available effect classes
|