WebGPU 基础知识-画布调整大小

WebGPU是WebGPU标准的一部分,由Khronos Group领导的WebGPU工作组制定,是一种为Web公开GPU硬件功能的API。它提供对网络上硬件的图形和计算能力的访问,旨在提供基于现代GPU的高性能、低延迟的图形渲染服务。

WebGPU 基础知识-画布调整大小
推荐使用NSDT 3DConvert进行3D模型格式转换,支持glb、obj、stp、fbx、ifc等多种3D模型格式之间进行互相转换,在转换过程中,能够很好的保留模型原有的颜色、材质等信息。

简单的画布调整大小 Simple Canvas Resizing

在我们继续之前,让我们回到我们的三角形绘图示例并添加一些对调整画布大小的基本支持。调整画布大小实际上是一个可能有很多微妙之处的主题,因此有一整篇文章都在讨论它。现在我们只添加一些基本支持。

首先我们添加一些 CSS 让我们的画布填满页面.

<style>
html, body {
  margin: 0;       /* remove the default margin          */
  height: 100%;    /* make the html,body fill the page   */
}
canvas {
  display: block;  /* make the canvas act like a block   */
  width: 100%;     /* make the canvas fill its container */
  height: 100%;
}
</style>

上边 CSS 只是将使画布显示以覆盖页面,但它不会改变画布本身的分辨率,因此您可能会注意到如果您将下面的示例变大,就像您单击全屏按钮一样,您会看到三角形的边缘是块状的。

默认情况下,  标签的分辨率为 300x150 像素。我们想调整画布以匹配大小。一个好的方法是使用 ResizeObserver 。您创建一个 ResizeObserver 并为其提供一个函数,以便在您要求它观察的元素改变其大小时调用。然后告诉它要观察哪些元素。

    ...
    // render();// 这行被删除
 
    const observer = new ResizeObserver(entries => {
      for (const entry of entries) {
        const canvas = entry.target;
        const width = entry.contentBoxSize[0].inlineSize;
        const height = entry.contentBoxSize[0].blockSize;
        canvas.width = Math.min(width, device.limits.maxTextureDimension2D);
        canvas.height = Math.min(height, device.limits.maxTextureDimension2D);
        // re-render
        render();
      }
    });
    observer.observe(canvas);

在上面的代码中,我们遍历了所有条目,但应该只有一个,因为我们只观察我们的画布。我们需要将画布的大小限制为我们的设备支持的最大尺寸,否则 WebGPU 将开始生成我们试图制作太大的纹理的错误。

我们调用 render 以新的分辨率重新渲染三角形。我们删除了对 render 的旧调用,因为它不需要。当元素开始被观察时, ResizeObserver 将始终至少调用一次回调以报告元素的大小。

当我们在 render 中调用 context.getCurrentTexture() 时会创建新大小的纹理,因此无需执行任何操作。

在接下来的文章中,我们将介绍将数据传递到着色器的各种方法。

上面的代码以非常简洁的方式获取了一个 WebGPU 设备。

更详细的方法是:

async function start() {
  if (!navigator.gpu) {
    fail('this browser does not support WebGPU');
    return;
  }

  const adapter = await navigator.gpu.requestAdapter();
  if (!adapter) {
    fail('this browser supports webgpu but it appears disabled');
    return;
  }

  const device = await adapter?.requestDevice();
  device.lost.then((info) => {
    console.error(`WebGPU device was lost: ${info.message}`);

    // 'reason' will be 'destroyed' if we intentionally destroy the device.
    if (info.reason !== 'destroyed') {
      // try again
      start();
    }
  });
  
  main(device);
}
start();

function main(device) {
  ... do webgpu ...
}

device.lost 是一个开始时unresolved的promise 。它将解决设备是否以及何时丢失。设备丢失的原因有很多。也许用户运行了一个非常密集的应用程序并且它使他们的 GPU 崩溃了。也许用户更新了他们的驱动程序。也许用户有一个外部 GPU 并拔掉了它。也许另一个页面使用了大量 GPU,您的选项卡在后台,浏览器决定通过丢失后台选项卡设备来释放一些内存。关键是对于任何严肃的应用程序,您可能想要处理丢失设备的问题。

请注意, requestDevice 总是返回一个设备。它可能会开始丢失。 WebGPU 的设计使得在大多数情况下,设备看起来可以工作,至少从 API 级别来看是这样。创建事物并使用它们的调用似乎会成功,但它们实际上不会起作用。当 lost 承诺解决时,由您决定改怎么做。

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号