6
5

バッファレスレンダリングで25行から始めるWebGL2

Last updated at Posted at 2024-07-20

WebGLが動くかどうか試そうと思った方、ちょろっとコードを書いてみようとしても、頂点バッファを用意するのって微妙に面倒ですよね。
WebGL2では、頂点シェーダでgl_VertexIDという内部変数を使うことができます。

これをうまく使うことで、頂点バッファを使わずに三角形を描画することができます。

@cx20 さんの以下の記事のコードをベースに、さらに短い最短のWebGLコードを書いてみましょう。

25行のWebGL2コード

こんな感じになります(25行と言いつつ厳密には26行なんだけど)。

let c, gl;
let v = '#version 300 es\nprecision highp float; void main() { float x = float(gl_VertexID - 1); float y = float((gl_VertexID & 1) * 2 - 1); gl_Position = vec4(x, y, 0.0, 1.0); }';
let f = '#version 300 es\nprecision highp float; out vec4 fragColor; void main() { fragColor = vec4(0.0, 0.0, 1.0, 1.0); }';
function initWebGL() {
    c = document.getElementById("c");
    gl = c.getContext("webgl2");
}
function initShaders() {
    var p = gl.createProgram();
    var vs = gl.createShader(gl.VERTEX_SHADER);
    var fs = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(vs, v);
    gl.shaderSource(fs, f);
    gl.compileShader(vs);
    gl.compileShader(fs);
    gl.attachShader(p, vs);
    gl.attachShader(p, fs);
    gl.linkProgram(p);
    gl.useProgram(p);
}
function draw() {
    gl.drawArrays(gl.TRIANGLES, 0, 3);
}
initWebGL();
initShaders();
draw();

実行するとちゃんと三角形が表示されます。

image.png

実際に動くコードは以下のJSBinに置きました。

頂点シェーダの部分を紐解いてみましょう。gl_VertexIDの部分にそれぞれ0, 1, 2が来た時を想像して暗算してみると、三角形ができることがわかると思います。「こんなの思いつかないよ」と思われるかもしれませんが、ある程度パターンが決まっているので、そのままおまじないとして覚えてしまうのがよろしいかと思います。

#version 300 es
precision highp float;
void main() {
    float x = float(gl_VertexID - 1);
    float y = float((gl_VertexID & 1) * 2 - 1);
    gl_Position = vec4(x, y, 0.0, 1.0);
}

番外編: 画面全体を覆う矩形を頂点バッファなしで描画する

ちなみに、以下のコードで画面を完全に覆う矩形を描画することができます。テクスチャ座標付きなので、頂点バッファを用意せずにポストプロセスやスクリーンスペースの処理ができ便利です。このコードもおまじないと思ってメモっておきましょう。

#version 300 es
precision highp float;
out vec2 texCoord
void main() {
    float x = float((gl_VertexID & 1) << 2); // 0, 4, 0
    float y = float((gl_VertexID & 2) << 1); // 0, 0, 4
    texCoord.x = x * 0.5;
    texCoord.y = y * 0.5;
    gl_Position = vec4(x - 1.0, y - 1.0, 0, 1);
    // x, y, u, v
    // -1, -1, 0, 0
    // 3, -1, 2, 0
    // -1, 3, 0, 2
}

図にするとこんな感じ(図中の数字はUVです)。大きな三角形を描画して、ラスタライズステージでフレームバッファに合うようはみ出た部分のフラグメントは破棄されるんですね。

image.png

こうした、頂点バッファを使わずに何らかの描画を行うことをバッファレスレンダリングと呼んだりするそうです。

まとめ

「最短25行で書けちゃうWebGL2」という記事でした。バッファレスレンダリングを行うことで、頂点データのセットアップを省略でき、コードをシンプルに保つことができます。どんどん使っていきましょう。

6
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5