WebGL:ブラウザ内で3Dグラフィックスを楽しむための入門ガイド

こんにちは、未来の3Dグラフィックスの魔法使いさんたち!このエキサイティングな旅にあなたをお連れするのはとても嬉しいです。コンピュータグラフィックスを多年間教えてきた者として、WebGLはブラウザの中で魔法の杖のような存在です。素晴らしい3Dグラフィックスやアニメーションをウェブページ上で作成できるのです。すごくないですか?さあ、BEGIN!

WebGL - Home

WebGLとは?

WebGLは、Web Graphics Libraryの略で、JavaScript APIによって、プラグインなしで対応するウェブブラウザ上にインタラクティブな2Dおよび3Dグラフィックスを描画することができます。まるでブラウザに素晴らしいビジュアル体験を作り出す超能力を与えるようなものです!

短い歴史

WebGLは2011年に初めて導入され、それ以来、ウェブ上のグラフィックスに対する私たちの考え方を革命づけました。WebGL導入前は、ブラウザ上で3Dグラフィックスを作成するには、FlashやJavaアプレットなどのプラグインに依存する必要がありました。今は、WebGLを使えば、ブラウザ上で nativity にすべて行うことができます。自転車からスポーツカーへのアップグレードのようなものです!

前提条件

私たちのWebGLの冒険を始める前に、正しいツールがバックパックに入っているか確認しましょう:

  1. 現代のウェブブラウザ(Chrome、Firefox、Safari、またはEdge)
  2. テキストエディタ(Visual Studio Codeをお勧めしますが、他でも可)
  3. HTMLとJavaScriptの基本知識(古い知識でも心配ありません。進めつつ復習します)

WebGLで始める

まず、初めてのWebGLプログラムを作成しましょう!シンプルな「Hello, WebGL!」の例で、画面に色つきの三角形を表示します。

ステップ1: HTMLの設定

まず、canvas要素を含むHTMLファイルを作成します。このcanvasが私たちのWebGL魔法の場となります。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello, WebGL!</title>
<style>
canvas { border: 1px solid black; }
</style>
</head>
<body>
<canvas id="glCanvas" width="640" height="480"></canvas>
<script src="webgl-demo.js"></script>
</body>
</html>

このHTMLでは、IDが「glCanvas」のcanvas要素を作成し、そのサイズを640x480ピクセルに設定しています。また、「webgl-demo.js」というJavaScriptファイルをリンクして、そこにWebGLのコードを書きます。

ステップ2: WebGLの初期化

次に、「webgl-demo.js」ファイルを作成し、JavaScriptを書いてWebGLを初期化します:

function main() {
const canvas = document.getElementById("glCanvas");
const gl = canvas.getContext("webgl");

if (!gl) {
alert("WebGLを初期化できません。ブラウザまたはマシンがサポートしていない可能性があります。");
return;
}

// 背景を黒色に設定し、カラーバッファをクリア
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
}

window.onload = main;

以下のように解説します:

  1. canvas要素を参照します。
  2. WebGLコンテキストをcanvasから取得します。失敗すると、エラーメッセージを表示します。
  3. 成功すると、背景色を黒色に設定し、カラーバッファをクリアします。

ステップ3: シェーダーの作成

シェーダーはGPU上で動作する特殊なプログラムで、GLSL(OpenGL Shading Language)という言語で書かれています。頂点シェーダーとフラグメントシェーダーの2種類が必要です。

// 頂点シェーダープログラム
const vsSource = `
attribute vec4 aVertexPosition;

void main() {
gl_Position = aVertexPosition;
}
`;

// フラグメントシェーダープログラム
const fsSource = `
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;

頂点シェーダーは頂点の位置を設定し、フラグメントシェーダーはピクセルの色(この場合は赤色)を設定します。

ステップ4: シェーダープログラムの初期化

次に、これらのシェーダーをコンパイルし、リンクしてシェーダープログラムを作成します:

function initShaderProgram(gl, vsSource, fsSource) {
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);

const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('シェーダープログラムを初期化できません:' + gl.getProgramInfoLog(shaderProgram));
return null;
}

return shaderProgram;
}

function loadShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert('シェーダーをコンパイルできません:' + gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}

return shader;
}

このコードはシェーダーをコンパイルし、リンクしてプログラムを作成し、エラーがないか確認します。

ステップ5: 三角形の作成

次に、三角形のデータを作成します:

function initBuffers(gl) {
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

const positions = [
-1.0,  1.0,
1.0,  1.0,
-1.0, -1.0,
];

gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

return {
position: positionBuffer,
};
}

このコードはバッファを作成し、三角形の頂点の位置データを設定します。

ステップ6: シーンの描画

最後に、すべてを合わせて三角形を描画します:

function drawScene(gl, programInfo, buffers) {
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);

gl.useProgram(programInfo.program);

gl.enableVertexAttribArray(programInfo.attribLocations.vertexPosition);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.position);
gl.vertexAttribPointer(
programInfo.attribLocations.vertexPosition,
2,        // 2成分ごとに繰り返し
gl.FLOAT, // データは32ビットの浮動小数点数
false,    // 正規化しない
0,        // ストライド(0 = 自動)
0         // バッファ内のオフセット
);

gl.drawArrays(gl.TRIANGLES, 0, 3);
}

この関数はキャンバスをクリアし、シェーダープログラムを設定し、バッファデータを接続して三角形を描画します。

すべてを合わせる

さあ、「main」関数を更新して、これらのすべてのピースを使いましょう:

function main() {
const canvas = document.getElementById("glCanvas");
const gl = canvas.getContext("webgl");

if (!gl) {
alert("WebGLを初期化できません。ブラウザまたはマシンがサポートしていない可能性があります。");
return;
}

const shaderProgram = initShaderProgram(gl, vsSource, fsSource);

const programInfo = {
program: shaderProgram,
attribLocations: {
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
},
};

const buffers = initBuffers(gl);

drawScene(gl, programInfo, buffers);
}

window.onload = main;

これで、初めてのWebGLプログラムが完成しました。ブラウザでHTMLファイルを開くと、黒い背景に赤い三角形が表示されるはずです。おめでとうございます!

よく使うWebGLメソッド

以下に、私たちが使用したよくあるWebGLメソッドとその目的を示します:

メソッド 目的
gl.createBuffer() 新しいバッファオブジェクトを作成します
gl.bindBuffer() バッファオブジェクトをターゲットにバインドします
gl.bufferData() バッファオブジェクトのデータストアを初期化および作成します
gl.createShader() シェーダーオブジェクトを作成します
gl.shaderSource() シェーダーオブジェクトのソースコードを設定します
gl.compileShader() シェーダーオブジェクトをコンパイルします
gl.createProgram() プログラムオブジェクトを作成します
gl.attachShader() シェーダーオブジェクトをプログラムオブジェクトにアタッチします
gl.linkProgram() プログラムオブジェクトをリンクします
gl.useProgram() 指定されたプログラムを現在のレンダリングステートの一部として設定します
gl.getAttribLocation() 属性変数の位置を取得します
gl.enableVertexAttribArray() ヴァーチャ attributes 配列を有効にします
gl.vertexAttribPointer() ヴァーチャ attributes 配列のレイアウトを指定します
gl.drawArrays() 配列データからプリミティブをレンダリングします

結論

今日は多くのことをカバーしました!WebGLとは何か、開発環境を設定し、最初のWebGLプログラムを作成しました。WebGLを学ぶことは、自転車を乗るのと同じで、最初は揺れが大きいかもしれませんが、練習すればすぐにスムーズに進むようになります!

次回のレッスンでは、より複雑な形状を探求し、インタラクティブな要素を追加し、3Dグラフィックスにまで進みます。WebGLの世界は広大でエキサイティングです。あなたと一緒にさらに探求できることをとても楽しみにしています。それでは、次回まで、ハッピーコーディングを!

Credits: Image by storyset