「WebGPU」でシェーダーを使って三角形を1つだけ描画してみよう

2025年7月17日(木)
大西 武 (オオニシ タケシ)
第5回の今回は、WebGPUでシンプルなシェーダーを使って三角形を描画する解説をします。

黒い三角形を1個だけ描画する

やっと三角形を1個だけ描画するところまできました(図3)。これだけのことなのに、これほど面倒ですね。今後の回以降はこれに肉付けしていき、複数の三角形を描画してオブジェクトを作ったり、様々な色にしたり、テクスチャを貼ったり、移動したり、アニメーションしたりします。

図3:黒い三角形を1個だけ描画

「index.html」ファイルで「lib」→「Model3D.js」を読み込む

三角形のデータを保持するクラスとして「Model3D」クラスをコーディングする「Model3D.js」ファイルを読み込みます。<script>タグの「init」関数でModel3Dクラスのインスタンスを生成して「_model」変数に代入し、頂点バッファを初期化します。「draw」関数でモデルを描画します。

・サンプルコード「index.html」
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>UltraMotion3D</title>
    <script src="lib/Model3D.js"></script>
    <script src="lib/WGSL.js"></script>
    <script src="lib/UltraMotion3D.js"></script>
    <script type="text/javascript">
var _model;
  
function init() {
  _model = new Model3D();
  _model.initBuffers();
}

function draw() {
  _model.draw();
}
    </script>
  </head>
  <body onload='initWebGPU("CanvasAnimation");'>
    <canvas id="CanvasAnimation" width="1000" height="900"></canvas>
  </body>
</html>

「lib」→「UltraMotion3D.js」に追記する

次のサンプルコードを「UltraMotion3D.js」ファイルに追記します。背景色を(R,G,B,A)=(1.0,1.0,1.0,1.0)の真っ白に変えました。描画のタイミングで「index.html」の「draw」関数を呼び出しているだけです。

・サンプルコード「lib」→「UltraMotion3D.js」
var _passEncoder = null;

async function initWebGPU(canvas) {
(中略)
}

function setPipeline(vertexWGSL,fragmentWGSL) {
(中略)
}

function everyFrame() {
  _commandEncoder = _device.createCommandEncoder();
  const textureView = _context.getCurrentTexture().createView();
  _renderPassDescriptor = {
    colorAttachments: [
      {
        view: textureView,
        clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
        loadOp: 'clear',
        storeOp: 'store',
      },
    ],
    depthStencilAttachment: {
      view: _depthTexture.createView(),
      depthClearValue: 1.0,
      depthLoadOp: 'clear',
      depthStoreOp: 'store',
    },
  };
  _passEncoder = _commandEncoder.beginRenderPass(_renderPassDescriptor);
  draw();
  _passEncoder.end();
  _device.queue.submit([_commandEncoder.finish()]);
}

function resize() {
(中略)
}

Model3Dクラスを実装する

「lib」→「Model3D.js」ファイルに3Dモデルを持つModel3Dクラスを宣言します。コンストラクタで3頂点と、それらを指すインデックスのプロパティを宣言します。「initBuffers」メソッドで頂点を入れるバッファを用意します。「draw」メソッドで3頂点の三角形を描画します。

次のサンプルコードを実装したら、index.htmlファイルをGoogle Chromeで開いてください。黒い三角形が表示されましたね。

・サンプルコード「lib」→「Model3D.js」
class Model3D {
  constructor() {
    this.vertices = [0,1,0,1, -1,-1,0,1, 1,-1,0,1];
    this.indices = [0,1,2];
  }
  initBuffers() {
    this.vertexArray = new Float32Array(this.vertices);
    this.verticesBuffer = _device.createBuffer({
      size: this.vertexArray.byteLength,
      usage: GPUBufferUsage.VERTEX,
      mappedAtCreation: true,
    });
    new Float32Array(this.verticesBuffer.getMappedRange()).set(this.vertexArray);
    this.verticesBuffer.unmap();
  }
  getVertexCount() {
    return ~~(this.vertexArray.length/4);
  }
  draw() {
    _passEncoder.setPipeline(_pipeline);
    _passEncoder.setVertexBuffer(0,this.verticesBuffer);
    _passEncoder.draw(this.getVertexCount());
  }
}

【サンプルコードの解説】
コンストラクタ(「constructor」メソッド)で(X,Y,Z,W)の3頂点を「vertices」プロパティに代入し、3頂点を指すインデックスを「indices」プロパティに代入します。
「initBuffers」メソッドでverticesプロパティは「Float32Array」配列に変換し、頂点バッファに入れます。
「draw」メソッドでパスエンコーダーにパイプラインをセットし、頂点バッファをセットして頂点の数だけ描画します。

【コラム】「CUI→GUI→?の次を考え出したい」

新たなユーザーインターフェースを生み出したいです。昔は文字だけでOSを操っていて、今はグラフィカルにマウスでOSを操ります。そこでその次を考えていて、誰でも使えるぐらいシンプルなOSのユーザーインターフェースを考えました。例えば「Webブラウザを起動しますか?」と聞かれたら、YesかNoだけで答えます。他にも全てYesかNoだけで操作します。でも、あまりにも自由度が低過ぎました…。

おわりに

今回は3つの頂点をシェーダーに渡し、それを囲んで真っ黒な三角形を描画する解説をしました。まだ色のデータは渡していないため、フラグメントシェーダーの中で黒色限定で塗ってみました。

次回は、ベクトルとベクトルの計算を実装する解説をします。

著者
大西 武 (オオニシ タケシ)
1975年香川県生まれ。大阪大学経済学部経営学科中退。プログラミング入門書など30冊以上を商業出版する作家。Microsoftで大賞やNTTドコモでグランプリなど20回以上全国区のコンテストに入賞するアーティスト。オリジナルの間違い探し「3Dクイズ」が全国放送のTVで約10回出題。
https://profile.vixar.jp

連載バックナンバー

開発言語技術解説
第5回

「WebGPU」でシェーダーを使って三角形を1つだけ描画してみよう

2025/7/17
第5回の今回は、WebGPUでシンプルなシェーダーを使って三角形を描画する解説をします。
開発言語技術解説
第4回

はじめての「WebGPU」で背景色を塗りつぶしてみよう

2025/6/25
第4回の今回は、WebGPUを初期化してタグを真っ黒な背景色で塗りつぶしてみる解説をします。
開発言語技術解説
第3回

WebGPUライブラリ「UltraMotion3D」で3DのサンプルWebコンテンツを動かしてみよう

2025/6/5
第3回の今回は、WebGPUライブラリ「UltraMotion3D」を使った3DのサンプルWebコンテンツの動かし方と「XAMPP」の使い方を解説します。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています