vizcore 0.1.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +70 -117
  3. data/docs/.nojekyll +0 -0
  4. data/docs/assets/playground-worker.js +373 -0
  5. data/docs/assets/playground.css +440 -0
  6. data/docs/assets/playground.js +652 -0
  7. data/docs/assets/site.css +744 -0
  8. data/docs/assets/vizcore-demo.gif +0 -0
  9. data/docs/assets/vizcore-poster.png +0 -0
  10. data/docs/assets/vj-tunnel.js +159 -0
  11. data/docs/index.html +225 -0
  12. data/docs/playground.html +81 -0
  13. data/docs/shape_dsl.md +269 -0
  14. data/examples/README.md +59 -0
  15. data/examples/assets/README.md +19 -0
  16. data/examples/audio_inspector.rb +34 -0
  17. data/examples/club_intro_drop.rb +78 -0
  18. data/examples/kansai_rubykaigi_visual.rb +70 -0
  19. data/examples/live_coding_minimal.rb +22 -0
  20. data/examples/midi_controller_show.rb +78 -0
  21. data/examples/midi_scene_switch.rb +3 -1
  22. data/examples/parser_visualizer.rb +48 -0
  23. data/examples/readme_demo.rb +17 -0
  24. data/examples/rhythm_geometry.rb +34 -0
  25. data/examples/ruby_crystal_show.rb +35 -0
  26. data/examples/shader_playground.rb +18 -0
  27. data/examples/unyo_liquid.rb +59 -0
  28. data/examples/vj_ambient_chill_room.rb +124 -0
  29. data/examples/vj_dnb_jungle.rb +170 -0
  30. data/examples/vj_festival_mainstage.rb +245 -0
  31. data/examples/vj_festival_mainstage.yml +17 -0
  32. data/examples/vj_glitch_industrial.rb +164 -0
  33. data/examples/vj_hiphop_cipher.rb +167 -0
  34. data/examples/vj_jpop_idol_live.rb +210 -0
  35. data/examples/vj_synthwave_retro.rb +173 -0
  36. data/examples/vj_techno_warehouse.rb +195 -0
  37. data/frontend/index.html +494 -2
  38. data/frontend/src/audio-inspector.js +40 -0
  39. data/frontend/src/custom-shape-param-controls.js +106 -0
  40. data/frontend/src/live-controls.js +131 -0
  41. data/frontend/src/main.js +1060 -16
  42. data/frontend/src/mapping-target-selector.js +109 -0
  43. data/frontend/src/midi-learn.js +194 -0
  44. data/frontend/src/performance-monitor.js +183 -0
  45. data/frontend/src/plugin-runtime.js +130 -0
  46. data/frontend/src/projector-mode.js +56 -0
  47. data/frontend/src/renderer/engine.js +157 -3
  48. data/frontend/src/renderer/layer-manager.js +442 -30
  49. data/frontend/src/renderer/shader-manager.js +26 -0
  50. data/frontend/src/runtime-control-preset.js +11 -0
  51. data/frontend/src/shader-error-overlay.js +29 -0
  52. data/frontend/src/shader-param-controls.js +93 -0
  53. data/frontend/src/shaders/builtins.js +380 -2
  54. data/frontend/src/shaders/post-effects.js +52 -0
  55. data/frontend/src/shape-editor-controls.js +157 -0
  56. data/frontend/src/visual-regression.js +67 -0
  57. data/frontend/src/visual-settings-preset.js +103 -0
  58. data/frontend/src/visuals/geometry.js +666 -0
  59. data/frontend/src/visuals/image-renderer.js +291 -0
  60. data/frontend/src/visuals/particle-system.js +56 -10
  61. data/frontend/src/visuals/shape-renderer.js +475 -0
  62. data/frontend/src/visuals/spectrogram-renderer.js +226 -0
  63. data/frontend/src/visuals/svg-arc.js +104 -0
  64. data/frontend/src/visuals/text-renderer.js +112 -11
  65. data/frontend/src/websocket-client.js +12 -1
  66. data/lib/vizcore/analysis/adaptive_normalizer.rb +70 -0
  67. data/lib/vizcore/analysis/beat_detector.rb +4 -2
  68. data/lib/vizcore/analysis/bpm_estimator.rb +8 -0
  69. data/lib/vizcore/analysis/feature_recorder.rb +159 -0
  70. data/lib/vizcore/analysis/feature_replay.rb +84 -0
  71. data/lib/vizcore/analysis/pipeline.rb +235 -11
  72. data/lib/vizcore/analysis/tap_tempo.rb +74 -0
  73. data/lib/vizcore/analysis.rb +4 -0
  74. data/lib/vizcore/audio/dummy_sine_input.rb +1 -1
  75. data/lib/vizcore/audio/fixture_input.rb +65 -0
  76. data/lib/vizcore/audio/input_manager.rb +4 -2
  77. data/lib/vizcore/audio/mic_input.rb +24 -8
  78. data/lib/vizcore/audio/portaudio_ffi.rb +106 -1
  79. data/lib/vizcore/audio.rb +1 -0
  80. data/lib/vizcore/cli/doctor.rb +159 -0
  81. data/lib/vizcore/cli/dsl_reference.rb +99 -0
  82. data/lib/vizcore/cli/layer_docs.rb +46 -0
  83. data/lib/vizcore/cli/scene_diagnostics.rb +23 -0
  84. data/lib/vizcore/cli/scene_inspector.rb +136 -0
  85. data/lib/vizcore/cli/scene_validator.rb +337 -0
  86. data/lib/vizcore/cli/shader_template.rb +68 -0
  87. data/lib/vizcore/cli/shader_uniform_docs.rb +54 -0
  88. data/lib/vizcore/cli.rb +689 -18
  89. data/lib/vizcore/config.rb +103 -2
  90. data/lib/vizcore/control_preset.rb +68 -0
  91. data/lib/vizcore/dsl/engine.rb +277 -5
  92. data/lib/vizcore/dsl/layer_builder.rb +1280 -23
  93. data/lib/vizcore/dsl/layer_group_builder.rb +112 -0
  94. data/lib/vizcore/dsl/mapping_resolver.rb +290 -7
  95. data/lib/vizcore/dsl/mapping_transform_builder.rb +71 -0
  96. data/lib/vizcore/dsl/reaction_builder.rb +44 -0
  97. data/lib/vizcore/dsl/scene_builder.rb +61 -5
  98. data/lib/vizcore/dsl/shader_source_resolver.rb +67 -6
  99. data/lib/vizcore/dsl/style_builder.rb +68 -0
  100. data/lib/vizcore/dsl/timeline_builder.rb +138 -0
  101. data/lib/vizcore/dsl/transition_controller.rb +77 -0
  102. data/lib/vizcore/dsl.rb +5 -1
  103. data/lib/vizcore/layer_catalog.rb +275 -0
  104. data/lib/vizcore/project_manifest.rb +152 -0
  105. data/lib/vizcore/renderer/png_writer.rb +57 -0
  106. data/lib/vizcore/renderer/render_sequence.rb +153 -0
  107. data/lib/vizcore/renderer/scene_frame_source.rb +132 -0
  108. data/lib/vizcore/renderer/scene_serializer.rb +36 -3
  109. data/lib/vizcore/renderer/snapshot.rb +38 -0
  110. data/lib/vizcore/renderer/snapshot_renderer.rb +938 -0
  111. data/lib/vizcore/renderer.rb +5 -0
  112. data/lib/vizcore/server/frame_broadcaster.rb +143 -8
  113. data/lib/vizcore/server/gallery_app.rb +155 -0
  114. data/lib/vizcore/server/gallery_page.rb +100 -0
  115. data/lib/vizcore/server/gallery_runner.rb +48 -0
  116. data/lib/vizcore/server/rack_app.rb +203 -4
  117. data/lib/vizcore/server/runner.rb +391 -22
  118. data/lib/vizcore/server/scene_dependency_watcher.rb +79 -0
  119. data/lib/vizcore/server/websocket_handler.rb +60 -10
  120. data/lib/vizcore/server.rb +4 -0
  121. data/lib/vizcore/shape.rb +719 -0
  122. data/lib/vizcore/sync/osc_message.rb +103 -0
  123. data/lib/vizcore/sync/osc_receiver.rb +68 -0
  124. data/lib/vizcore/sync.rb +4 -0
  125. data/lib/vizcore/templates/midi_control_scene.rb +3 -1
  126. data/lib/vizcore/templates/plugin_layer.rb +20 -0
  127. data/lib/vizcore/templates/plugin_readme.md +23 -0
  128. data/lib/vizcore/templates/plugin_renderer.js +43 -0
  129. data/lib/vizcore/templates/plugin_scene.rb +14 -0
  130. data/lib/vizcore/templates/project_readme.md +7 -23
  131. data/lib/vizcore/templates/rubykaigi_scene.rb +30 -0
  132. data/lib/vizcore/version.rb +1 -1
  133. data/lib/vizcore.rb +28 -0
  134. data/scripts/browser_capture.mjs +75 -0
  135. data/sig/vizcore.rbs +461 -0
  136. metadata +94 -3
  137. data/docs/GETTING_STARTED.md +0 -105
data/docs/shape_dsl.md ADDED
@@ -0,0 +1,269 @@
1
+ # Vizcore Shape DSL
2
+
3
+ Vizcore shape layers can declare 2D vector primitives directly in Ruby. Calling a
4
+ shape primitive inside a layer automatically marks that layer as `type: :shape`.
5
+
6
+ ```ruby
7
+ Vizcore.define do
8
+ scene :logo do
9
+ layer :badge do
10
+ rect :panel, width: 360, height: 160, radius: 24 do
11
+ fill "#111827"
12
+ stroke width: 2, color: "#38bdf8"
13
+ opacity 0.8
14
+ end
15
+
16
+ star :spark, points: 5, radius: 72, inner_radius: 28 do
17
+ translate x: 180, y: 0
18
+ map beat_pulse, to: :scale, range: 0.8..1.4
19
+ end
20
+ end
21
+ end
22
+ end
23
+ ```
24
+
25
+ ## Primitives
26
+
27
+ Supported primitives:
28
+
29
+ - `circle id = nil, x: 0, y: 0, radius: 100, count: 1, segments: 96`
30
+ - `line id = nil, x1: -100, y1: 0, x2: 100, y2: 0`
31
+ - `rect id = nil, x: 0, y: 0, width:, height:, radius: 0`
32
+ - `polygon id = nil, points: [[x, y], ...], closed: true`
33
+ - `polyline id = nil, points: [[x, y], ...]`
34
+ - `path id = nil, detail: 32, tolerance: nil, max_segments: 4096 do ... end`
35
+ - `bezier id = nil, from:, control:, to:` for quadratic curves
36
+ - `bezier id = nil, from:, c1:, c2:, to:` for cubic curves
37
+ - `star id = nil, points: 5, radius: 100, inner_radius: 50`
38
+ - `custom_shape name_or_class, **params`
39
+
40
+ `draw do ... end` may be used to group declarations for readability.
41
+ `group do ... end` applies shared style and transform to child primitives.
42
+
43
+ ## Path Commands
44
+
45
+ Path blocks support an SVG-like command subset:
46
+
47
+ ```ruby
48
+ path :blob, detail: 48 do
49
+ move_to 0, 120
50
+ line_to 120, 0
51
+ quad_to 80, -100, 0, -120
52
+ cubic_to -80, -100, -120, 80, 0, 120
53
+ close
54
+ end
55
+ ```
56
+
57
+ Commands are serialized as `M`, `L`, `Q`, `C`, `H`, `V`, `A`, and `Z`. The
58
+ Canvas2D renderer draws `arc_to` as an SVG-style elliptical arc, and the line
59
+ fallback/snapshot renderer flattens curves and arcs to line segments.
60
+ `detail` controls the default curve/arc subdivision count. When `tolerance` is
61
+ provided, quadratic and cubic curves use adaptive flattening instead. `max_segments`
62
+ caps the number of flattened line segments per path; the DSL raises when the
63
+ estimated flattened path would exceed that budget.
64
+
65
+ ## Style And Transform
66
+
67
+ Inside a shape block, these methods target the shape rather than the layer:
68
+
69
+ ```ruby
70
+ fill "#f472b6"
71
+ stroke 2
72
+ stroke width: 3, color: "#ffffff"
73
+ blend :add
74
+ opacity 0.75
75
+
76
+ translate x: 100, y: 40
77
+ translate 100, 40
78
+ rotate 30
79
+ scale 1.2
80
+ scale x: 1.4, y: 0.8
81
+ origin x: 0, y: 0
82
+ ```
83
+
84
+ The transform order is origin adjustment, scale, rotate, then translate.
85
+
86
+ ## Groups
87
+
88
+ Groups are flattened into child primitives during DSL evaluation. Child shapes
89
+ inherit style values they do not set themselves, and group opacity is multiplied
90
+ with child opacity.
91
+
92
+ ```ruby
93
+ group :spinner do
94
+ translate x: 0, y: 80
95
+ rotate 15
96
+ scale 1.2
97
+ opacity 0.75
98
+ stroke width: 2, color: "#38bdf8"
99
+
100
+ 12.times do |index|
101
+ rect width: 12, height: 80 do
102
+ translate x: 0, y: 160
103
+ rotate index * 30
104
+ end
105
+ end
106
+ end
107
+ ```
108
+
109
+ ## Mapping
110
+
111
+ Mappings declared inside a shape block are scoped to that shape:
112
+
113
+ ```ruby
114
+ circle :ring, radius: 120 do
115
+ map bass, to: :radius, range: 80..240
116
+ map beat_pulse, to: :scale, range: 1.0..1.4
117
+ map high, to: :opacity, range: 0.2..1.0
118
+ end
119
+ ```
120
+
121
+ Transform aliases:
122
+
123
+ - `:translate_x` -> `transform.translate.x`
124
+ - `:translate_y` -> `transform.translate.y`
125
+ - `:rotate` and `:rotation` -> `transform.rotate`
126
+ - `:scale` -> `transform.scale`
127
+ - `:scale_x` -> `transform.scale.x`
128
+ - `:scale_y` -> `transform.scale.y`
129
+ - `:origin_x` -> `transform.origin.x`
130
+ - `:origin_y` -> `transform.origin.y`
131
+
132
+ You can also map to a named shape from the layer scope:
133
+
134
+ ```ruby
135
+ rect :panel, width: 360, height: 160
136
+ map bass, to: shape(:panel).rotate, range: -12..12
137
+ ```
138
+
139
+ Mappings inside a static `custom_shape` block are applied to each primitive
140
+ generated by that custom shape:
141
+
142
+ ```ruby
143
+ custom_shape :badge, radius: 120 do
144
+ fill "#22d3ee"
145
+ map beat_pulse, to: :scale, range: 0.8..1.2
146
+ end
147
+ ```
148
+
149
+ ## Custom Shapes
150
+
151
+ Custom shapes are registered in Ruby and expanded into regular shape
152
+ primitives before the browser receives the scene.
153
+
154
+ ```ruby
155
+ class DiamondShape
156
+ include Vizcore::Shape
157
+
158
+ param :radius, default: 100, min: 10, max: 400
159
+
160
+ def draw(ctx)
161
+ radius = ctx.param(:radius)
162
+
163
+ ctx.polygon points: [
164
+ [0, radius],
165
+ [radius, 0],
166
+ [0, -radius],
167
+ [-radius, 0]
168
+ ]
169
+ end
170
+ end
171
+
172
+ Vizcore.register_shape :diamond, DiamondShape
173
+ ```
174
+
175
+ Use the registered shape from a layer:
176
+
177
+ ```ruby
178
+ layer :generated_logo do
179
+ custom_shape :diamond, radius: 140 do
180
+ rotate 45
181
+ stroke width: 2, color: "#ffffff"
182
+ end
183
+ end
184
+ ```
185
+
186
+ Block registration is supported for small generators:
187
+
188
+ ```ruby
189
+ Vizcore.register_shape :spark do |ctx|
190
+ ctx.star points: 5, radius: ctx.param(:radius, 80), inner_radius: 32
191
+ end
192
+ ```
193
+
194
+ `draw(ctx)` may return a primitive hash, an array of primitive hashes, or build
195
+ primitives with `ctx.draw`, `ctx.circle`, `ctx.rect`, `ctx.path`, and the other
196
+ shape methods. Values declared with `param` are validated against their
197
+ `min`/`max` metadata before `draw(ctx)` runs, and dynamic custom shape
198
+ descriptors include the same schema for editor tooling.
199
+
200
+ By default, custom shapes are expanded when the DSL is evaluated. Use
201
+ `dynamic: true` when the generator needs mapped params, `ctx.time`, `ctx.frame`,
202
+ or `ctx.audio` at runtime:
203
+
204
+ ```ruby
205
+ custom_shape :orbit, count: 32, radius: 260, dynamic: true do
206
+ fill "#22d3ee"
207
+ map bass, to: :radius, range: 120..280
208
+ map beat_pulse, to: :scale, range: 0.8..1.2
209
+ end
210
+ ```
211
+
212
+ Inside a dynamic custom shape block, mappings to custom params such as `:radius`
213
+ are applied before `draw(ctx)` runs. Transform aliases such as `:scale` and
214
+ `:rotate` are applied to the generated primitives after expansion.
215
+
216
+ Use `static: true` for generators that are independent of runtime context. Static
217
+ custom shapes with identical renderer, params, layer context, palette, and
218
+ resolution reuse a cached expansion, while each call still receives its own copy
219
+ of the generated primitives.
220
+
221
+ ## Coordinates
222
+
223
+ New shape schema layers use center-origin logical coordinates by default:
224
+
225
+ - `x` increases to the right.
226
+ - `y` increases upward.
227
+ - `x: 0, y: 0` is the center of the canvas.
228
+
229
+ Legacy `circle` and `line` layers without `shape_schema_version: 2` keep the old
230
+ coordinate heuristic for compatibility with existing examples.
231
+
232
+ Set `units :ndc` on the layer to use normalized device coordinates directly.
233
+
234
+ ## Validation
235
+
236
+ The DSL raises early for malformed primitives:
237
+
238
+ - duplicate shape IDs within a layer
239
+ - negative `radius`, `inner_radius`, `width`, `height`, or `stroke_width`
240
+ - `polygon` with fewer than 3 points
241
+ - `polyline` with fewer than 2 points
242
+ - `path` without commands
243
+ - `path` whose estimated flattened segment count exceeds `max_segments`
244
+ - unknown `custom_shape`
245
+ - custom shapes that return unsupported primitive kinds
246
+
247
+ `vizcore validate` also emits warnings for shape payloads that are renderable but
248
+ likely surprising: unsupported primitive kinds in raw `params[:shapes]`, fills
249
+ that line fallback will ignore, opacity values outside `0..1`, and zero or very
250
+ large scale values that will collapse or clamp.
251
+
252
+ ## Renderer Notes
253
+
254
+ The browser renderer uses a Canvas2D shape backend composited through the
255
+ existing WebGL layer pipeline. It supports fill, stroke color/width, opacity,
256
+ dash, line caps/joins, transforms, and logical/ndc coordinates for the shape
257
+ schema.
258
+
259
+ If Canvas2D is unavailable, the browser falls back to the existing line renderer.
260
+ That fallback ignores fill and only approximates stroke geometry. The software
261
+ snapshot renderer also uses line flattening.
262
+
263
+ The browser HUD includes local shape editor controls for resolved shape layers:
264
+ primitive kind, translate, rotate, scale, opacity, fill, stroke color, and stroke
265
+ width can be adjusted in the running view without mutating the source DSL file.
266
+ Dynamic custom shape params with `param` metadata are also exposed as HUD
267
+ controls; changing one sends a runtime override to the server so the Ruby custom
268
+ shape is re-expanded on the next frame. The HUD also lists valid mapping target
269
+ paths for layer params, primitive params/transforms, and custom shape params.
@@ -0,0 +1,59 @@
1
+ # Vizcore Examples
2
+
3
+ Run the browser gallery for launch commands and scene metadata:
4
+
5
+ ```bash
6
+ vizcore gallery
7
+ ```
8
+
9
+ Most examples also work directly:
10
+
11
+ ```bash
12
+ vizcore start examples/basic.rb
13
+ vizcore start examples/audio_inspector.rb --audio-source mic
14
+ vizcore start examples/audio_inspector.rb --audio-source mic --noise-gate 0.001
15
+ vizcore start examples/vj_techno_warehouse.rb --audio-source file --audio-file examples/assets/complex_demo_loop.wav
16
+ ```
17
+
18
+ ## Core Examples
19
+
20
+ | File | Description |
21
+ |---|---|
22
+ | `basic.rb` | Single wireframe cube layer |
23
+ | `intro_drop.rb` | Beat-triggered scene transition |
24
+ | `file_audio_demo.rb` | File audio source walkthrough |
25
+ | `complex_audio_showcase.rb` | Dense multi-layer showcase |
26
+ | `rhythm_geometry.rb` | Drum-reactive geometric pattern |
27
+ | `ruby_crystal_show.rb` | Ruby-themed crystal visual |
28
+ | `parser_visualizer.rb` | Parser-themed token and AST sketch |
29
+ | `live_coding_minimal.rb` | Tiny live-coding scene |
30
+ | `club_intro_drop.rb` | Intro, build, drop flow |
31
+ | `shader_playground.rb` | Focused shader params example |
32
+ | `audio_inspector.rb` | Audio feature visualization |
33
+ | `readme_demo.rb` | Minimal beat pulse to ring radius demo |
34
+ | `midi_scene_switch.rb` | MIDI scene switching |
35
+ | `midi_controller_show.rb` | MIDI pads and CC controls |
36
+ | `kansai_rubykaigi_visual.rb` | Event showcase visual |
37
+ | `custom_shader.rb` | Custom GLSL shader |
38
+ | `unyo_liquid.rb` | Liquid wobble and FFT blob |
39
+
40
+ ## VJ Set Examples
41
+
42
+ Ready-to-run scenes grouped by genre / mood. All scenes accept live mic input
43
+ or any audio file. `B` toggles Blackout, `F` toggles Freeze, and scenes that
44
+ declare tap tempo use Space.
45
+
46
+ | File | Genre / Mood | BPM | Scenes | Notes |
47
+ |---|---|---|---|---|
48
+ | `vj_techno_warehouse.rb` | Techno / Warehouse | 128-140 | 4 | wireframe + particles |
49
+ | `vj_dnb_jungle.rb` | Drum & Bass / Jungle | 170-180 | 3 | kick/snare/hihat split |
50
+ | `vj_ambient_chill_room.rb` | Ambient / Chill | 60-90 | 2 | beatless, drone-friendly |
51
+ | `vj_hiphop_cipher.rb` | HipHop / Cipher | 85-100 | 3 | text-forward |
52
+ | `vj_jpop_idol_live.rb` | J-POP / Idol | 130-180 | 4 | color fields + tap tempo |
53
+ | `vj_synthwave_retro.rb` | Synthwave / Retro | 100-120 | 3 | circle and line primitives |
54
+ | `vj_glitch_industrial.rb` | Glitch / Industrial | n/a | 3 | feedback + difference blend |
55
+ | `vj_festival_mainstage.rb` | EDM / Mainstage | 124-132 | 5 | uses `extends:` and `group` |
56
+
57
+ Use `examples/vj_festival_mainstage.yml` as a manifest pattern for file-audio
58
+ rehearsal. Replace `audio_file` with your set recording or switch to
59
+ `audio_source: mic` for live input.
@@ -0,0 +1,19 @@
1
+ # Example Assets
2
+
3
+ `complex_demo_loop.wav` is bundled for repeatable file-audio testing.
4
+
5
+ For logos or show-specific art, place your own files in this directory and
6
+ reference them from a scene:
7
+
8
+ ```ruby
9
+ layer :logo do
10
+ type :svg
11
+ file "assets/your_logo.svg"
12
+ fit :contain
13
+ map beat_pulse, to: :scale, range: 0.9..1.08
14
+ end
15
+ ```
16
+
17
+ No copyrighted venue logos, artist marks, photos, or fonts are bundled with
18
+ Vizcore examples. Keep those assets local to your project unless you have the
19
+ right to redistribute them.
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Visualizes the same audio features shown in the HUD inspector.
4
+ Vizcore.define do
5
+ audio_normalize mode: :adaptive, window: 2.0, target: 0.85, floor: 0.001
6
+
7
+ scene :audio_inspector do
8
+ layer :bars do
9
+ shader :audio_bars
10
+ param :bar_count, default: 32.0, range: 12.0..64.0, step: 1.0
11
+ param :floor_glow, default: 0.18, range: 0.0..1.0, step: 0.02
12
+ blend :screen
13
+ map amplitude, to: :floor_glow, gain: 1.6, range: 0.08..0.5
14
+ end
15
+
16
+ layer :peak_blob do
17
+ type :radial_blob
18
+ radius 0.28
19
+ wobble 0.35
20
+ blend :add
21
+ map amplitude, to: :radius, range: 0.22..0.58, curve: :sqrt
22
+ map fft_spectrum => :spectrum
23
+ map treble, to: :wobble, range: 0.2..1.2
24
+ end
25
+
26
+ layer :label do
27
+ type :text
28
+ content "AUDIO"
29
+ font_size 76
30
+ glow_strength 0.2
31
+ map beat_pulse, to: :glow_strength, range: 0.12..0.8
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ # File-audio friendly intro -> build -> drop flow.
4
+ Vizcore.define do
5
+ scene :intro do
6
+ layer :grid do
7
+ shader :neon_grid
8
+ opacity 0.75
9
+ map mid, to: :effect_intensity, range: 0.08..0.28
10
+ end
11
+
12
+ layer :title do
13
+ type :text
14
+ content "INTRO"
15
+ font_size 84
16
+ map beat_pulse, to: :glow_strength, range: 0.12..0.65
17
+ end
18
+ end
19
+
20
+ scene :build do
21
+ layer :rings do
22
+ shader :spectrum_rings
23
+ blend :screen
24
+ map bass, to: :effect_intensity, gain: 1.4, range: 0.16..0.5
25
+ end
26
+
27
+ layer :particles do
28
+ type :particle_field
29
+ count 2200
30
+ blend :add
31
+ map amplitude, to: :speed, range: 0.4..3.2
32
+ map treble, to: :sparkle, range: 0.0..0.9
33
+ end
34
+ end
35
+
36
+ scene :drop do
37
+ layer :tunnel do
38
+ shader :bass_tunnel
39
+ blend :screen
40
+ end
41
+
42
+ layer :flash do
43
+ shader :glitch_flash
44
+ blend :add
45
+ map beat_pulse, to: :intensity, range: 0.2..1.0, attack: 1.0, release: 0.08
46
+ end
47
+
48
+ layer :drop_text do
49
+ type :text
50
+ content "DROP"
51
+ font_size 122
52
+ blend :screen
53
+ map beat_pulse, to: :glow_strength, range: 0.3..1.0
54
+ end
55
+ end
56
+
57
+ transition from: :intro, to: :build do
58
+ trigger { beat_count >= 32 || frame_count >= 240 }
59
+ effect :crossfade, duration: 1.0
60
+ end
61
+
62
+ transition from: :build, to: :drop do
63
+ trigger { beat_count >= 64 || frame_count >= 480 }
64
+ effect :flash, duration: 0.35
65
+ end
66
+
67
+ key "i" do
68
+ switch_scene :intro
69
+ end
70
+
71
+ key "u" do
72
+ switch_scene :build
73
+ end
74
+
75
+ key "d" do
76
+ switch_scene :drop
77
+ end
78
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Kansai RubyKaigi visual: ruby crystal, water ripple, geometric pattern, and title.
4
+ Vizcore.define do
5
+ scene :kansai_rubykaigi do
6
+ layer :lake_ripple do
7
+ shader :liquid_wobble
8
+ wobble 0.18
9
+ warp 0.32
10
+ distortion 0.16
11
+ opacity 0.86
12
+ blend :screen
13
+ effect :feedback
14
+ effect_intensity 0.08
15
+
16
+ map bass, to: :wobble, gain: 0.9, range: 0.12..0.58, curve: :sqrt
17
+ map mid, to: :warp, gain: 1.2, range: 0.22..1.45
18
+ map high, to: :effect_intensity, range: 0.04..0.22
19
+ end
20
+
21
+ layer :kyoto_pattern do
22
+ shader :kaleidoscope
23
+ opacity 0.34
24
+ blend :add
25
+ vj_effect :mirror
26
+ effect_intensity 0.18
27
+
28
+ map mid, to: :effect_intensity, gain: 1.2, range: 0.08..0.42
29
+ end
30
+
31
+ layer :ruby_glow do
32
+ shader :ruby_crystal
33
+ facets 8.0
34
+ refraction 0.52
35
+ opacity 0.82
36
+ blend :screen
37
+ effect :bloom
38
+
39
+ map bass, to: :refraction, gain: 0.9, range: 0.34..0.86, curve: :sqrt
40
+ map beat_pulse, to: :effect_intensity, range: 0.12..0.72
41
+ end
42
+
43
+ layer :spark_line do
44
+ type :particle_field
45
+ count 1800
46
+ force_field :vortex
47
+ turbulence 0.18
48
+ blend :add
49
+
50
+ map amplitude, to: :speed, gain: 2.2, range: 0.25..4.2, curve: :sqrt
51
+ map bass, to: :size, gain: 2.0, range: 1.4..5.4
52
+ map hihat, to: :sparkle, gain: 2.4, range: 0.0..1.0
53
+ end
54
+
55
+ layer :event_title do
56
+ type :text
57
+ content "KANSAI RUBYKAIGI"
58
+ font "IBM Plex Sans"
59
+ font_size 66
60
+ align :center
61
+ color "#fff4e6"
62
+ stroke width: 2, color: "#120617"
63
+ shadow color: "#ff335f", blur: 20
64
+ glow_strength 0.28
65
+ blend :screen
66
+
67
+ map beat_pulse, to: :glow_strength, range: 0.2..0.92
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Short scene intended for live-coding demos.
4
+ Vizcore.define do
5
+ scene :main do
6
+ layer :pulse do
7
+ type :radial_blob
8
+ radius 0.34
9
+ wobble 0.2
10
+ map amplitude, to: :radius, range: 0.22..0.7, curve: :sqrt
11
+ map fft_spectrum => :spectrum
12
+ end
13
+
14
+ layer :beat_label do
15
+ type :text
16
+ content "VIZCORE"
17
+ font_size 86
18
+ glow_strength 0.2
19
+ map beat_pulse, to: :glow_strength, range: 0.12..0.85
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ # MIDI controller showcase: pads switch scenes, knobs control global shader uniforms.
4
+ Vizcore.define do
5
+ set :global_intensity, 0.65
6
+ set :global_color, 0.15
7
+
8
+ midi :controller, device: :default
9
+
10
+ scene :midi_warmup do
11
+ layer :ribbon do
12
+ shader :waveform_ribbon
13
+ blend :screen
14
+ effect :bloom
15
+ map mid, to: :effect_intensity, range: 0.08..0.24
16
+ end
17
+
18
+ layer :title do
19
+ type :text
20
+ content "MIDI CONTROL"
21
+ font_size 72
22
+ color "#e8fbff"
23
+ glow_strength 0.16
24
+ blend :screen
25
+ map beat_pulse, to: :glow_strength, range: 0.12..0.65
26
+ end
27
+ end
28
+
29
+ scene :midi_drop do
30
+ layer :stars do
31
+ shader :starfield
32
+ blend :screen
33
+ effect :glitch
34
+ map high, to: :effect_intensity, range: 0.1..0.65
35
+ end
36
+
37
+ layer :drop_text do
38
+ type :text
39
+ content "DROP"
40
+ font_size 118
41
+ color "#fff1d6"
42
+ glow_strength 0.25
43
+ blend :add
44
+ map beat_pulse, to: :glow_strength, range: 0.25..1.0
45
+ end
46
+ end
47
+
48
+ scene :midi_crystal do
49
+ layer :crystal do
50
+ shader :ruby_crystal
51
+ facets 7.0
52
+ refraction 0.44
53
+ blend :screen
54
+ map bass, to: :refraction, gain: 0.9, range: 0.32..0.82
55
+ map mid, to: :facets, gain: 1.8, range: 5.0..10.0
56
+ end
57
+ end
58
+
59
+ midi_map note: 36 do
60
+ switch_scene :midi_warmup
61
+ end
62
+
63
+ midi_map note: 37 do
64
+ switch_scene :midi_drop
65
+ end
66
+
67
+ midi_map note: 38 do
68
+ switch_scene :midi_crystal
69
+ end
70
+
71
+ midi_map cc: 1 do |value|
72
+ set :global_intensity, value / 127.0
73
+ end
74
+
75
+ midi_map cc: 2 do |value|
76
+ set :global_color, value / 127.0
77
+ end
78
+ end
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Vizcore.define do
4
+ set :global_intensity, 0.65
5
+
4
6
  midi :controller, device: :default
5
7
 
6
8
  scene :warmup do
7
9
  layer :grid do
8
- shader :neon_grid
10
+ shader :waveform_ribbon
9
11
  map frequency_band(:mid) => :intensity
10
12
  end
11
13
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Parser-themed visual sketch: token flow, AST energy, and reduce flashes.
4
+ Vizcore.define do
5
+ scene :parser_visualizer do
6
+ layer :token_stream do
7
+ shader :waveform_ribbon
8
+ blend :screen
9
+ effect :crt
10
+ effect_intensity 0.18
11
+ map amplitude, to: :effect_intensity, range: 0.08..0.32
12
+ end
13
+
14
+ layer :ast_nodes do
15
+ type :particle_field
16
+ count 2200
17
+ force_field :vortex
18
+ turbulence 0.28
19
+ blend :add
20
+ map bass, to: :size, gain: 3.0, range: 1.8..6.5, curve: :sqrt
21
+ map mid, to: :speed, gain: 2.0, range: 0.4..4.2
22
+ map hihat, to: :sparkle, gain: 2.2, range: 0.0..1.0
23
+ end
24
+
25
+ layer :reduce_flash do
26
+ shader :ruby_crystal
27
+ facets 7.0
28
+ refraction 0.42
29
+ blend :add
30
+ effect :bloom
31
+ map kick, to: :effect_intensity, gain: 2.0, range: 0.05..0.55
32
+ map beat_pulse, to: :refraction, range: 0.32..0.86
33
+ end
34
+
35
+ layer :parser_label do
36
+ type :text
37
+ content "SHIFT -> REDUCE -> ACCEPT"
38
+ font "IBM Plex Mono"
39
+ font_size 58
40
+ align :center
41
+ fill "#d9ffe8"
42
+ stroke width: 2, color: "#06111f"
43
+ glow_strength 0.26
44
+ blend :screen
45
+ map beat_pulse, to: :glow_strength, range: 0.18..0.9
46
+ end
47
+ end
48
+ end