Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
軽率にBabylon.jsの WebGPUエンジンを使って ComputeShaderに入門し...
Search
にー兄さん
September 30, 2023
Technology
0
780
軽率にBabylon.jsの WebGPUエンジンを使って ComputeShaderに入門した / learn-about-babylonjs-webgpu-computeshader
IwakenLab Shaderこんな感じ発表会#2
にー兄さん
September 30, 2023
Tweet
Share
More Decks by にー兄さん
See All by にー兄さん
軽率にAndroidXRのJetpack SceneCoreを使って3Dモデルを表示してみる / androidxr-scenecore-3dmodels
drumath2237
0
35
UnJSを使って軽率にCLIを作ってみたらめちゃくちゃ便利だった / create CLI with UnJS
drumath2237
4
1.5k
create-babylon-appを軽率にアプデしたい / update create babylon app
drumath2237
1
1.6k
Babylon.js 7注目機能を 軽率にまとめてみる/whats-new-in-babylonjs-v7
drumath2237
1
320
軽率にVFX Graphと Compute Shaderを 組み合わせるテクニック/integrate-vfxgraph-and-compute-shader
drumath2237
1
400
軽率にVue 3で リアルタイム3Dアプリを作れる ライブラリを作ってみた/vue-with-3d-app
drumath2237
3
1.9k
軽率にBabylon.jsを C#で使う技術 / using-babylonjs-with-csharp
drumath2237
1
870
今こそ軽率に理解したい WebXR Device APIとBabylon.jsの話 / understand-webxr-device-api-and-babylonjs
drumath2237
0
220
Vue・Babylon連携ライブラリ BabyuewJSについて / about-babyuewjs
drumath2237
0
190
Other Decks in Technology
See All in Technology
クラウドサービス事業者におけるOSS
tagomoris
4
1k
入門 PEAK Threat Hunting @SECCON
odorusatoshi
0
140
Amazon Aurora のバージョンアップ手法について
smt7174
2
140
PHPカンファレンス名古屋-テックリードの経験から学んだ設計の教訓
hayatokudou
2
540
Iceberg Meetup Japan #1 : Iceberg and Databricks
databricksjapan
0
320
What's new in Go 1.24?
ciarana
1
110
OPENLOGI Company Profile
hr01
0
60k
開発組織を進化させる!AWSで実践するチームトポロジー
iwamot
1
170
Pwned Labsのすゝめ
ken5scal
1
340
OCI Success Journey OCIの何が評価されてる?疑問に答える事例セミナー(2025年2月実施)
oracle4engineer
PRO
2
120
IAMポリシーのAllow/Denyについて、改めて理解する
smt7174
2
200
(機械学習システムでも) SLO から始める信頼性構築 - ゆる SRE#9 2025/02/21
daigo0927
0
260
Featured
See All Featured
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
GraphQLの誤解/rethinking-graphql
sonatard
68
10k
Building an army of robots
kneath
303
45k
Building a Scalable Design System with Sketch
lauravandoore
461
33k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.1k
Building Flexible Design Systems
yeseniaperezcruz
328
38k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
129
19k
VelocityConf: Rendering Performance Case Studies
addyosmani
328
24k
Thoughts on Productivity
jonyablonski
69
4.5k
Adopting Sorbet at Scale
ufuk
74
9.2k
It's Worth the Effort
3n
184
28k
GitHub's CSS Performance
jonrohan
1030
460k
Transcript
軽率にBabylon.jsの WebGPUエンジンを使って ComputeShaderに入門した Shaderってこんな感じ発表会 #2 にー兄さん(@ninisan_drumath)
にー兄さん(@ninisan_drumath) ソフトウェアエンジニア 株式会社ホロラボ / IwakenLab Unity / ロケーションベースAR / WebAR
/ Babylon.js / Azure Kinect 最新技術を使った検証開発や デモンストレーションが好き 唐突な うちの猫たち→
本日の話: 「WebGPUのComputeShaderって こんな感じ」 Babylon.jsの
アジェンダ - WebGPUとかWGSLとかComputeShaderとか - Babylon.jsでもComputeShaderが使いたい - おわりに
WebGPUとかWGSLとか ComputeShaderとか
WebGPUとは① ブラウザ向けグラフィクスAPIの一種 従来はWebGL・WebGL2などがあり、 WebGL2が主流になろうとしている(ここの温度感あってる?) 今年の5月くらいにPC向けGoogle Chrome 113から 特殊な設定なしで利用できるように
WebGPUとは② 嬉しいところ - 低レベルなAPIを採用され、処理効率が向上 - モダングラフィクスAPIの流れを汲んでいる - コンピュートシェーダが使える これからに期待 -
2023年現在 使える環境が限られている - WebXRでは使えない、はず(要出典)
WGSL WebGPUで採用されているシェーダ言語 Rustっぽい構文 下記はCYOSで生成されたコードの比較(少し調整済み) #version 300 es precision highp float;
in vec3 position; uniform mat4 worldViewProjection; out vec4 vPosition; void main() { vec4 p = vec4(position, 1.f); vPosition = p; gl_Position = worldViewProjection * p; } #include<sceneUboDeclaration> #include<meshUboDeclaration> attribute position : vec3<f32>; varying vPosition : vec4<f32>; @vertex fn main(input: VertexInputs) -> FragmentInputs { let p = vec4<f32>(vertexInputs.position, 1.0); vertexOutputs.vPosition = p; vertexOutputs.position = scene.viewProjection * mesh.world * p; } WGSL GLSL
Compute Shader 汎用的な計算をGPUで行うための仕組み つまりGPGPU(General Purpose GPU) WebGL系ではこの仕組みが無かったので vertex/fragmentシェーダで実現していた WebGPUには標準搭載されており、WGSLで書ける
Babylon.jsでも ComputeShaderが使いたい
完成イメージ
どんなものを作るか GPUパーティクルを意識して 大量のオブジェクトの属性計算をGPGPUで処理したい (今回は90,000パーティクル) 平面上のランダムな位置にパーティクル位置を初期化 StorageBufferにPositionの配列を格納 3D Sin Waveを適用(dispatch) PointsCloudSystemにPosition配列を適用
時間によってアニメーションさせて上記処理を繰り返す
環境 - Windows 10 Home - Google Chrome 117 -
Babylon.js 6.7.0 - WebGPU Engine使用 - Vite + TypeScript - もし素でWebGPUをTSで開発する場合 @webgpu/typesに型定義があります - Babylon.jsでは不要です サンプルはGitHubで公開しています(docs整備中) https://github.com/drumath2237/babylon-compute-shader-sandbox
Babylon.jsにおけるWebGPUとComputeShader WebGPUは ほぼフルサポート 一部機能は動かないらしい 基本的にEngineをWebGPUEngineに差し替えれば 既存のWebGLアプリから移行できる const engine = new WebGPUEngine(renderCanvas,
{ antialias: true, }); await engine.initAsync(); ComputeShaderはWebGPUエンジンでのみ使用可能 > Note that in Babylon.js this is a WebGPU feature only (starting at v5.0), WebGL does not support compute shaders.
ComputeShaderを書く(3dSinWave.wgsl) struct Params { time: f32 } @group(0) @binding(0) var<uniform>
params : Params; @group(0) @binding(1) var<storage,read_write> positionBuffer : array<f32>; @compute @workgroup_size(2,1,1) fn main(@builtin(global_invocation_id) global_id: vec3<u32>) { var particleId = global_id.x * u32(300) + global_id.y; var x = positionBuffer[particleId * u32(3)]; var z = positionBuffer[particleId * u32(3) + u32(2)]; var distance = sqrt(x * x + z * z); positionBuffer[particleId * u32(3) + u32(1)] = sin(distance * 1.2 - params.time); } 拡張機能を入れれば VSCodeで普通に書ける
ComputeShaderインスタンスの作成 Compute Shaderのコードと bindingsのLayoutを定義して インスタンス化 const sinWaveComputeShader = new ComputeShader(
"3d sin wave", engine, { computeSource: computeShaderSource }, { bindingsMapping: { params: { group: 0, binding: 0 }, positionBuffer: { group: 0, binding: 1 }, }, } );
UniformBufferを作成 プリミティブな値は UniformBufferとして渡している 時間によるアニメーションのための float32を渡して更新する let time = 5; const
waveParamsUniformBuffer = new UniformBuffer( engine, undefined, undefined, "params" ); waveParamsUniformBuffer.addUniform("time", 1); waveParamsUniformBuffer.updateFloat("time", time); sinWaveComputeShader.setUniformBuffer( "params", waveParamsUniformBuffer );
Position配列の初期化とStorageBufferの作成 PointCloudSystemと Compute Shaderの相互で 参照するPosition配列(Float32Array) ComputeShaderには StorageBufferに変換して渡している const positionBuffer =
new Float32Array(PARTICLE_COUNT * 3); for (let i = 0; i < PARTICLE_COUNT; i++) { positionBuffer[i * 3] = randomNumberBetween(-10, 10); positionBuffer[i * 3 + 1] = 0; positionBuffer[i * 3 + 2] = randomNumberBetween(-10, 10); } const positionStorage = new StorageBuffer( engine, positionBuffer.byteLength ); positionStorage.update(positionBuffer); sinWaveComputeShader.setStorageBuffer( "positionBuffer", positionStorage);
繰り返しdispatch シーンのレンダリングループで 時間を更新して位置を再計算 dispatchのコスト高そうなので あまりよくない……? scene.registerBeforeRender(async () => { time
+= 0.1; waveParamsUniformBuffer.updateFloat("time", time); waveParamsUniformBuffer.update(); await sinWaveComputeShader.dispatchWhenReady( PARTICLE_ONE_SIDE, PARTICLE_ONE_SIDE ); const res = await positionStorage.read(); positionBuffer.set(new Float32Array(res.buffer)); pointCloud.setParticles(); });
完成
おわりに
まとめと感想 WebGPUのComputeShader気になっていたので 入門できてうれしい Babylon.jsだと普通に動くっぽいのでみんなでやろう
参考 WebGPUがついに利用可能に WebGL以上の高速な描画と、計算処理への可能性 https://ics.media/entry/230426/ IwakenLabShader勉強会でBabylon.jsにおけるComputeShaderでGPUパーティクルを行うデモの準備 https://zenn.dev/drumath2237/scraps/082ff30318fb2e WGSL 仕様メモ https://ikorin2.hatenablog.jp/entry/2023/04/23/213426 Compute
Shaders | Babylon.js Documentation https://doc.babylonjs.com/features/featuresDeepDive/materials/shaders/computeShader