欢迎来到 WebGPU 的世界 上

简介: 欢迎来到 WebGPU 的世界


图片.png


WebGPU是一门神奇的技术,在浏览器支持率0%,标准还没有定稿的情况下,就已经被Three.js和Babylon.js等主流3D和游戏框架支持了。而且被Tensorflow.js用来加速手机端的深度学习,比起WebGL能带来20~30倍的显著提升。

图片.png


在主流框架中 WebGPU 的例子


1、在Three.js中使用WebGPU

使用Three.js的封装,我们可以直接生成WebGPU的调用。

02.gif

我们照猫画虎引入WebGPU相关的库:

import * as THREE from 'three';
   import * as Nodes from 'three-nodes/Nodes.js';
   import { add, mul } from 'three-nodes/ShaderNode.js';
            import WebGPU from './jsm/capabilities/WebGPU.js';
   import WebGPURenderer from './jsm/renderers/webgpu/WebGPURenderer.js';
...

剩下就跟普通的WebGL代码写起来差不多:

async function init() {
    if ( WebGPU.isAvailable() === false ) {
     document.body.appendChild( WebGPU.getErrorMessage() );
     throw new Error( 'No WebGPU support' );
    }
    const container = document.createElement( 'div' );
    document.body.appendChild( container );
    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 4000 );
    camera.position.set( 0, 200, 1200 );
    scene = new THREE.Scene();
...

只不过渲染器使用WebGPURenderer:

    renderer = new WebGPURenderer();
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    container.appendChild( renderer.domElement );
...

如果封装的不能满足需求了,我们可以使用WGSL语言进行扩展:

    material = new Nodes.MeshBasicNodeMaterial();
    material.colorNode = desaturateWGSLNode.call( { color: new Nodes.TextureNode( texture ) } );
    materials.push( material );
    const getWGSLTextureSample = new Nodes.FunctionNode( `
     fn getWGSLTextureSample( tex: texture_2d<f32>, tex_sampler: sampler, uv:vec2<f32> ) -> vec4<f32> {
      return textureSample( tex, tex_sampler, uv ) * vec4<f32>( 0.0, 1.0, 0.0, 1.0 );
     }
    ` );
    const textureNode = new Nodes.TextureNode( texture );
    material = new Nodes.MeshBasicNodeMaterial();
    material.colorNode = getWGSLTextureSample.call( { tex: textureNode, tex_sampler: textureNode, uv: new Nodes.UVNode() } );
    materials.push( material );

WGSL是WebGPU进行GPU指令编程的语言。类似于OpenGL的GLSL, Direct3D的HLSL。

我们来看一个完整的例子,显示一个跳舞的小人,也不过100多行代码:

003.gif

<!DOCTYPE html>
<html lang="en">
 <head>
  <title>three.js - WebGPU - Skinning</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  <link type="text/css" rel="stylesheet" href="main.css">
  <meta http-equiv="origin-trial" content="AoS1pSJwCV3KRe73TO0YgJkK9FZ/qhmvKeafztp0ofiE8uoGrnKzfxGVKKICvoBfL8dgE0zpkp2g/oEJNS0fDgkAAABeeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJHUFUiLCJleHBpcnkiOjE2NTI4MzE5OTksImlzU3ViZG9tYWluIjp0cnVlfQ==">
 </head>
 <body>
  <div id="info">
   <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> WebGPU - Skinning
  </div>
  <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
  <script type="importmap">
   {
    "imports": {
     "three": "../build/three.module.js",
     "three-nodes/": "./jsm/nodes/"
    }
   }
  </script>
  <script type="module">
   import * as THREE from 'three';
   import * as Nodes from 'three-nodes/Nodes.js';
   import { FBXLoader } from './jsm/loaders/FBXLoader.js';
   import WebGPU from './jsm/capabilities/WebGPU.js';
   import WebGPURenderer from './jsm/renderers/webgpu/WebGPURenderer.js';
   import LightsNode from 'three-nodes/lights/LightsNode.js';
   let camera, scene, renderer;
   let mixer, clock;
   init().then( animate ).catch( error );
   async function init() {
    if ( WebGPU.isAvailable() === false ) {
     document.body.appendChild( WebGPU.getErrorMessage() );
     throw new Error( 'No WebGPU support' );
    }
    camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
    camera.position.set( 100, 200, 300 );
    scene = new THREE.Scene();
    camera.lookAt( 0, 100, 0 );
    clock = new THREE.Clock();
    // 光照
    const light = new THREE.PointLight( 0xffffff );
    camera.add( light );
    scene.add( camera );
    const lightNode = new LightsNode().fromLights( [ light ] );
    const loader = new FBXLoader();
    loader.load( 'models/fbx/Samba Dancing.fbx', function ( object ) {
     mixer = new THREE.AnimationMixer( object );
     const action = mixer.clipAction( object.animations[ 0 ] );
     action.play();
     object.traverse( function ( child ) {
      if ( child.isMesh ) {
       child.material = new Nodes.MeshStandardNodeMaterial();
       child.material.lightNode = lightNode;
      }
     } );
     scene.add( object );
    } );
    // 渲染
    renderer = new WebGPURenderer();
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
    window.addEventListener( 'resize', onWindowResize );
    return renderer.init();
   }
   function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );
   }
   function animate() {
    requestAnimationFrame( animate );
    const delta = clock.getDelta();
    if ( mixer ) mixer.update( delta );
    renderer.render( scene, camera );
   }
   function error( error ) {
    console.error( error );
   }
  </script>
 </body>
</html>


2、在Babylon.js中使用WebGPU

Babylon.js的封装与Three.js大同小异,我们来看个PlayGround的效果:

image.gif图片.png

不同之处在于处理WebGPU的支持情况时,Babylon.js并不判断整体上支不支持WebGPU,而是只看具体功能。

比如上面的例子,只判断是不是支持计算着色器。

    const supportCS = engine.getCaps().supportComputeShaders;

不过目前在macOS上,只有WebGPU支持计算着色器。

如果我们把环境切换成WebGL2,就变成下面这样了:

image.gif图片.png

顺便说一句,Babylon.js判断WebGL2和WebGL时也是同样的逻辑,有高就用高。

如果对于着色器不熟悉,Babylon.js提供了练习Vertex Shader和Pixel Shader的环境:https://cyos.babylonjs.com/ , 带语法高亮和预览。

image.gif图片.png

针对需要通过写手机应用的场景,Babylon.js提供了与React Native结合的能力:

image.gif图片.png


3、用WebGPU进行深度学习加速

除了3D界面和游戏,深度学习的推理器也是GPU的重度用户。所以Tensorflow.js也在还落不了地的时候就支持了WebGPU。实在是计算着色器太重要了。

写出来的加速代码就像下面一样,很多算子的实现最终是由WGSL代码来实现的,最终会转换成GPU的指令。

  getUserCode(): string {
    const rank = this.xShape.length;
    const type = getCoordsDataType(rank);
    const start = this.xShape.map((_, i) => `uniforms.pad${i}[0]`).join(',');
    const end = this.xShape
                    .map(
                        (_, i) => `uniforms.pad${i}[0] + uniforms.xShape${
                            rank > 1 ? `[${i}]` : ''}`)
                    .join(',');
    const startValue = rank > 1 ? `${type}(${start})` : `${start}`;
    const endValue = rank > 1 ? `${type}(${end})` : `${end}`;
    const leftPadCondition = rank > 1 ? `any(outC < start)` : `outC < start`;
    const rightPadCondition = rank > 1 ? `any(outC >= end)` : `outC >= end`;
    const unpackedCoords = rank > 1 ?
        ['coords[0]', 'coords[1]', 'coords[2]', 'coords[3]'].slice(0, rank) :
        'coords';
    const userCode = `
      ${getMainHeaderAndGlobalIndexString()}
        if (index < uniforms.size) {
          let start = ${startValue};
          let end = ${endValue};
          let outC = getCoordsFromIndex(index);
          if (${leftPadCondition} || ${rightPadCondition}) {
            setOutputAtIndex(index, uniforms.constantValue);
          } else {
            let coords = outC - start;
            setOutputAtIndex(index, getX(${unpackedCoords}));
          }
        }
      }
    `;
    return userCode;
  }




相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
相关文章
Threejs实现模拟河流,水面水流,水管水流,海面
Threejs实现模拟河流,水面水流,水管水流,海面
3681 0
Threejs实现模拟河流,水面水流,水管水流,海面
Threejs实现下雨,下雪,阴天,晴天,火焰
Threejs实现下雨,下雪,阴天,晴天,火焰
2774 0
Threejs实现下雨,下雪,阴天,晴天,火焰
|
5月前
|
数据采集 JavaScript 前端开发
“所见即所爬”:使用Pyppeteer无头浏览器抓取动态壁纸
“所见即所爬”:使用Pyppeteer无头浏览器抓取动态壁纸
|
开发框架
threejs做特效:实现物体的发光效果-EffectComposer详解!
【8月更文挑战第7天】实现物体的发光效果-EffectComposer详解!
2633 6
threejs做特效:实现物体的发光效果-EffectComposer详解!
|
11月前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
463 4
|
机器学习/深度学习 编解码 人工智能
ColorFlow:腾讯和清华大学联合推出的图像序列着色模型,通过参考图像的颜色对黑白漫画进行着色生成彩色漫画
ColorFlow是由清华大学和腾讯ARC实验室共同推出的图像序列着色模型,通过检索增强、上下文学习和超分辨率技术,确保黑白图像序列的着色与参考图像颜色一致,适用于漫画、动画制作等工业应用。
1597 15
ColorFlow:腾讯和清华大学联合推出的图像序列着色模型,通过参考图像的颜色对黑白漫画进行着色生成彩色漫画
threeJs用精灵模型Sprite实现下雨效果
这篇文章介绍了使用Three.js中的Sprite(精灵)模型来实现下雨特效的方法和技术细节。
618 2
threeJs用精灵模型Sprite实现下雨效果
|
JavaScript 定位技术 异构计算
WebGis——从零开始vue使用cesium添加点线(四)
WebGis——从零开始vue使用cesium添加点线(四)
|
编解码 缓存 算法
Three.js如何降低3D模型的大小以便更快加载
为加快600MB的3D模型在Three.js中的加载速度,可采用多种压缩方法:1) 减少顶点数,使用简化工具或LOD技术;2) 压缩纹理,降低分辨率或转为KTX2等格式;3) 采用高效文件格式如glTF 2.0及draco压缩;4) 合并材质减少数量;5) 利用Three.js内置优化如BufferGeometry;6) 按需分批加载模型;7) Web Workers后台处理;8) 多模型合并减少绘制;9) 使用Texture Atlas及专业优化工具。示例代码展示了使用GLTFLoader加载优化后的模型。
2160 12