mcpField
T
typegpu

typegpu

github.com/heygen-com创意与媒体74.7k51.0k 次安装今天更新
代码仓库

关于 typegpu

面向 HyperFrames 的 TypeGPU 和原生 WebGPU 技能,说明时间线同步、响应 seek 的渲染方式及 GPU 帧捕获要求。

主要功能

  1. 01异步初始化前同步注册 GSAP 时间线
  2. 02依据 HyperFrames 时间和 seek 事件渲染
  3. 03处理 GPU 帧捕获与队列完成
  4. 04设计模糊及透明画布渲染通道
  5. 05使用确定性的动画输入

适用场景

  1. 01在 HyperFrames 中制作可 seek 的 GPU 效果
  2. 02将 GPU 合成内容渲染为视频
  3. 03在 HTML 内容上叠加 GPU 视觉效果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/heygen-com/hyperframes --skill typegpu

安装后在 Claude Code 中输入/typegpu确认已加载。

详细介绍

HyperFrames 的 TypeGPU / WebGPU

HyperFrames 通过其 typegpu 运行时适配器支持 TypeGPU 和原始 WebGPU。该适配器不负责管理你的渲染管线。它会发布 HyperFrames 时间并分发 seek 事件,以便你的合成能够渲染精确的 GPU 帧。

约定

  • 异步初始化 WebGPU(await navigator.gpu.requestAdapter()),但必须同步注册所有 GSAP 补间动画——在任何 await 之前。HyperFrames 播放器会在页面加载时立即读取时间线。
  • 根据 HyperFrames 时间进行渲染,而不是使用 performance.now()。
  • 监听 hf-seek 事件,并在该时间点精确重新渲染。
  • 在 WebGPU 不可用的环境中加入保护——适配器不会替你进行检查。
  • 对于视频渲染,在提交 GPU 工作后调用 await device.queue.onSubmittedWorkDone(),以确保在捕获帧之前画布已完成刷新。

每次 seek 时,适配器都会设置 window.__hfTypegpuTime 并分发 new CustomEvent("hf-seek", { detail: { time } })。

基本模式

<canvas id="gpu-layer"></canvas>
<script>
  (async () => {
    if (!navigator.gpu) return;
    const adapter = await navigator.gpu.requestAdapter();
    if (!adapter) return;
    const device = await adapter.requestDevice();
    const canvas = document.getElementById("gpu-layer");
    canvas.width = 1920;
    canvas.height = 1080;
    const ctx = canvas.getContext("webgpu");
    const fmt = navigator.gpu.getPreferredCanvasFormat();
    ctx.configure({ device, format: fmt, alphaMode: "opaque" });

    // Build your pipeline, buffers, bind groups...
    const timeUniform = new Float32Array([0]);
    const timeBuf = device.createBuffer({
      size: 16,
      usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
    });

    function render(t) {
      timeUniform[0] = t;
      device.queue.writeBuffer(timeBuf, 0, timeUniform);
      const enc = device.createCommandEncoder();
      const pass = enc.beginRenderPass({
        colorAttachments: [
          {
            view: ctx.getCurrentTexture().createView(),
            loadOp: "clear",
            clearValue: { r: 0, g: 0, b: 0, a: 1 },
            storeOp: "store",
          },
        ],
      });
      pass.setPipeline(pipeline);
      pass.setBindGroup(0, bindGroup);
      pass.draw(3);
      pass.end();
      device.queue.submit([enc.finish()]);
    }

    render(0);
    window.addEventListener("hf-seek", (e) => render(e.detail.time));
  })();
</script>

时间线注册

驱动文本、字幕或 HTML 元素的 GSAP 补间动画必须同步注册——在任何 await 之前:

const tl = gsap.timeline({ paused: true });

// Caption tweens: synchronous, added before WebGPU init
gsap.set(".cap", { opacity: 0 });
tl.to("#cap-1", { opacity: 1, duration: 0.3 }, 1.0);
tl.to("#cap-1", { opacity: 0, duration: 0.2 }, 3.5);

window.__timelines["my-comp"] = tl;

// GPU-dependent tweens can go inside the async IIFE
(async () => {
  // ... WebGPU init ...
  const proxy = { value: 0 };
  tl.to(proxy, { value: 1, duration: 2, onUpdate: render }, 0.5);
})();

基于视频的效果(液态玻璃、扭曲)

要将 <video> 用作 GPU 输入纹理:

const videoEl = document.getElementById("aroll");

// Wait for video metadata before creating the texture
await new Promise((r) => {
  if (videoEl.readyState >= 1) r();
  else videoEl.addEventListener("loadedmetadata", r, { once: true });
});

// Create texture at the video's NATIVE resolution
const vw = videoEl.videoWidth,
  vh = videoEl.videoHeight;
const bgTex = device.createTexture({
  size: [vw, vh],
  format: "rgba8unorm",
  usage:
    GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT,
});

function render(t) {
  try {
    device.queue.copyExternalImageToTexture({ source: videoEl }, { texture: bgTex }, [vw, vh]);
  } catch (_) {
    /* frame not decoded yet */
  }
  // ... draw ...
}

渲染模式注意事项: 无头 Chrome 可能无法对视频元素执行 copyExternalImageToTexture。对于生产渲染,请使用 FFmpeg 预先提取关键帧并保存为 PNG,然后将其作为图像纹理加载。

通过降采样通道实现磨砂模糊

单通道高斯核无法实现玻璃般的磨砂模糊。请使用两通道方案:

  1. 通道 1 — 降采样: 将全分辨率纹理渲染到小型纹理(1/6 分辨率)。降采样时的双线性过滤会自然地对像素求平均。
  2. 通道 2 — 玻璃合成: 对磨砂内部采样小型纹理(双线性放大 = 强平滑模糊),对清晰区域和色差折射采样全分辨率纹理。

这种方法无需生成 mipmap,即可实现与 TypeGPU 的 textureSampleBias mip 级别方法相同的效果。

透明画布与不透明画布

  • alphaMode: 'opaque' — GPU 画布渲染完整画面(视频 + 效果)。当 GPU 管线处理所有视觉内容时使用。
  • alphaMode: 'premultiplied' — GPU 画布在 alpha = 0 的位置透明,使下方的 HTML 元素能够显示出来。用于叠加在常规 <video> 元素上的覆盖层(粒子、路径动画)。

WGSL 全屏三角形

全屏效果的标准顶点着色器(无需顶点缓冲区):

struct Vo { @builtin(position) pos: vec4f, @location(0) uv: vec2f }

@vertex fn vs(@builtin(vertex_index) vi: u32) -> Vo {
  let ps = array<vec2f, 3>(vec2f(-1., -1.), vec2f(3., -1.), vec2f(-1., 3.));
  let ts = array<vec2f, 3>(vec2f(0., 1.), vec2f(2., 1.), vec2f(0., -1.));
  return Vo(vec4f(ps[vi], 0., 1.), ts[vi]);
}

使用 pass.draw(3) 绘制——一个覆盖视口的三角形。

圆角矩形 SDF(液态玻璃胶囊)

fn sdf_box(p: vec2f, half_size: vec2f, corner_radius: f32) -> f32 {
  let d = abs(p) - half_size + vec2f(corner_radius);
  return length(max(d, vec2f(0.))) + min(max(d.x, d.y), 0.) - corner_radius;
}

使用它为玻璃效果定义内部/环形/外部区域。负值表示位于形状内部。

确定性渲染

  • 不使用 Math.random()——请使用带种子的 PRNG。
  • 渲染循环不使用 requestAnimationFrame——仅响应 hf-seek 进行渲染。
  • 动画时间不使用 performance.now()——读取 window.__hfTypegpuTime 或 e.detail.time。
  • 提交 GPU 工作后,为渲染模式的帧捕获调用 await device.queue.onSubmittedWorkDone()。

评论

支持 Markdown