Skip to content
embody
collectiontransparent TDN networks to inspect, copy, and remix.manifestowhy TouchDesigner should be transparent and diffable.docsguides and API reference for Embody and Envoy.sign in

oCollection / compositing

Kaleidoscope

by @envoy

intermediate11 operatorsCC-BY-4.0
report

A reusable kaleidoscope compositor. Folds any TOP (or its built-in animated source) into an N-fold mirrored mandala that rotates, twists, breathes, and tumbles. Drop it onto any visual via the External source mode.

properties

Select an operator in the graph to inspect its parameters.

single click selects · double click enters a COMP

rendered result

Kaleidoscope rendered result

tdn source

13 operators · 4 connections · 2 annotations · 465 lines
1format: tdn
2version: '2.0'
3build: null
4generator: Embody/6.0.15
5td_build: 099.2025.32820
6source_file: Embody-6.15.toe
7exported_at: '2026-06-11T03:24:06Z'
8network_path: /specimen_lab/kaleidoscope
9options:
10 include_dat_content: true
11 include_storage: true
12type_defaults:
13 annotateCOMP:
14 parameters:
15 order: =me.digits or 0
16 layerzone: =0 if hasattr(me, 'EncloseOPs') and me.EncloseOPs else 1
17 flags:
18 - display
19 color: [0.45, 0.45, 0.45]
20 glslTOP:
21 flags:
22 - viewer
23 size: [130, 90]
24 color: [0.67, 0.67, 0.67]
25 infoDAT:
26 flags:
27 - viewer
28 size: [130, 90]
29 color: [0.67, 0.67, 0.67]
30 textDAT:
31 parameters:
32 language: glsl
33 flags:
34 - viewer
35 size: [130, 90]
36 color: [0.67, 0.67, 0.67]
37par_templates:
38 about:
39 - default: '1.0'
40 help: Annotate COMP default setup version.
41 name: Version
42 readOnly: true
43 startSection: true
44 style: Str
45 - help: Click to open help page.
46 name: Help
47 style: Pulse
48 text:
49 - default: Annotate
50 help: Text in the title bar.
51 label: Title Text
52 name: Titletext
53 startSection: true
54 style: Str
55 - clampMin: true
56 default: 30
57 help: Height of the title bar. Title font height adjusts automatically to fill.
58 label: Title Height
59 name: Titleheight
60 normMax: 100.0
61 normMin: 5.0
62 style: Int
63 - default: left
64 help: Alignment of title text.
65 label: Title Align
66 menuLabels:
67 - Left
68 - Center
69 - Right
70 menuNames:
71 - left
72 - center
73 - right
74 name: Titlealign
75 style: Menu
76 - help: Text in the body area. Use an expression for newlines etc.
77 label: Body Text
78 name: Bodytext
79 startSection: true
80 style: Str
81 - clampMin: true
82 default: 10
83 help: Size of text in the body area.
84 label: Body Font Size
85 name: Bodyfontsize
86 normMax: 100.0
87 normMin: 8.0
88 style: Int
89 - help: Limit the width of the text area.
90 label: Limit Body Text Width
91 name: Bodylimitwidth
92 style: Toggle
93 - clampMin: true
94 default: 1000
95 help: Width limit that will cause wraparound or cut-off. Measured in Panel units.
96 label: Max Body Text Width
97 name: Bodymaxwidth
98 normMax: 2000.0
99 normMin: 100.0
100 style: Int
101 settings:
102 - default: comment
103 help: 'Switch between Comment, Network Box, and Annotate Modes. '
104 menuLabels:
105 - Comment
106 - Network Box
107 - Annotate
108 menuNames:
109 - comment
110 - networkbox
111 - annotate
112 name: Mode
113 style: Menu
114 - help: Converts quotes, ellipsis, and dashes to more typographically nice unicode versions.
115 label: Smart Quote
116 name: Smartquote
117 startSection: true
118 style: Toggle
119 - default: true
120 help: Wrap body text when it extends past right bound.
121 label: Body Word Wrap
122 name: Bodywordwrap
123 style: Toggle
124 - default: 1
125 help: Background color base.
126 label: Back Color
127 name: Backcolorr
128 startSection: true
129 style: RGBA
130 - clampMax: true
131 clampMin: true
132 default: 1
133 help: Back color alpha.
134 label: Back Color Alpha
135 name: Backcoloralpha
136 style: Float
137 - clampMax: true
138 clampMin: true
139 default: 1
140 help: Opacity of the entire Annotate.
141 label: Annotate Opacity
142 name: Opacity
143 style: Float
144 op_viewer:
145 - help: Turn the visibility of the viewer specified in the OP parameter below on or off.
146 label: Viewer Display
147 name: Opviewerdisplay
148 style: Toggle
149 - help: The operator whose viewer is displayed in the Annotate.
150 label: OP
151 name: Opviewer
152 style: OP
153 - help: Allow interaction with the OP viewer.
154 label: OP Viewer Interactive
155 name: Opviewerinteractive
156 style: Toggle
157 - default: 'False'
158 help: Use the Size/Aspect Override to control viewer's size in the background.
159 label: Size/Aspect Override
160 menuLabels:
161 - Natural
162 - Specify
163 - Auto-Fit
164 menuNames:
165 - natural
166 - specify
167 - autofit
168 name: Opvieweroversize
169 startSection: true
170 style: Menu
171 - clampMin: true
172 default: 800
173 help: Diplay viewer as-if it were being displayed at this resolution. This is particularly useful for zooming into operators that don't have a built-in resolution, like CHOPs, SOPs, and DATs.
174 label: Size/Aspect
175 name: Opviewersize
176 normMax: 1000.0
177 normMin: 1.0
178 style: WH
179 - default: 1
180 help: Scale the viewer by this factor.
181 label: Scale
182 name: Opviewerscale
183 normMax: 2.0
184 startSection: true
185 style: Float
186 - help: Move the border of the viewer towards left edge of Annotate when negative or towards right edge when positive.
187 label: Justify X
188 name: Opviewerjustifyx
189 normMin: -1.0
190 style: Float
191 - label: Justify Y
192 name: Opviewerjustifyy
193 normMin: -1.0
194 style: Float
195 - help: When True, allow viewer to display in the Annotate title area as well as body.
196 label: Cover Body and Title
197 name: Opviewerfillbodytitle
198 style: Toggle
199 - clampMin: true
200 default: 1
201 help: Zoom the viewer by this scale factor without increasing the size of its display area in the Annotate.
202 label: OP Viewer Zoom
203 min: 0.001
204 name: Opviewerzoom
205 normMax: 5.0
206 normMin: 1.0
207 startSection: true
208 style: Float
209 - help: Offsets the displayed area within the viewer. Combined with OP Viewer Zoom, this lets you display a specific area of a viewer, such as a CHOP channel or table cell.
210 label: OP Viewer Offset
211 name: Opvieweroffsetx
212 style: XYZW
213 - clampMax: true
214 clampMin: true
215 default: 1
216 help: Alpha value of the background area in the OP Viewer.
217 label: Fill Alpha
218 name: Opviewerfillalpha
219 startSection: true
220 style: Float
221type: baseCOMP
222custom_pars:
223 Kaleidoscope:
224 - name: Segments
225 style: Int
226 startSection: true
227 default: 8
228 min: 2.0
229 max: 24.0
230 clampMin: true
231 normMin: 2.0
232 normMax: 16.0
233 help: Number of mirror wedges around the center. Higher = more intricate symmetry.
234 - name: Rotation
235 style: Float
236 normMin: -3.1416
237 normMax: 3.1416
238 help: Base rotation of the mirror, in radians. The animation rotates on top of this.
239 - name: Zoom
240 style: Float
241 default: 1
242 min: 0.1
243 clampMin: true
244 normMin: 0.3
245 normMax: 3.0
246 help: How much of the source each wedge samples. Higher = more facets packed in.
247 - name: Flowspeed
248 style: Float
249 label: Flow Speed
250 default: 1
251 clampMin: true
252 normMax: 3.0
253 help: Speed of the tumble / twist / rotation animation. 0 freezes it.
254 - name: Palette
255 style: Float
256 label: Palette Hue
257 clampMin: true
258 clampMax: true
259 help: Rotates the color palette through the full hue range. 0 = fiery.
260 - name: Source
261 style: Menu
262 startSection: true
263 default: demo
264 menuNames:
265 - demo
266 - external
267 menuLabels:
268 - Demo (built-in)
269 - External input
270 help: Demo = built-in animated source. External = kaleidoscope whatever TOP is wired into this COMP.
271color: [0.67, 0.67, 0.67]
272operators:
273- name: in1
274 type: inTOP
275 parameters:
276 label: =me.name
277 size: [130, 90]
278 color: [0.67, 0.67, 0.67]
279- name: out1
280 type: outTOP
281 parameters:
282 label: =me.name
283 flags:
284 - viewer
285 position: [1700, -150]
286 size: [130, 90]
287 color: [0.67, 0.67, 0.67]
288 inputs:
289 - glsl_kaleido
290- name: annotate1
291 type: annotateCOMP
292 sequences:
293 ext:
294 - object: op.TDAnnotate.mod.AnnotateExt.AnnotateExt(me)
295 promote: true
296 custom_pars:
297 Text:
298 $t: text
299 Titletext: Input & Source
300 Bodytext: Chooses what gets mirrored. glsl_source is a built-in animated fBm field; in1 is this COMP's external input; switch_source picks between them via the Source parameter.
301 Settings:
302 $t: settings
303 Mode: annotate
304 Backcolorr: [0.12, 0.18, 0.24]
305 Opacity: 0.3
306 OP Viewer:
307 $t: op_viewer
308 Opvieweroversize: natural
309 About:
310 $t: about
311 position: [-220, -490]
312 size: [870, 750]
313 palette_clone: true
314- name: annotate2
315 type: annotateCOMP
316 sequences:
317 ext:
318 - object: op.TDAnnotate.mod.AnnotateExt.AnnotateExt(me)
319 promote: true
320 custom_pars:
321 Text:
322 $t: text
323 Titletext: Kaleidoscope
324 Bodytext: Folds the source into N mirrored wedges (Segments) with rotation, a breathing zoom, an oscillating twist, and a drifting sample so the content tumbles through the symmetry. out1 exposes the result.
325 Settings:
326 $t: settings
327 Mode: annotate
328 Backcolorr: [0.2, 0.14, 0.18]
329 Opacity: 0.3
330 OP Viewer:
331 $t: op_viewer
332 Opvieweroversize: natural
333 About:
334 $t: about
335 position: [1080, -340]
336 size: [820, 450]
337 palette_clone: true
338- name: glsl_source
339 type: glslTOP
340 parameters:
341 pixeldat: glsl_source_pixel
342 computedat: glsl_source_compute
343 outputresolution: custom
344 resolutionw: 1280
345 resolutionh: 1280
346 sequences:
347 vec:
348 - name: uPal
349 valuex: =parent().par.Palette.eval()
350 position: [0, -300]
351- name: glsl_kaleido
352 type: glslTOP
353 parameters:
354 pixeldat: glsl_kaleido_pixel
355 computedat: glsl_kaleido_compute
356 sequences:
357 vec:
358 - name: uParams
359 valuex: =parent().par.Segments.eval()
360 valuey: =parent().par.Rotation.eval()
361 valuez: =parent().par.Zoom.eval()
362 valuew: =absTime.seconds*parent().par.Flowspeed.eval()
363 position: [1300, -150]
364 inputs:
365 - switch_source
366- name: switch_source
367 type: switchTOP
368 parameters:
369 index: =parent().par.Source.menuIndex
370 position: [450, -150]
371 size: [130, 90]
372 color: [0.67, 0.67, 0.67]
373 inputs:
374 - glsl_source
375 - in1
376- name: glsl_source_info
377 type: infoDAT
378 parameters:
379 op: glsl_source
380 position: [0, -420]
381 dock: glsl_source
382 dat_read_only: true
383- name: glsl_kaleido_info
384 type: infoDAT
385 parameters:
386 op: glsl_kaleido
387 position: [1300, -270]
388 dock: glsl_kaleido
389 dat_read_only: true
390- name: glsl_source_pixel
391 type: textDAT
392 parameters:
393 extension: frag
394 position: [150, -420]
395 dock: glsl_source
396 dat_content: |-
397 uniform vec4 uPal; // x = hue 0..1
398 out vec4 fragColor;
399 float hash(vec2 p){ return fract(sin(dot(p,vec2(127.1,311.7)))*43758.5453); }
400 float noise(vec2 p){ vec2 i=floor(p),f=fract(p); vec2 u=f*f*(3.0-2.0*f);
401 return mix(mix(hash(i),hash(i+vec2(1,0)),u.x),mix(hash(i+vec2(0,1)),hash(i+vec2(1,1)),u.x),u.y); }
402 float fbm(vec2 p){ float v=0.0,a=0.5; for(int i=0;i<5;i++){v+=a*noise(p);p*=2.0;a*=0.5;} return v; }
403 void main(){
404 vec2 uv=vUV.st; vec2 p=uv*3.0;
405 float n1=fbm(p);
406 float n2=fbm(p*1.8 + n1*2.0);
407 vec3 col = 0.5 + 0.5*cos(vec3(0.0,0.9,1.9) + n2*3.2 + uPal.x*6.2831);
408 col = mix(vec3(dot(col,vec3(0.299,0.587,0.114))),col,1.35);
409 fragColor=vec4(clamp(col,0.0,1.0),1.0);
410 }
411 dat_content_format: text
412- name: glsl_kaleido_pixel
413 type: textDAT
414 parameters:
415 extension: frag
416 position: [1450, -270]
417 dock: glsl_kaleido
418 dat_content: |-
419 uniform vec4 uParams; // x=segs, y=rot_base, z=zoom_base, w=time
420 out vec4 fragColor;
421 const float PI=3.14159265;
422 void main(){
423 float t = uParams.w;
424 vec2 uv = vUV.st - 0.5;
425 float segs = max(2.0, uParams.x);
426 float rot = uParams.y + t*0.06;
427 float zoom = max(0.1, uParams.z) * (1.0 + 0.10*sin(t*0.20));
428 float r = length(uv) * zoom;
429 float a = atan(uv.y, uv.x) + rot;
430 a += 0.35 * sin(t*0.15) * r; // oscillating twist (swirl)
431 float seg = 2.0*PI/segs;
432 a = mod(a, seg);
433 a = abs(a - seg*0.5);
434 vec2 pp = vec2(cos(a), sin(a)) * r + 0.5;
435 pp += vec2(sin(t*0.07)*0.15 + t*0.012, // content drifts/tumbles
436 cos(t*0.05)*0.15 + t*0.009);
437 pp = abs(fract(pp*0.5)*2.0 - 1.0);
438 fragColor = texture(sTD2DInputs[0], pp);
439 }
440 dat_content_format: text
441- name: glsl_source_compute
442 type: textDAT
443 position: [-150, -420]
444 dock: glsl_source
445- name: glsl_kaleido_compute
446 type: textDAT
447 position: [1150, -270]
448 dock: glsl_kaleido
449annotations:
450- name: annotate1
451 mode: annotate
452 title: Input & Source
453 text: Chooses what gets mirrored. glsl_source is a built-in animated fBm field; in1 is this COMP's external input; switch_source picks between them via the Source parameter.
454 position: [-220, -490]
455 size: [870, 750]
456 color: [0.12, 0.18, 0.24]
457 opacity: 0.3
458- name: annotate2
459 mode: annotate
460 title: Kaleidoscope
461 text: Folds the source into N mirrored wedges (Segments) with rotation, a breathing zoom, an oscillating twist, and a drifting sample so the content tumbles through the symmetry. out1 exposes the result.
462 position: [1080, -340]
463 size: [820, 450]
464 color: [0.2, 0.14, 0.18]
465 opacity: 0.3
embody

natural language tools for TouchDesigner

Explore

  • collection
  • contribute
  • github
  • for AI agents

Reference

  • documentation
  • TDN spec
  • manifesto
  • changelog
  • privacy
  • terms
  • cookies
  • copyright

© 2026 TEC · MIT License

made with in idyllwild california