Skip to content

feat(shader-transitions): optional shader field — CSS crossfade mixing in HyperShader#886

Open
ukimsanov wants to merge 1 commit into
mainfrom
feat/shader-optional-css-mix
Open

feat(shader-transitions): optional shader field — CSS crossfade mixing in HyperShader#886
ukimsanov wants to merge 1 commit into
mainfrom
feat/shader-optional-css-mix

Conversation

@ukimsanov
Copy link
Copy Markdown
Collaborator

What

Makes the shader field in TransitionConfig optional. When omitted, HyperShader performs a smooth CSS opacity crossfade instead of a WebGL effect — using the existing applyFallbackTransition() path that was already there for texture-load failures.

Why

Previously, using HyperShader.init() locked the entire composition into WebGL-only transitions. Any transition that didn't need a shader effect (smooth cuts, crossfades between related beats) still required picking the least-intrusive shader (flash-through-white at 0.01s). This was an all-or-nothing constraint that produced unwanted white flashes in practice.

Now shader and CSS crossfade transitions can be mixed freely in the same composition:

var tl = HyperShader.init({
  bgColor: "#000",
  scenes: ["beat-1", "beat-2", "beat-3", "beat-4"],
  transitions: [
    { time: 4.0, shader: "sdf-iris", duration: 0.7 },   // WebGL shader
    { time: 8.5, duration: 0.8 },                         // no shader → CSS crossfade
    { time: 13.0, shader: "domain-warp", duration: 0.6 }, // WebGL shader
  ],
});

How

  • TransitionConfig.shader changed from ShaderName (required) to ShaderName | undefined (optional)
  • In the program compilation loop: skip transitions with no shader
  • In the transition setup loop: isCssFallback = !t.shader — fallback transitions get prog: null, ready: true, fallback: true, dirty: false — no prewarming needed
  • renderShader call uses non-null assertion (state.prog!) — safe because the fallback path returns before this point
  • HfTransitionMeta.shader in both the local interface and engine/src/types.ts made optional to match
  • CachedTransition.prog type widened to WebGLProgram | null

Test plan

  • Built packages/shader-transitions — clean TypeScript, no errors
  • Tested with a 3-scene composition: sdf-iris shader + CSS crossfade + domain-warp shader
  • Rendered to MP4 — both transition types composite correctly
  • Verified CSS crossfade fallback uses applyFallbackTransition() smooth opacity interpolation
  • Player scrubber works correctly (using HyperShader.init() without timeline: option)

…de mixing

Allow omitting the shader field in TransitionConfig to get a smooth CSS
opacity crossfade instead of a WebGL effect. HyperShader manages all scene
visibility regardless of transition type, so shader and CSS crossfade
transitions can now be mixed freely in the same composition.

When shader is omitted:
- No WebGL program is compiled or cached for that transition
- The existing applyFallbackTransition() path handles the crossfade
- No texture prewarming needed — transition is marked ready immediately

Tested: verified with a 3-scene composition (sdf-iris + CSS crossfade)
rendered to MP4. Both transition types render correctly.

engine/src/types.ts: HfTransitionMeta.shader is now optional to match
@miguel-heygen
Copy link
Copy Markdown
Collaborator

fix the failed ci checks btw

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants