1use {
6 log::trace,
7 std::collections::HashMap,
8 vk_graph::{
9 Graph,
10 driver::{
11 ash::vk,
12 compute::{ComputePipeline, ComputePipelineInfo},
13 device::Device,
14 image::ImageInfo,
15 shader::Shader,
16 sync::AccessType,
17 },
18 node::{AnyImageNode, ImageLeaseNode},
19 pool::{Pool as _, hash::HashPool},
20 },
21 vk_shader_macros::include_glsl,
22};
23
24#[allow(missing_docs)]
25#[derive(Clone, Copy, Debug)]
26pub enum Transition {
27 Angular {
28 starting_angle: f32,
29 },
30 Bounce {
31 shadow_height: f32,
32 bounces: f32,
33 shadow_colour: [f32; 4],
34 },
35 BowTieHorizontal,
36 BowTieVertical,
37 BowTieWithParameter {
38 adjust: f32,
39 reverse: bool,
40 },
41 Burn {
42 color: [f32; 3],
43 },
44 ButterflyWaveScrawler {
45 amplitude: f32,
46 waves: f32,
47 color_separation: f32,
48 },
49 CannabisLeaf,
50 Circle {
51 center: [f32; 2],
52 background_color: [f32; 3],
53 },
54 CircleCrop {
55 background_color: [f32; 4],
56 },
57 CircleOpen {
58 smoothness: f32,
59 opening: bool,
60 },
61 ColorDistance {
62 power: f32,
63 },
64 ColorPhase {
65 from_step: [f32; 4],
66 to_step: [f32; 4],
67 },
68 CoordFromIn,
69 CrazyParametricFun {
70 a: f32,
71 b: f32,
72 amplitude: f32,
73 smoothness: f32,
74 },
75 Crosshatch {
76 center: [f32; 2],
77 threshold: f32,
78 fade_edge: f32,
79 },
80 CrossWarp,
81 CrossZoom {
82 strength: f32,
83 },
84 Cube {
85 perspective: f32,
86 unzoom: f32,
87 reflection: f32,
88 floating: f32,
89 },
90 Directional {
91 direction: [f32; 2],
92 },
93 DirectionalEasing {
94 direction: [f32; 2],
95 },
96 DirectionalWarp {
97 direction: [f32; 2],
98 },
99 DirectionalWipe {
100 smoothness: f32,
101 direction: [f32; 2],
102 },
103 Displacement {
104 displacement_map: AnyImageNode,
105 strength: f32,
106 },
107 DoomScreen {
108 bars: i32,
110
111 amplitude: f32,
114
115 noise: f32,
117
118 frequency: f32,
120
121 drip_scale: f32,
124 },
125 Doorway {
126 reflection: f32,
127 perspective: f32,
128 depth: f32,
129 },
130 Dreamy,
131 DreamyZoom {
132 rotation: f32,
134
135 scale: f32,
137 },
138 FadeColor {
139 color_phase: f32,
141
142 color: [f32; 3],
143 },
144 Fade,
145 FadeGrayscale {
146 intensity: f32,
149 },
150 FilmBurn {
151 seed: f32,
152 },
153 Flyeye {
154 size: f32,
155 zoom: f32,
156 color_separation: f32,
157 },
158 GlitchDisplace,
159 GlitchMemories,
160 GridFlip {
161 pause: f32,
162 size: [i32; 2],
163 background_color: [f32; 4],
164 divider_width: f32,
165 randomness: f32,
166 },
167 Heart,
168 Hexagonalize {
169 steps: i32,
170 horizontal_hexagons: f32,
171 },
172 InvertedPageCurl,
173 Kaleidoscope {
174 speed: f32,
175 angle: f32,
176 power: f32,
177 },
178 LeftRight,
179 LinearBlur {
180 intensity: f32,
181 },
182 Luma {
183 luma_map: AnyImageNode,
184 },
185 LuminanceMelt {
186 direction: bool,
188
189 threshold: f32,
191
192 above: bool,
194 },
195 Morph {
196 strength: f32,
197 },
198 Mosaic {
199 end: [i32; 2],
200 },
201 Multiply,
202 Overexposure {
203 strength: f32,
204 },
205 Perlin {
206 scale: f32,
207 smoothness: f32,
208 seed: f32,
209 },
210 Pinwheel {
211 speed: f32,
212 },
213 Pixelize {
214 steps: i32,
216
217 squares_min: [i32; 2],
219 },
220 PolarFunction {
221 segments: i32,
222 },
223 PolkaDotsCurtain {
224 dots: f32,
225 center: [f32; 2],
226 },
227 PowerKaleido {
228 scale: f32,
229 z: f32,
230 speed: f32,
231 },
232 Radial {
233 smoothness: f32,
234 },
235 RandomNoisex,
236 RandomSquares {
237 smoothness: f32,
238 size: [i32; 2],
239 },
240 Ripple {
241 amplitude: f32,
242 speed: f32,
243 },
244 Rotate,
245 RotateScale {
246 rotations: f32,
247 center: [f32; 2],
248 background_color: [f32; 4],
249 scale: f32,
250 },
251 ScaleIn,
252 SimpleZoom {
253 zoom_quickness: f32,
254 },
255 SquaresWire {
256 smoothness: f32,
257 squares: [i32; 2],
258 direction: [f32; 2],
259 },
260 Squeeze {
261 color_separation: f32,
262 },
263 StereoViewer {
264 zoom: f32,
266
267 corner_radius: f32,
269 },
270 Swap {
271 reflection: f32,
272 perspective: f32,
273 depth: f32,
274 },
275 Swirl,
276 TangentMotionBlur,
277 TopBottom,
278 TvStatic {
279 offset: f32,
280 },
281 UndulatingBurnOut {
282 smoothness: f32,
283 center: [f32; 2],
284 color: [f32; 3],
285 },
286 WaterDrop {
287 amplitude: f32,
288 speed: f32,
289 },
290 Wind {
291 size: f32,
292 },
293 WindowBlinds,
294 WindowSlice {
295 count: f32,
296 smoothness: f32,
297 },
298 WipeDown,
299 WipeLeft,
300 WipeRight,
301 WipeUp,
302 ZoomInCircles,
303 ZoomLeftWipe {
304 zoom_quickness: f32,
305 },
306 ZoomRightWipe {
307 zoom_quickness: f32,
308 },
309}
310
311impl Transition {
312 fn ty(&self) -> TransitionType {
313 match self {
314 Self::Angular { .. } => TransitionType::Angular,
315 Self::Bounce { .. } => TransitionType::Bounce,
316 Self::BowTieHorizontal => TransitionType::BowTieHorizontal,
317 Self::BowTieVertical => TransitionType::BowTieVertical,
318 Self::BowTieWithParameter { .. } => TransitionType::BowTieWithParameter,
319 Self::Burn { .. } => TransitionType::Burn,
320 Self::ButterflyWaveScrawler { .. } => TransitionType::ButterflyWaveScrawler,
321 Self::CannabisLeaf { .. } => TransitionType::CannabisLeaf,
322 Self::Circle { .. } => TransitionType::Circle,
323 Self::CircleCrop { .. } => TransitionType::CircleCrop,
324 Self::CircleOpen { .. } => TransitionType::CircleOpen,
325 Self::ColorDistance { .. } => TransitionType::ColorDistance,
326 Self::ColorPhase { .. } => TransitionType::ColorPhase,
327 Self::CoordFromIn => TransitionType::CoordFromIn,
328 Self::CrazyParametricFun { .. } => TransitionType::CrazyParametricFun,
329 Self::Crosshatch { .. } => TransitionType::Crosshatch,
330 Self::CrossWarp => TransitionType::CrossWarp,
331 Self::CrossZoom { .. } => TransitionType::CrossZoom,
332 Self::Cube { .. } => TransitionType::Cube,
333 Self::Directional { .. } => TransitionType::Directional,
334 Self::DirectionalEasing { .. } => TransitionType::DirectionalEasing,
335 Self::DirectionalWarp { .. } => TransitionType::DirectionalWarp,
336 Self::DirectionalWipe { .. } => TransitionType::DirectionalWipe,
337 Self::Displacement { .. } => TransitionType::Displacement,
338 Self::DoomScreen { .. } => TransitionType::DoomScreen,
339 Self::Doorway { .. } => TransitionType::Doorway,
340 Self::Dreamy => TransitionType::Dreamy,
341 Self::DreamyZoom { .. } => TransitionType::DreamyZoom,
342 Self::FadeColor { .. } => TransitionType::FadeColor,
343 Self::Fade => TransitionType::Fade,
344 Self::FadeGrayscale { .. } => TransitionType::FadeGrayscale,
345 Self::FilmBurn { .. } => TransitionType::FilmBurn,
346 Self::Flyeye { .. } => TransitionType::Flyeye,
347 Self::GlitchDisplace => TransitionType::GlitchDisplace,
348 Self::GlitchMemories => TransitionType::GlitchMemories,
349 Self::GridFlip { .. } => TransitionType::GridFlip,
350 Self::Heart => TransitionType::Heart,
351 Self::Hexagonalize { .. } => TransitionType::Hexagonalize,
352 Self::InvertedPageCurl => TransitionType::InvertedPageCurl,
353 Self::Kaleidoscope { .. } => TransitionType::Kaleidoscope,
354 Self::LeftRight => TransitionType::LeftRight,
355 Self::LinearBlur { .. } => TransitionType::LinearBlur,
356 Self::Luma { .. } => TransitionType::Luma,
357 Self::LuminanceMelt { .. } => TransitionType::LuminanceMelt,
358 Self::Morph { .. } => TransitionType::Morph,
359 Self::Mosaic { .. } => TransitionType::Mosaic,
360 Self::Multiply => TransitionType::Multiply,
361 Self::Overexposure { .. } => TransitionType::Overexposure,
362 Self::Perlin { .. } => TransitionType::Perlin,
363 Self::Pinwheel { .. } => TransitionType::Pinwheel,
364 Self::Pixelize { .. } => TransitionType::Pixelize,
365 Self::PolarFunction { .. } => TransitionType::PolarFunction,
366 Self::PolkaDotsCurtain { .. } => TransitionType::PolkaDotsCurtain,
367 Self::PowerKaleido { .. } => TransitionType::PowerKaleido,
368 Self::Radial { .. } => TransitionType::Radial,
369 Self::RandomNoisex => TransitionType::RandomNoisex,
370 Self::RandomSquares { .. } => TransitionType::RandomSquares,
371 Self::Ripple { .. } => TransitionType::Ripple,
372 Self::Rotate => TransitionType::Rotate,
373 Self::RotateScale { .. } => TransitionType::RotateScale,
374 Self::ScaleIn => TransitionType::ScaleIn,
375 Self::SimpleZoom { .. } => TransitionType::SimpleZoom,
376 Self::SquaresWire { .. } => TransitionType::SquaresWire,
377 Self::Squeeze { .. } => TransitionType::Squeeze,
378 Self::StereoViewer { .. } => TransitionType::StereoViewer,
379 Self::Swap { .. } => TransitionType::Swap,
380 Self::Swirl => TransitionType::Swirl,
381 Self::TangentMotionBlur => TransitionType::TangentMotionBlur,
382 Self::TopBottom => TransitionType::TopBottom,
383 Self::TvStatic { .. } => TransitionType::TvStatic,
384 Self::UndulatingBurnOut { .. } => TransitionType::UndulatingBurnOut,
385 Self::WaterDrop { .. } => TransitionType::WaterDrop,
386 Self::Wind { .. } => TransitionType::Wind,
387 Self::WindowBlinds => TransitionType::WindowBlinds,
388 Self::WindowSlice { .. } => TransitionType::WindowSlice,
389 Self::WipeDown => TransitionType::WipeDown,
390 Self::WipeLeft => TransitionType::WipeLeft,
391 Self::WipeRight => TransitionType::WipeRight,
392 Self::WipeUp => TransitionType::WipeUp,
393 Self::ZoomInCircles => TransitionType::ZoomInCircles,
394 Self::ZoomLeftWipe { .. } => TransitionType::ZoomLeftWipe,
395 Self::ZoomRightWipe { .. } => TransitionType::ZoomRightWipe,
396 }
397 }
398}
399
400pub struct TransitionPipeline {
402 cache: HashPool,
403 pipelines: HashMap<TransitionType, ComputePipeline>,
404}
405
406impl TransitionPipeline {
407 pub fn new(device: &Device) -> Self {
409 let cache = HashPool::new(device);
410 let pipelines = Default::default();
411
412 Self { cache, pipelines }
413 }
414
415 pub fn apply(
417 &mut self,
418 graph: &mut Graph,
419 a_image: impl Into<AnyImageNode>,
420 b_image: impl Into<AnyImageNode>,
421 transition: Transition,
422 progress: f32,
423 ) -> ImageLeaseNode {
424 let a_image = a_image.into();
425 let b_image = b_image.into();
426
427 let a_info = graph.resource(a_image).info;
428 let b_info = graph.resource(b_image).info;
429
430 let dest_info = ImageInfo::image_2d(
431 a_info.width.max(b_info.width),
432 a_info.height.max(b_info.height),
433 vk::Format::R8G8B8A8_UNORM,
434 vk::ImageUsageFlags::SAMPLED
435 | vk::ImageUsageFlags::STORAGE
436 | vk::ImageUsageFlags::TRANSFER_DST
437 | vk::ImageUsageFlags::TRANSFER_SRC,
438 );
439 let dest_image = graph.bind_resource(
440 self.cache
441 .resource(dest_info)
442 .expect("missing transition image"),
443 );
444
445 self.apply_to(graph, a_image, b_image, dest_image, transition, progress);
446
447 dest_image
448 }
449
450 pub fn apply_to(
452 &mut self,
453 graph: &mut Graph,
454 a_image: impl Into<AnyImageNode>,
455 b_image: impl Into<AnyImageNode>,
456 dest_image: impl Into<AnyImageNode>,
457 transition: Transition,
458 progress: f32,
459 ) {
460 let a_image = a_image.into();
461 let b_image = b_image.into();
462 let dest_image = dest_image.into();
463 let progress = progress.clamp(0.0, 1.0);
464
465 let dest_info = graph.resource(dest_image).info;
466
467 let transition_ty = transition.ty();
469 let pipeline = self.pipeline(transition_ty);
470
471 let mut push_consts = Vec::with_capacity(128);
472 push_consts.extend_from_slice(&progress.to_ne_bytes());
473
474 extend_push_constants(transition, &mut push_consts);
475
476 graph
477 .begin_cmd()
478 .debug_name(format!("transition {transition_ty:?}"))
479 .bind_pipeline(pipeline)
480 .shader_resource_access(0, a_image, AccessType::ComputeShaderReadOther)
481 .shader_resource_access(1, b_image, AccessType::ComputeShaderReadOther)
482 .shader_resource_access(2, dest_image, AccessType::ComputeShaderWrite)
483 .record_cmd(move |cmd| {
484 cmd.push_constants(0, &push_consts)
485 .dispatch(dest_info.width, dest_info.height, 1);
486 });
487 }
488
489 fn pipeline(&mut self, transition_ty: TransitionType) -> &ComputePipeline {
490 self.pipelines.entry(transition_ty).or_insert_with(|| {
491 trace!("creating {transition_ty:?}");
492
493 ComputePipeline::create(
494 &self.cache.device,
495 ComputePipelineInfo::default(),
496 Shader::new_compute(match transition_ty {
497 TransitionType::Angular => {
498 include_glsl!("res/shader/transition/angular.comp").as_slice()
499 }
500 TransitionType::Bounce => {
501 include_glsl!("res/shader/transition/bounce.comp").as_slice()
502 }
503 TransitionType::BowTieHorizontal => {
504 include_glsl!("res/shader/transition/bow_tie_horizontal.comp").as_slice()
505 }
506 TransitionType::BowTieVertical => {
507 include_glsl!("res/shader/transition/bow_tie_vertical.comp").as_slice()
508 }
509 TransitionType::BowTieWithParameter => {
510 include_glsl!("res/shader/transition/bow_tie_with_parameter.comp",)
511 .as_slice()
512 }
513 TransitionType::Burn => {
514 include_glsl!("res/shader/transition/burn.comp").as_slice()
515 }
516 TransitionType::ButterflyWaveScrawler => {
517 include_glsl!("res/shader/transition/butterfly_wave_scrawler.comp",)
518 .as_slice()
519 }
520 TransitionType::CannabisLeaf => {
521 include_glsl!("res/shader/transition/cannabis_leaf.comp").as_slice()
522 }
523 TransitionType::Circle => {
524 include_glsl!("res/shader/transition/circle.comp").as_slice()
525 }
526 TransitionType::CircleCrop => {
527 include_glsl!("res/shader/transition/circle_crop.comp").as_slice()
528 }
529 TransitionType::CircleOpen => {
530 include_glsl!("res/shader/transition/circle_open.comp").as_slice()
531 }
532 TransitionType::ColorDistance => {
533 include_glsl!("res/shader/transition/color_distance.comp").as_slice()
534 }
535 TransitionType::ColorPhase => {
536 include_glsl!("res/shader/transition/color_phase.comp").as_slice()
537 }
538 TransitionType::CoordFromIn => {
539 include_glsl!("res/shader/transition/coord_from_in.comp").as_slice()
540 }
541 TransitionType::CrazyParametricFun => {
542 include_glsl!("res/shader/transition/crazy_parametric_fun.comp").as_slice()
543 }
544 TransitionType::Crosshatch => {
545 include_glsl!("res/shader/transition/crosshatch.comp").as_slice()
546 }
547 TransitionType::CrossWarp => {
548 include_glsl!("res/shader/transition/cross_warp.comp").as_slice()
549 }
550 TransitionType::CrossZoom => {
551 include_glsl!("res/shader/transition/cross_zoom.comp").as_slice()
552 }
553 TransitionType::Cube => {
554 include_glsl!("res/shader/transition/cube.comp").as_slice()
555 }
556 TransitionType::Directional => {
557 include_glsl!("res/shader/transition/directional.comp").as_slice()
558 }
559 TransitionType::DirectionalEasing => {
560 include_glsl!("res/shader/transition/directional_easing.comp").as_slice()
561 }
562 TransitionType::DirectionalWarp => {
563 include_glsl!("res/shader/transition/directional_warp.comp").as_slice()
564 }
565 TransitionType::DirectionalWipe => {
566 include_glsl!("res/shader/transition/directional_wipe.comp").as_slice()
567 }
568 TransitionType::Displacement => {
569 include_glsl!("res/shader/transition/displacement.comp").as_slice()
570 }
571 TransitionType::DoomScreen => {
572 include_glsl!("res/shader/transition/doom_screen.comp").as_slice()
573 }
574 TransitionType::Doorway => {
575 include_glsl!("res/shader/transition/doorway.comp").as_slice()
576 }
577 TransitionType::Dreamy => {
578 include_glsl!("res/shader/transition/dreamy.comp").as_slice()
579 }
580 TransitionType::DreamyZoom => {
581 include_glsl!("res/shader/transition/dreamy_zoom.comp").as_slice()
582 }
583 TransitionType::FadeColor => {
584 include_glsl!("res/shader/transition/fade_color.comp").as_slice()
585 }
586 TransitionType::Fade => {
587 include_glsl!("res/shader/transition/fade.comp").as_slice()
588 }
589 TransitionType::FadeGrayscale => {
590 include_glsl!("res/shader/transition/fade_grayscale.comp").as_slice()
591 }
592 TransitionType::FilmBurn => {
593 include_glsl!("res/shader/transition/film_burn.comp").as_slice()
594 }
595 TransitionType::Flyeye => {
596 include_glsl!("res/shader/transition/flyeye.comp").as_slice()
597 }
598 TransitionType::GlitchDisplace => {
599 include_glsl!("res/shader/transition/glitch_displace.comp").as_slice()
600 }
601 TransitionType::GlitchMemories => {
602 include_glsl!("res/shader/transition/glitch_memories.comp").as_slice()
603 }
604 TransitionType::GridFlip => {
605 include_glsl!("res/shader/transition/grid_flip.comp").as_slice()
606 }
607 TransitionType::Heart => {
608 include_glsl!("res/shader/transition/heart.comp").as_slice()
609 }
610 TransitionType::Hexagonalize => {
611 include_glsl!("res/shader/transition/hexagonalize.comp").as_slice()
612 }
613 TransitionType::InvertedPageCurl => {
614 include_glsl!("res/shader/transition/inverted_page_curl.comp").as_slice()
615 }
616 TransitionType::Kaleidoscope => {
617 include_glsl!("res/shader/transition/kaleidoscope.comp").as_slice()
618 }
619 TransitionType::LeftRight => {
620 include_glsl!("res/shader/transition/left_right.comp").as_slice()
621 }
622 TransitionType::LinearBlur => {
623 include_glsl!("res/shader/transition/linear_blur.comp").as_slice()
624 }
625 TransitionType::Luma => {
626 include_glsl!("res/shader/transition/luma.comp").as_slice()
627 }
628 TransitionType::LuminanceMelt => {
629 include_glsl!("res/shader/transition/luminance_melt.comp").as_slice()
630 }
631 TransitionType::Morph => {
632 include_glsl!("res/shader/transition/morph.comp").as_slice()
633 }
634 TransitionType::Mosaic => {
635 include_glsl!("res/shader/transition/mosaic.comp").as_slice()
636 }
637 TransitionType::Multiply => {
638 include_glsl!("res/shader/transition/multiply.comp").as_slice()
639 }
640 TransitionType::Overexposure => {
641 include_glsl!("res/shader/transition/overexposure.comp").as_slice()
642 }
643 TransitionType::Perlin => {
644 include_glsl!("res/shader/transition/perlin.comp").as_slice()
645 }
646 TransitionType::Pinwheel => {
647 include_glsl!("res/shader/transition/pinwheel.comp").as_slice()
648 }
649 TransitionType::Pixelize => {
650 include_glsl!("res/shader/transition/pixelize.comp").as_slice()
651 }
652 TransitionType::PolarFunction => {
653 include_glsl!("res/shader/transition/polar_function.comp").as_slice()
654 }
655 TransitionType::PolkaDotsCurtain => {
656 include_glsl!("res/shader/transition/polka_dots_curtain.comp").as_slice()
657 }
658 TransitionType::PowerKaleido => {
659 include_glsl!("res/shader/transition/power_kaleido.comp").as_slice()
660 }
661 TransitionType::Radial => {
662 include_glsl!("res/shader/transition/radial.comp").as_slice()
663 }
664 TransitionType::RandomNoisex => {
665 include_glsl!("res/shader/transition/random_noisex.comp").as_slice()
666 }
667 TransitionType::RandomSquares => {
668 include_glsl!("res/shader/transition/random_squares.comp").as_slice()
669 }
670 TransitionType::Ripple => {
671 include_glsl!("res/shader/transition/ripple.comp").as_slice()
672 }
673 TransitionType::Rotate => {
674 include_glsl!("res/shader/transition/rotate.comp").as_slice()
675 }
676 TransitionType::RotateScale => {
677 include_glsl!("res/shader/transition/rotate_scale.comp").as_slice()
678 }
679 TransitionType::ScaleIn => {
680 include_glsl!("res/shader/transition/scale_in.comp").as_slice()
681 }
682 TransitionType::SimpleZoom => {
683 include_glsl!("res/shader/transition/simple_zoom.comp").as_slice()
684 }
685 TransitionType::SquaresWire => {
686 include_glsl!("res/shader/transition/squares_wire.comp").as_slice()
687 }
688 TransitionType::Squeeze => {
689 include_glsl!("res/shader/transition/squeeze.comp").as_slice()
690 }
691 TransitionType::StereoViewer => {
692 include_glsl!("res/shader/transition/stereo_viewer.comp").as_slice()
693 }
694 TransitionType::Swap => {
695 include_glsl!("res/shader/transition/swap.comp").as_slice()
696 }
697 TransitionType::Swirl => {
698 include_glsl!("res/shader/transition/swirl.comp").as_slice()
699 }
700 TransitionType::TangentMotionBlur => {
701 include_glsl!("res/shader/transition/tangent_motion_blur.comp").as_slice()
702 }
703 TransitionType::TopBottom => {
704 include_glsl!("res/shader/transition/top_bottom.comp").as_slice()
705 }
706 TransitionType::TvStatic => {
707 include_glsl!("res/shader/transition/tv_static.comp").as_slice()
708 }
709 TransitionType::UndulatingBurnOut => {
710 include_glsl!("res/shader/transition/undulating_burn_out.comp").as_slice()
711 }
712 TransitionType::WaterDrop => {
713 include_glsl!("res/shader/transition/water_drop.comp").as_slice()
714 }
715 TransitionType::Wind => {
716 include_glsl!("res/shader/transition/wind.comp").as_slice()
717 }
718 TransitionType::WindowBlinds => {
719 include_glsl!("res/shader/transition/window_blinds.comp").as_slice()
720 }
721 TransitionType::WindowSlice => {
722 include_glsl!("res/shader/transition/window_slice.comp").as_slice()
723 }
724 TransitionType::WipeDown => {
725 include_glsl!("res/shader/transition/wipe_down.comp").as_slice()
726 }
727 TransitionType::WipeLeft => {
728 include_glsl!("res/shader/transition/wipe_left.comp").as_slice()
729 }
730 TransitionType::WipeRight => {
731 include_glsl!("res/shader/transition/wipe_right.comp").as_slice()
732 }
733 TransitionType::WipeUp => {
734 include_glsl!("res/shader/transition/wipe_up.comp").as_slice()
735 }
736 TransitionType::ZoomInCircles => {
737 include_glsl!("res/shader/transition/zoom_in_circles.comp").as_slice()
738 }
739 TransitionType::ZoomLeftWipe => {
740 include_glsl!("res/shader/transition/zoom_left_wipe.comp").as_slice()
741 }
742 TransitionType::ZoomRightWipe => {
743 include_glsl!("res/shader/transition/zoom_right_wipe.comp").as_slice()
744 }
745 }),
746 )
747 .expect("invalid transition pipeline")
748 })
749 }
750}
751
752fn extend_push_constants(transition: Transition, push_consts: &mut Vec<u8>) {
753 match transition {
754 Transition::Angular { starting_angle } => {
755 push_consts.extend_from_slice(&starting_angle.to_ne_bytes());
756 }
757 Transition::Bounce {
758 shadow_height,
759 bounces,
760 shadow_colour,
761 } => {
762 push_consts.extend_from_slice(&shadow_height.to_ne_bytes());
763 push_consts.extend_from_slice(&bounces.to_ne_bytes());
764 push_consts.extend_from_slice(&[0u8; 4]); push_consts.extend_from_slice(&shadow_colour[0].to_ne_bytes());
766 push_consts.extend_from_slice(&shadow_colour[1].to_ne_bytes());
767 push_consts.extend_from_slice(&shadow_colour[2].to_ne_bytes());
768 push_consts.extend_from_slice(&shadow_colour[3].to_ne_bytes());
769 }
770 Transition::BowTieWithParameter { adjust, reverse } => {
771 push_consts.extend_from_slice(&adjust.to_ne_bytes());
772 push_consts.extend_from_slice(&(reverse as u32).to_ne_bytes());
773 }
774 Transition::Burn { color } => {
775 push_consts.extend_from_slice(&[0u8; 12]); push_consts.extend_from_slice(&color[0].to_ne_bytes());
777 push_consts.extend_from_slice(&color[1].to_ne_bytes());
778 push_consts.extend_from_slice(&color[2].to_ne_bytes());
779 }
780 Transition::ButterflyWaveScrawler {
781 amplitude,
782 waves,
783 color_separation,
784 } => {
785 push_consts.extend_from_slice(&litude.to_ne_bytes());
786 push_consts.extend_from_slice(&waves.to_ne_bytes());
787 push_consts.extend_from_slice(&color_separation.to_ne_bytes());
788 }
789 Transition::Circle {
790 center,
791 background_color,
792 } => {
793 push_consts.extend_from_slice(&[0u8; 4]); push_consts.extend_from_slice(¢er[0].to_ne_bytes());
795 push_consts.extend_from_slice(¢er[1].to_ne_bytes());
796 push_consts.extend_from_slice(&background_color[0].to_ne_bytes());
797 push_consts.extend_from_slice(&background_color[1].to_ne_bytes());
798 push_consts.extend_from_slice(&background_color[2].to_ne_bytes());
799 push_consts.extend_from_slice(&[0u8; 4]); }
801 Transition::CircleCrop { background_color } => {
802 push_consts.extend_from_slice(&[0u8; 12]); push_consts.extend_from_slice(&background_color[0].to_ne_bytes());
804 push_consts.extend_from_slice(&background_color[1].to_ne_bytes());
805 push_consts.extend_from_slice(&background_color[2].to_ne_bytes());
806 push_consts.extend_from_slice(&background_color[3].to_ne_bytes());
807 push_consts.extend_from_slice(&[0u8; 4]); }
809 Transition::CircleOpen {
810 smoothness,
811 opening,
812 } => {
813 push_consts.extend_from_slice(&smoothness.to_ne_bytes());
814 push_consts.extend_from_slice(&(opening as u32).to_ne_bytes());
815 }
816 Transition::ColorDistance { power } => {
817 push_consts.extend_from_slice(&power.to_ne_bytes());
818 }
819 Transition::ColorPhase { from_step, to_step } => {
820 push_consts.extend_from_slice(&[0u8; 12]); push_consts.extend_from_slice(&from_step[0].to_ne_bytes());
822 push_consts.extend_from_slice(&from_step[1].to_ne_bytes());
823 push_consts.extend_from_slice(&from_step[2].to_ne_bytes());
824 push_consts.extend_from_slice(&from_step[3].to_ne_bytes());
825 push_consts.extend_from_slice(&to_step[0].to_ne_bytes());
826 push_consts.extend_from_slice(&to_step[1].to_ne_bytes());
827 push_consts.extend_from_slice(&to_step[2].to_ne_bytes());
828 push_consts.extend_from_slice(&to_step[3].to_ne_bytes());
829 }
830 Transition::CrazyParametricFun {
831 a,
832 b,
833 amplitude,
834 smoothness,
835 } => {
836 push_consts.extend_from_slice(&a.to_ne_bytes());
837 push_consts.extend_from_slice(&b.to_ne_bytes());
838 push_consts.extend_from_slice(&litude.to_ne_bytes());
839 push_consts.extend_from_slice(&smoothness.to_ne_bytes());
840 }
841 Transition::Crosshatch {
842 center,
843 threshold,
844 fade_edge,
845 } => {
846 push_consts.extend_from_slice(&[0u8; 4]); push_consts.extend_from_slice(¢er[0].to_ne_bytes());
848 push_consts.extend_from_slice(¢er[1].to_ne_bytes());
849 push_consts.extend_from_slice(&threshold.to_ne_bytes());
850 push_consts.extend_from_slice(&fade_edge.to_ne_bytes());
851 }
852 Transition::CrossZoom { strength } => {
853 push_consts.extend_from_slice(&strength.to_ne_bytes());
854 }
855 Transition::Cube {
856 perspective,
857 unzoom,
858 reflection,
859 floating,
860 } => {
861 push_consts.extend_from_slice(&perspective.to_ne_bytes());
862 push_consts.extend_from_slice(&unzoom.to_ne_bytes());
863 push_consts.extend_from_slice(&reflection.to_ne_bytes());
864 push_consts.extend_from_slice(&floating.to_ne_bytes());
865 }
866 Transition::Directional { direction } => {
867 push_consts.extend_from_slice(&[0u8; 4]); push_consts.extend_from_slice(&direction[0].to_ne_bytes());
869 push_consts.extend_from_slice(&direction[1].to_ne_bytes());
870 }
871 Transition::DirectionalEasing { direction } => {
872 push_consts.extend_from_slice(&[0u8; 4]); push_consts.extend_from_slice(&direction[0].to_ne_bytes());
874 push_consts.extend_from_slice(&direction[1].to_ne_bytes());
875 }
876 Transition::DirectionalWarp { direction } => {
877 push_consts.extend_from_slice(&[0u8; 4]); push_consts.extend_from_slice(&direction[0].to_ne_bytes());
879 push_consts.extend_from_slice(&direction[1].to_ne_bytes());
880 }
881 Transition::DirectionalWipe {
882 smoothness,
883 direction,
884 } => {
885 push_consts.extend_from_slice(&smoothness.to_ne_bytes());
886 push_consts.extend_from_slice(&direction[0].to_ne_bytes());
887 push_consts.extend_from_slice(&direction[1].to_ne_bytes());
888 }
889 Transition::Displacement { strength, .. } => {
890 push_consts.extend_from_slice(&strength.to_ne_bytes());
891 }
892 Transition::DoomScreen {
893 bars,
894 amplitude,
895 noise,
896 frequency,
897 drip_scale,
898 } => {
899 push_consts.extend_from_slice(&bars.to_ne_bytes());
900 push_consts.extend_from_slice(&litude.to_ne_bytes());
901 push_consts.extend_from_slice(&noise.to_ne_bytes());
902 push_consts.extend_from_slice(&frequency.to_ne_bytes());
903 push_consts.extend_from_slice(&drip_scale.to_ne_bytes());
904 }
905 Transition::Doorway {
906 reflection,
907 perspective,
908 depth,
909 } => {
910 push_consts.extend_from_slice(&reflection.to_ne_bytes());
911 push_consts.extend_from_slice(&perspective.to_ne_bytes());
912 push_consts.extend_from_slice(&depth.to_ne_bytes());
913 }
914 Transition::DreamyZoom { rotation, scale } => {
915 push_consts.extend_from_slice(&rotation.to_ne_bytes());
916 push_consts.extend_from_slice(&scale.to_ne_bytes());
917 }
918 Transition::FadeColor { color_phase, color } => {
919 push_consts.extend_from_slice(&color_phase.to_ne_bytes());
920 push_consts.extend_from_slice(&[0u8; 8]); push_consts.extend_from_slice(&color[0].to_ne_bytes());
922 push_consts.extend_from_slice(&color[1].to_ne_bytes());
923 push_consts.extend_from_slice(&color[2].to_ne_bytes());
924 }
925 Transition::FadeGrayscale { intensity } => {
926 push_consts.extend_from_slice(&intensity.to_ne_bytes());
927 }
928 Transition::FilmBurn { seed } => {
929 push_consts.extend_from_slice(&seed.to_ne_bytes());
930 }
931 Transition::Flyeye {
932 size,
933 zoom,
934 color_separation,
935 } => {
936 push_consts.extend_from_slice(&size.to_ne_bytes());
937 push_consts.extend_from_slice(&zoom.to_ne_bytes());
938 push_consts.extend_from_slice(&color_separation.to_ne_bytes());
939 }
940 Transition::GridFlip {
941 pause,
942 size,
943 background_color,
944 divider_width,
945 randomness,
946 } => {
947 push_consts.extend_from_slice(&pause.to_ne_bytes());
948 push_consts.extend_from_slice(&size[0].to_ne_bytes());
949 push_consts.extend_from_slice(&size[1].to_ne_bytes());
950 push_consts.extend_from_slice(&background_color[0].to_ne_bytes());
951 push_consts.extend_from_slice(&background_color[1].to_ne_bytes());
952 push_consts.extend_from_slice(&background_color[2].to_ne_bytes());
953 push_consts.extend_from_slice(&background_color[3].to_ne_bytes());
954 push_consts.extend_from_slice(÷r_width.to_ne_bytes());
955 push_consts.extend_from_slice(&randomness.to_ne_bytes());
956 }
957 Transition::Hexagonalize {
958 steps,
959 horizontal_hexagons,
960 } => {
961 push_consts.extend_from_slice(&steps.to_ne_bytes());
962 push_consts.extend_from_slice(&horizontal_hexagons.to_ne_bytes());
963 }
964 Transition::Kaleidoscope {
965 speed,
966 angle,
967 power,
968 } => {
969 push_consts.extend_from_slice(&speed.to_ne_bytes());
970 push_consts.extend_from_slice(&angle.to_ne_bytes());
971 push_consts.extend_from_slice(&power.to_ne_bytes());
972 }
973 Transition::LinearBlur { intensity } => {
974 push_consts.extend_from_slice(&intensity.to_ne_bytes());
975 }
976 Transition::LuminanceMelt {
977 direction,
978 threshold,
979 above,
980 } => {
981 push_consts.extend_from_slice(&(direction as u32).to_ne_bytes());
982 push_consts.extend_from_slice(&threshold.to_ne_bytes());
983 push_consts.extend_from_slice(&(above as u32).to_ne_bytes());
984 }
985 Transition::Morph { strength } => {
986 push_consts.extend_from_slice(&strength.to_ne_bytes());
987 }
988 Transition::Mosaic { end } => {
989 push_consts.extend_from_slice(&end[0].to_ne_bytes());
990 push_consts.extend_from_slice(&end[1].to_ne_bytes());
991 }
992 Transition::Overexposure { strength } => {
993 push_consts.extend_from_slice(&strength.to_ne_bytes());
994 }
995 Transition::Perlin {
996 scale,
997 smoothness,
998 seed,
999 } => {
1000 push_consts.extend_from_slice(&scale.to_ne_bytes());
1001 push_consts.extend_from_slice(&smoothness.to_ne_bytes());
1002 push_consts.extend_from_slice(&seed.to_ne_bytes());
1003 }
1004 Transition::Pinwheel { speed } => {
1005 push_consts.extend_from_slice(&speed.to_ne_bytes());
1006 }
1007 Transition::Pixelize { steps, squares_min } => {
1008 push_consts.extend_from_slice(&steps.to_ne_bytes());
1009 push_consts.extend_from_slice(&squares_min[0].to_ne_bytes());
1010 push_consts.extend_from_slice(&squares_min[1].to_ne_bytes());
1011 }
1012 Transition::PolarFunction { segments } => {
1013 push_consts.extend_from_slice(&segments.to_ne_bytes());
1014 }
1015 Transition::PolkaDotsCurtain { dots, center } => {
1016 push_consts.extend_from_slice(&dots.to_ne_bytes());
1017 push_consts.extend_from_slice(¢er[0].to_ne_bytes());
1018 push_consts.extend_from_slice(¢er[1].to_ne_bytes());
1019 }
1020 Transition::PowerKaleido { scale, z, speed } => {
1021 push_consts.extend_from_slice(&scale.to_ne_bytes());
1022 push_consts.extend_from_slice(&z.to_ne_bytes());
1023 push_consts.extend_from_slice(&speed.to_ne_bytes());
1024 }
1025 Transition::Radial { smoothness } => {
1026 push_consts.extend_from_slice(&smoothness.to_ne_bytes());
1027 }
1028 Transition::RandomSquares { smoothness, size } => {
1029 push_consts.extend_from_slice(&smoothness.to_ne_bytes());
1030 push_consts.extend_from_slice(&size[0].to_ne_bytes());
1031 push_consts.extend_from_slice(&size[1].to_ne_bytes());
1032 }
1033 Transition::Ripple { amplitude, speed } => {
1034 push_consts.extend_from_slice(&litude.to_ne_bytes());
1035 push_consts.extend_from_slice(&speed.to_ne_bytes());
1036 }
1037 Transition::RotateScale {
1038 rotations,
1039 center,
1040 background_color,
1041 scale,
1042 } => {
1043 push_consts.extend_from_slice(&rotations.to_ne_bytes());
1044 push_consts.extend_from_slice(¢er[0].to_ne_bytes());
1045 push_consts.extend_from_slice(¢er[1].to_ne_bytes());
1046 push_consts.extend_from_slice(&background_color[0].to_ne_bytes());
1047 push_consts.extend_from_slice(&background_color[1].to_ne_bytes());
1048 push_consts.extend_from_slice(&background_color[2].to_ne_bytes());
1049 push_consts.extend_from_slice(&background_color[3].to_ne_bytes());
1050 push_consts.extend_from_slice(&scale.to_ne_bytes());
1051 }
1052 Transition::SimpleZoom { zoom_quickness } => {
1053 push_consts.extend_from_slice(&zoom_quickness.to_ne_bytes());
1054 }
1055 Transition::SquaresWire {
1056 smoothness,
1057 squares,
1058 direction,
1059 } => {
1060 push_consts.extend_from_slice(&smoothness.to_ne_bytes());
1061 push_consts.extend_from_slice(&squares[0].to_ne_bytes());
1062 push_consts.extend_from_slice(&squares[1].to_ne_bytes());
1063 push_consts.extend_from_slice(&direction[0].to_ne_bytes());
1064 push_consts.extend_from_slice(&direction[1].to_ne_bytes());
1065 }
1066 Transition::Squeeze { color_separation } => {
1067 push_consts.extend_from_slice(&color_separation.to_ne_bytes());
1068 }
1069 Transition::StereoViewer {
1070 zoom,
1071 corner_radius,
1072 } => {
1073 push_consts.extend_from_slice(&zoom.to_ne_bytes());
1074 push_consts.extend_from_slice(&corner_radius.to_ne_bytes());
1075 }
1076 Transition::Swap {
1077 reflection,
1078 perspective,
1079 depth,
1080 } => {
1081 push_consts.extend_from_slice(&reflection.to_ne_bytes());
1082 push_consts.extend_from_slice(&perspective.to_ne_bytes());
1083 push_consts.extend_from_slice(&depth.to_ne_bytes());
1084 }
1085 Transition::TvStatic { offset } => {
1086 push_consts.extend_from_slice(&offset.to_ne_bytes());
1087 }
1088 Transition::UndulatingBurnOut {
1089 smoothness,
1090 center,
1091 color,
1092 } => {
1093 push_consts.extend_from_slice(&smoothness.to_ne_bytes());
1094 push_consts.extend_from_slice(¢er[0].to_ne_bytes());
1095 push_consts.extend_from_slice(¢er[1].to_ne_bytes());
1096 push_consts.extend_from_slice(&color[0].to_ne_bytes());
1097 push_consts.extend_from_slice(&color[1].to_ne_bytes());
1098 push_consts.extend_from_slice(&color[2].to_ne_bytes());
1099 }
1100 Transition::WaterDrop { amplitude, speed } => {
1101 push_consts.extend_from_slice(&litude.to_ne_bytes());
1102 push_consts.extend_from_slice(&speed.to_ne_bytes());
1103 }
1104 Transition::Wind { size } => {
1105 push_consts.extend_from_slice(&size.to_ne_bytes());
1106 }
1107 Transition::WindowSlice { count, smoothness } => {
1108 push_consts.extend_from_slice(&count.to_ne_bytes());
1109 push_consts.extend_from_slice(&smoothness.to_ne_bytes());
1110 }
1111 Transition::ZoomLeftWipe { zoom_quickness } => {
1112 push_consts.extend_from_slice(&zoom_quickness.to_ne_bytes());
1113 }
1114 Transition::ZoomRightWipe { zoom_quickness } => {
1115 push_consts.extend_from_slice(&zoom_quickness.to_ne_bytes());
1116 }
1117 Transition::BowTieHorizontal
1118 | Transition::BowTieVertical
1119 | Transition::CannabisLeaf
1120 | Transition::CoordFromIn
1121 | Transition::CrossWarp
1122 | Transition::Dreamy
1123 | Transition::Fade
1124 | Transition::GlitchDisplace
1125 | Transition::GlitchMemories
1126 | Transition::Heart
1127 | Transition::InvertedPageCurl
1128 | Transition::Luma { .. }
1129 | Transition::LeftRight
1130 | Transition::Multiply
1131 | Transition::RandomNoisex
1132 | Transition::Rotate
1133 | Transition::ScaleIn
1134 | Transition::Swirl
1135 | Transition::TangentMotionBlur
1136 | Transition::TopBottom
1137 | Transition::WindowBlinds
1138 | Transition::WipeDown
1139 | Transition::WipeLeft
1140 | Transition::WipeRight
1141 | Transition::WipeUp
1142 | Transition::ZoomInCircles => {}
1143 };
1144}
1145
1146#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1147enum TransitionType {
1148 Angular,
1149 Bounce,
1150 BowTieHorizontal,
1151 BowTieVertical,
1152 BowTieWithParameter,
1153 Burn,
1154 ButterflyWaveScrawler,
1155 CannabisLeaf,
1156 Circle,
1157 CircleCrop,
1158 CircleOpen,
1159 ColorDistance,
1160 ColorPhase,
1161 CoordFromIn,
1162 CrazyParametricFun,
1163 Crosshatch,
1164 CrossWarp,
1165 CrossZoom,
1166 Cube,
1167 Directional,
1168 DirectionalEasing,
1169 DirectionalWarp,
1170 DirectionalWipe,
1171 Displacement,
1172 DoomScreen,
1173 Doorway,
1174 Dreamy,
1175 DreamyZoom,
1176 FadeColor,
1177 Fade,
1178 FadeGrayscale,
1179 FilmBurn,
1180 Flyeye,
1181 GlitchDisplace,
1182 GlitchMemories,
1183 GridFlip,
1184 Heart,
1185 Hexagonalize,
1186 InvertedPageCurl,
1187 Kaleidoscope,
1188 LeftRight,
1189 LinearBlur,
1190 Luma,
1191 LuminanceMelt,
1192 Morph,
1193 Mosaic,
1194 Multiply,
1195 Overexposure,
1196 Perlin,
1197 Pinwheel,
1198 Pixelize,
1199 PolarFunction,
1200 PolkaDotsCurtain,
1201 PowerKaleido,
1202 Radial,
1203 RandomNoisex,
1204 RandomSquares,
1205 Ripple,
1206 Rotate,
1207 RotateScale,
1208 ScaleIn,
1209 SimpleZoom,
1210 SquaresWire,
1211 Squeeze,
1212 StereoViewer,
1213 Swap,
1214 Swirl,
1215 TangentMotionBlur,
1216 TopBottom,
1217 TvStatic,
1218 UndulatingBurnOut,
1219 WaterDrop,
1220 Wind,
1221 WindowBlinds,
1222 WindowSlice,
1223 WipeDown,
1224 WipeLeft,
1225 WipeRight,
1226 WipeUp,
1227 ZoomInCircles,
1228 ZoomLeftWipe,
1229 ZoomRightWipe,
1230}