mcpField
T
typegpu

typegpu

github.com/boraoztunc创意与媒体434185 次安装11 周前更新
代码仓库

关于 typegpu

面向 HyperFrames 创作者的 TypeGPU 与原生 WebGPU 开发技能,说明如何同步时间轴、渲染 GPU 画面并制作视觉效果。

主要功能

  1. 01按 HyperFrames 时间同步渲染
  2. 02响应 hf-seek 事件
  3. 03同步注册 GSAP 时间轴
  4. 04制作多阶段磨砂模糊
  5. 05配置透明或不透明画布

适用场景

  1. 01按视频时间轴帧渲染 GPU 效果
  2. 02在 HTML 内容上叠加 GPU 动画
  3. 03基于纹理制作磨砂玻璃效果

安装

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

$npx skills add https://github.com/boraoztunc/skills --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