目次
詳細設定
バインド
時間 - 制服
パーティクルの位置 - WGSL ストレージ
頂点シェーダーのコンピュートシェーダーでパーティクルの位置を読み取ります
シミュレーションを段階的に実行します
結論
ホームページ ウェブフロントエンド jsチュートリアル WebGPU チュートリアル: Web 上のコンピューティング、頂点、およびフラグメント シェーダー

WebGPU チュートリアル: Web 上のコンピューティング、頂点、およびフラグメント シェーダー

Jan 17, 2025 am 08:30 AM

WebGPU tutorial: compute, vertex, and fragment shaders on the web

WebGPU は、最先端の GPU コンピューティング機能を Web にもたらし、共有コード ベースを使用してすべての消費者プラットフォームに利益をもたらすことを約束するグローバル テクノロジーです。

その前身である WebGL は強力ですが、コンピューティング シェーダー機能が著しく不足しており、アプリケーションの範囲が制限されています。

WGSL (WebGPU Shader/Compute Language) は、Rust や GLSL などの分野のベスト プラクティスを活用しています。

WebGPU の使い方を学んでいると、ドキュメントにいくつかのギャップがあることに気づきました。計算シェーダーを使用して頂点シェーダーとフラグメント シェーダーのデータを計算するための簡単な出発点を見つけたいと思っていました。

このチュートリアルのすべてのコードの単一ファイル HTML は、https://www.php.cn/link/2e5281ee978b78d6f5728aad8f28fedb にあります。詳細な内訳については、以下をお読みください。

これは、私のドメインで実行されるこの HTML のシングルクリックのデモです: https://www.php.cn/link/bed827b4857bf056d05980661990ccdc Chrome や Edge などの WebGPU ベースのブラウザhttps://www.php.cn/link/bae00fb8b4115786ba5dbbb67b9b177a)。

詳細設定

これは粒子シミュレーションです。時間の経過とともにタイムステップで発生します。

時間は JS/CPU で追跡され、(float) 均一として GPU に渡されます。

パーティクル データは完全に GPU 上で管理されますが、CPU と対話し続けるため、メモリの割り当てと初期値の設定が可能になります。データを CPU に読み戻すことも可能ですが、このチュートリアルでは省略します。

このセットアップの魅力は、各パーティクルが他のすべてのパーティクルと並行して更新され、ブラウザでの驚異的な計算速度とレンダリング速度が可能になることです (並列化により GPU のコア数が最大化されます。パーティクルの数は次のように割ることができます)。コアごとの更新ステップごとの真のサイクル数を取得するには、コアの数を使用します)。

バインド

WebGPU が CPU と GPU 間のデータ交換に使用するメカニズムはバインドです。WebGPU バッファーを使用して、JS 配列 (Float32Array など) を WGSL のメモリ位置に「バインド」できます。 WGSL メモリの場所は、グループ番号とバインディング番号という 2 つの整数によって識別されます。

私たちのケースでは、コンピューティング シェーダーと頂点シェーダーの両方が、時間とパーティクルの位置という 2 つのデータ バインディングに依存しています。

時間 - 制服

コンピューティング シェーダー (https://www.php.cn/link/2e5281ee978b78d6f5728aad8f28fedb#L43) と頂点シェーダーには均一な定義が存在します。 (https://www.php.cn/link/2e5281ee978b78d6f5728aad8f28fedb#L69) 中 - シェーダー更新位置を計算し、頂点シェーダーは時間に基づいて色を更新します。

コンピューティング シェーダーから始めて、JS と WGSL のバインディング セットアップを見てみましょう。

<code>const computeBindGroup = device.createBindGroup({
  /*
    参见 computePipeline 定义,网址为
    https://www.php.cn/link/2e5281ee978b78d6f5728aad8f28fedb#L102

    它允许将 JS 字符串与 WGSL 代码链接到 WebGPU
  */
  layout: computePipeline.getBindGroupLayout(0), // 组号 0
  entries: [{
    // 时间绑定在绑定号 0
    binding: 0,
    resource: {
      /*
      作为参考,缓冲区声明为:

      const timeBuffer = device.createBuffer({
        size: Float32Array.BYTES_PER_ELEMENT,
        usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST})
      })

      https://www.php.cn/link/2e5281ee978b78d6f5728aad8f28fedb#L129
      */
      buffer: timeBuffer
    }
  },
  {
    // 粒子位置数据在绑定号 1(仍在组 0)
    binding: 1,
    resource: {
      buffer: particleBuffer
    }
  }]
});</code>
ログイン後にコピー

およびコンピューティング シェーダー内の対応する宣言

<code>// 来自计算着色器 - 顶点着色器中也有类似的声明
@group(0) @binding(0) var<uniform> t: f32;
@group(0) @binding(1) var<storage read_write=""> particles : array<particle>;
</particle></storage></uniform></code>
ログイン後にコピー

重要なのは、JS と WGSL のグループ番号とバインディング番号を一致させることによって、JS 側の timeBuffer を WGSL にバインドしていることです。

これにより、JS から変数の値を制御できるようになります:

<code>/* 数组中只需要 1 个元素,因为时间是单个浮点值 */
const timeJs = new Float32Array(1)
let t = 5.3
/* 纯 JS,只需设置值 */
timeJs.set([t], 0)
/* 将数据从 CPU/JS 传递到 GPU/WGSL */
device.queue.writeBuffer(timeBuffer, 0, timeJs);</code>
ログイン後にコピー

パーティクルの位置 - WGSL ストレージ

粒子の位置を GPU からアクセス可能なメモリに直接保存して更新することで、GPU の大規模なマルチコア アーキテクチャを利用して粒子の位置を並行して更新できるようになります。

並列化は、コンピューティング シェーダーで宣言されたワーク グループ サイズを使用して調整されます。

<code>@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
  // ...
}
</u32></code>
ログイン後にコピー

@builtin(global_invocation_id) global_id : vec3 値はスレッド識別子を提供します。

定義により、global_invocation_id = workgroup_id * workgroup_size local_invocation_id - これは、パーティクル インデックスとして使用できることを意味します。

たとえば、10,000 個のパーティクルがあり、workgroup_size が 64 の場合、Math.ceil(10000/64) ワークグループをスケジュールする必要があります。コンピューティング パスが JS からトリガーされるたびに、次の量の作業を実行するように GPU に明示的に指示します:

<code>computePass.dispatchWorkgroups(Math.ceil(PARTICLE_COUNT / WORKGROUP_SIZE));</code>
ログイン後にコピー

PARTICLE_COUNT == 10000 および WORKGROUP_SIZE == 64 の場合、157 個のワークグループ (10000/64 = 156.25) が開始され、各ワークグループの local_invocation_id の計算範囲は 0 ~ 63 になります (workgroup_id の範囲は 0 ~ 157 です)。 )。 157 * 64 = 1048 なので、最終的にはワークグループでもう少し多くの計算を行うことになります。冗長な呼び出しを破棄することでオーバーフローを処理します。

これらの要素を考慮したシェーダーの計算の最終結果は次のとおりです:

<code>@compute @workgroup_size(${WORKGROUP_SIZE})
fn main(@builtin(global_invocation_id) global_id : vec3<u32>) {
  let index = global_id.x;
  // 由于工作组网格未对齐,因此丢弃额外的计算
  if (index >= arrayLength(&particles)) {
    return;
  }
  /* 将整数索引转换为浮点数,以便我们可以根据索引(和时间)计算位置更新 */
  let fi = f32(index);
  particles[index].position = vec2<f32>(
    /* 公式背后没有宏伟的意图 - 只不过是用时间+索引的例子 */
    cos(fi * 0.11) * 0.8 + sin((t + fi)/100)/10,
    sin(fi * 0.11) * 0.8 + cos((t + fi)/100)/10
  );
}
</f32></u32></code>
ログイン後にコピー

パーティクルはストレージ変数として定義されているため、これらの値は計算パス全体で保持されます。

頂点シェーダーのコンピュートシェーダーでパーティクルの位置を読み取ります

コンピューティング シェーダーのみがストレージに書き込むことができるため、コンピューティング シェーダーから頂点シェーダー内のパーティクルの位置を読み取るには、読み取り専用ビューが必要です。

以下は WGSL からの声明です:

<code>@group(0) @binding(0) var<uniform> t: f32;
@group(0) @binding(1) var<storage> particles : array<vec2>>;
/*
或等效:

@group(0) @binding(1) var<storage read=""> particles : array<vec2>>;
*/
</vec2></storage></vec2></storage></uniform></code>
ログイン後にコピー

コンピューティング シェーダーで同じ read_write スタイルを再利用しようとすると、エラーが発生します:

<code>var with 'storage' address space and 'read_write' access mode cannot be used by vertex pipeline stage</code>
ログイン後にコピー

頂点シェーダーのバインディング番号は、コンピューティング シェーダーのバインディング番号と一致する必要はないことに注意してください。頂点シェーダーのバインディング グループ宣言と一致する必要があるだけです。

<code>const renderBindGroup = device.createBindGroup({
  layout: pipeline.getBindGroupLayout(0),
  entries: [{
    binding: 0,
    resource: {
      buffer: timeBuffer
    }
  },
  {
    binding: 1,
    resource: {
      buffer: particleBuffer
    }
  }]
});</code>
ログイン後にコピー

GitHub サンプル コードで binding:2 を選択しました https://www.php.cn/link/2e5281ee978b78d6f5728aad8f28fedb#L70 - WebGPU によって課される制約の境界を調べるためだけに

シミュレーションを段階的に実行します

すべての設定が完了すると、更新ループとレンダリング ループが JS で調整されます。

<code>/* 从 t = 0 开始模拟 */
let t = 0
function frame() {
  /*
    为简单起见,使用恒定整数时间步 - 无论帧速率如何,都会一致渲染。
  */
  t += 1
  timeJs.set([t], 0)
  device.queue.writeBuffer(timeBuffer, 0, timeJs);

  // 计算传递以更新粒子位置
  const computePassEncoder = device.createCommandEncoder();
  const computePass = computePassEncoder.beginComputePass();
  computePass.setPipeline(computePipeline);
  computePass.setBindGroup(0, computeBindGroup);
  // 重要的是要调度正确数量的工作组以处理所有粒子
  computePass.dispatchWorkgroups(Math.ceil(PARTICLE_COUNT / WORKGROUP_SIZE));
  computePass.end();
  device.queue.submit([computePassEncoder.finish()]);

  // 渲染传递
  const commandEncoder = device.createCommandEncoder();
  const passEncoder = commandEncoder.beginRenderPass({
    colorAttachments: [{
      view: context.getCurrentTexture().createView(),
      clearValue: { r: 0.0, g: 0.0, b: 0.0, a: 1.0 },
      loadOp: 'clear',
      storeOp: 'store',
    }]
  });
  passEncoder.setPipeline(pipeline);
  passEncoder.setBindGroup(0, renderBindGroup);
  passEncoder.draw(PARTICLE_COUNT);
  passEncoder.end();
  device.queue.submit([commandEncoder.finish()]);

  requestAnimationFrame(frame);
}
frame();</code>
ログイン後にコピー

結論

WebGPU は、ブラウザ内で大規模並列 GPU コンピューティングのパワーを解放します。

パスで実行されます。各パスには、メモリ バインディング (CPU メモリと GPU メモリのブリッジ) を備えたパイプラインを通じて有効化されたローカル変数があります。

コンピューティングの配信により、ワークグループを通じて並列ワークロードを調整できます。

多少の重いセットアップが必要ですが、ローカル バインディング/状態スタイルは WebGL のグローバル状態モデルに比べて大幅に改善されていると思います。使いやすくなり、同時に GPU コンピューティングのパワーを最終的に Web にもたらします。

以上がWebGPU チュートリアル: Web 上のコンピューティング、頂点、およびフラグメント シェーダーの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

javascriptの分解:それが何をするのか、なぜそれが重要なのか javascriptの分解:それが何をするのか、なぜそれが重要なのか Apr 09, 2025 am 12:07 AM

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

JavaScriptの進化:現在の傾向と将来の見通し JavaScriptの進化:現在の傾向と将来の見通し Apr 10, 2025 am 09:33 AM

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

JavaScriptエンジン:実装の比較 JavaScriptエンジン:実装の比較 Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

JavaScript:Web言語の汎用性の調査 JavaScript:Web言語の汎用性の調査 Apr 11, 2025 am 12:01 AM

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合) next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合) Apr 11, 2025 am 08:22 AM

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

Python vs. JavaScript:学習曲線と使いやすさ Python vs. JavaScript:学習曲線と使いやすさ Apr 16, 2025 am 12:12 AM

Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

C/CからJavaScriptへ:すべてがどのように機能するか C/CからJavaScriptへ:すべてがどのように機能するか Apr 14, 2025 am 12:05 AM

C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合) next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合) Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

See all articles