什么?你还没学WebGPU?一份WebGPU学习指南送给你

786 阅读3分钟

什么是WebGPU

三维技术是前端不可分割的一部分,如何在网页中显示各种三维模型?搭建三维场景?运行三维游戏?想必各位前端开发首先想到的就是WebGL。WebGL基于openGL ES进行了两次迭代,现在大多数浏览器支持WebGL 2.0。然而,WebGL技术已经远远落后于现代显卡的发展速度,导致WebGL开发出的三维应用的性能远不及使用现代Api的本地应用。这给网页3D的应用带来了很大的瓶颈。

WebGPU就是用来弥补差距的浏览器全新Api。说是WebGPU,实际上是对WebGL Api的升级。它使用了现代显卡Api和全新工作流,减少了JS和显卡的通信次数,开发了新的shader语言,并兼容了了能够最大化各家显卡性能的Api。目前,一些主流的开源库已经使用上了这项技术,如Threejs、Babylonjs和tensorflowjs等。它们宣称WebGPU带来了数倍乃至上百倍的性能提升。

webgpu是一种简单的系统,它所做的也只不过是在GPU上运行三种函数:顶点着色器、片元着色器和计算着色器。 image.png

  • 上图上有一个管道,包含两个GPU可以运行的着色器,点着色器和片元着色器,当然,你也可以有一个计算着色器
  • 着色器通过bindGroup指向资源(buffer, texture,sample)
  • 管道间接通过内部状态引用缓存区的属性
  • 属性从缓冲区提取数据,并将数据输入顶点着色器
  • 顶点着色器可能数据反馈给片元着色器
  • 片元着色器通过渲染过程描述写入纹理

要在GPU上执行着色器,需要创建所有这些资源并设置此状态。资源的创造是相对直接的。一件有趣的事情是,大多数Web GPU资源在创建后无法更改。你可以更改它们的内容,但不能更改它们的大小、用法、格式等。如果你想更改其中的任何内容,你可以创建一个新资源并销毁旧资源。

一些状态是通过创建然后执行命令缓冲区来设置的。命令缓冲区顾名思义。它们是命令的缓冲区。您可以创建编码器。编码器将命令编码到命令缓冲器中。然后完成编码器,它会为您提供它创建的命令缓冲区。然后,您可以提交该命令缓冲区,让Web GPU执行命令。

image.png 如下代码,绘制一个三角形:

async function main() {
  const adapter = await navigator.gpu?.requestAdapter();
  const device = await adapter?.requestDevice();
  if (!device) {
    fail('need a browser that supports WebGPU');
    return;
  }

  // Get a WebGPU context from the canvas and configure it
  const canvas = document.querySelector('canvas');
  const context = canvas.getContext('webgpu');
  const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
  context.configure({
    device,
    format: presentationFormat,
      });

  const module = device.createShaderModule({
    label: 'our hardcoded red triangle shaders',
    code: `
      @vertex fn vs(
        @builtin(vertex_index) vertexIndex : u32
      ) -> @builtin(position) vec4f {
        var pos = array<vec2f, 3>(
          vec2f( 0.0,  0.5),  // top center
          vec2f(-0.5, -0.5),  // bottom left
          vec2f( 0.5, -0.5)   // bottom right
        );

        return vec4f(pos[vertexIndex], 0.0, 1.0);
      }

      @fragment fn fs() -> @location(0) vec4f {
        return vec4f(1, 0, 0, 1);
      }
    `,
  });

  const pipeline = device.createRenderPipeline({
    label: 'our hardcoded red triangle pipeline',
    layout: 'auto',
    vertex: {
      module,
      entryPoint: 'vs',
    },
    fragment: {
      module,
      entryPoint: 'fs',
      targets: [{ format: presentationFormat }],
    },
  });

  const renderPassDescriptor = {
    label: 'our basic canvas renderPass',
    colorAttachments: [
      {
        // view: <- to be filled out when we render
        clearValue: [0.3, 0.3, 0.3, 1],
        loadOp: 'clear',
        storeOp: 'store',
      },
    ],
  };

  function render() {
    // Get the current texture from the canvas context and
    // set it as the texture to render to.
    renderPassDescriptor.colorAttachments[0].view =
        context.getCurrentTexture().createView();

    // make a command encoder to start encoding commands
    const encoder = device.createCommandEncoder({ label: 'our encoder' });

    // make a render pass encoder to encode render specific commands
    const pass = encoder.beginRenderPass(renderPassDescriptor);
    pass.setPipeline(pipeline);
    pass.draw(3);  // call our vertex shader 3 times.
    pass.end();

    const commandBuffer = encoder.finish();
    device.queue.submit([commandBuffer]);
  }

  render();
}

function fail(msg) {
  // eslint-disable-next-line no-alert
  alert(msg);
}

main();

WebGPU要怎么学呢?

笔者在WebGPU正式推出后,就开始了对WebGPU的学习。到现在也有一两个月了。中间走了不少弯路,也得到了很多感悟,最终也算是有所收获。我下面就根据我的经验梳理一下WebGPU的学习过程,让大家少走一些弯路,也能够对WebGPU这项技术有一个较深的理解。

首先要明白一点,如果你要学习就需要深入的学习,从基础到应用,如果你只是想参考例子写一个玩具,我觉得读到这里应该就可以了,去找几个Web3D开源库,参考例子Copy Copy玩玩就行了。下面我介绍的学习过程是需要你下一番功夫,耗费点脑力的。

其实学习过程很简单,也就几步:

  1. 由于WebGPU是3D技术,它的基础是图形学,图像学的基础是数学,主要是线性代数。首先需要去复习一个基础的线性代数知识。其次,需要对图形学的基础知识有基础的了解。这里推荐闫令琪Games 101课程,还有李伟老师写的博客李伟的博客 (yxyy.name)(在掘金也可以搜到李伟老师的写的博客)
  2. 在有了基础的线性代数和图形学知识后,便可以学习WebGPU相关的Api了,这里推荐WebGPU Fundamentals,在这本教程里对WebGPU进行了由浅入深的教学讲解,读完这个教程,基本上就能够说对WebGPU入门了,可以去应对各种应用了。
  3. 学习了WebGPU相关Api后,便可以去学习基于WebGPU的各种流行的开源Web3D库了,如babylonjs,threejs等

github也开了awesome-webgpu,可以找到各种想要的知识:

github.com/mikbry/awes…

以上就是全部内容了。希望我的分享能够给您带来收获。可以关注我,或者关注我的公众号:风筝文刊,我将常伴你左右!