WebGL - キューブの回転

こんにちは、未来のWebGL魔術師たち!今日は、3Dグラフィックスの世界への興奮的な旅を始めます。このチュートリアルの最後に、あなたはWebGLを使って回転するキューブを作成できるようになるでしょう。素晴らしいですね?さあ、潜りましょう!

WebGL - Cube Rotation

基本を理解する

キューブをDJのように回転させる前に、いくつかの基本的な概念を理解しましょう。

WebGLとは?

WebGL(Web Graphics Library)は、ブラウザ内で3Dグラフィックスを描画するためのJavaScript APIです。まるでブラウザに3D眼鏡を装着しているようなものです!

なぜキューブ?

「なぜキューブから始めるのか」と疑うかもしれません。そうですね、私の愛する学生们、キューブは3Dグラフィックスの「Hello World」とも言えます。簡単で理解しやすく、同時に重要な概念を教えてくれます。そして、誰もがキューブが好きですよね?

WebGL環境の設定

HTMLキャンバス

まず最初に、キューブがパフォーマンスを行うステージが必要です。WebGLでは、このステージをキャンバスと呼びます。以下のように設定しましょう:

<canvas id="glcanvas" width="640" height="480">
あなたのブラウザはHTML5キャンバスをサポートしていません
</canvas>

これで640x480ピクセルのキャンバスが作成されます。見えない場合は、今は無視して構いません - 現在は無形のダンスフロアのようなものです。

WebGLの初期化

次に、WebGLをパーティーの準備にしましょう:

var canvas = document.getElementById('glcanvas');
var gl = canvas.getContext('webgl');

if (!gl) {
console.log('WebGLがサポートされていません。experimental-webglにフォールバックします');
gl = canvas.getContext('experimental-webgl');
}

if (!gl) {
alert('あなたのブラウザはWebGLをサポートしていません');
}

このコードでWebGLのコンテキストを取得します。ブラウザがWebGLをサポートしていない場合、DVDをVHSプレイヤーで再生しようとするようなものです - 効かないでしょう!

3Dキューブの作成

頂点の定義

キューブには8つの角(頂点)があります。これらの角がどこにあるかをWebGLに伝える必要があります:

var vertices = [
//前面
-1.0, -1.0,  1.0,
1.0, -1.0,  1.0,
1.0,  1.0,  1.0,
-1.0,  1.0,  1.0,

//後面
-1.0, -1.0, -1.0,
-1.0,  1.0, -1.0,
1.0,  1.0, -1.0,
1.0, -1.0, -1.0,

//上面
-1.0,  1.0, -1.0,
-1.0,  1.0,  1.0,
1.0,  1.0,  1.0,
1.0,  1.0, -1.0,

//下面
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0,  1.0,
-1.0, -1.0,  1.0,

//右面
1.0, -1.0, -1.0,
1.0,  1.0, -1.0,
1.0,  1.0,  1.0,
1.0, -1.0,  1.0,

//左面
-1.0, -1.0, -1.0,
-1.0, -1.0,  1.0,
-1.0,  1.0,  1.0,
-1.0,  1.0, -1.0
];

この3つの数のセットは、キューブの角を3D空間上で表現しています。まるでWebGLにキューブの地図を渡しているようなものです!

バッファーの作成

次に、このデータをGPUに送信する必要があります:

var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

これは、キューブをスーツケース(バッファー)に詰め、GPUに送信するようなものです。

シェーダー - WebGLの魔術師

頂点シェーダー

頂点シェーダーは、頂点の位置を設定します:

var vertexShaderSource = `
attribute vec3 aVertexPosition;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
void main(void) {
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);
}
`;

このシェーダーは各頂点に変換行列を適用します。まるで魔術師がキューブの角を動かしているようなものです!

フラグメントシェーダー

フラグメントシェーダーは、キューブを色付けします:

var fragmentShaderSource = `
void main(void) {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;

このシンプルなシェーダーはすべてを白色にします。まるでキューブを塗装しているようなものです!

シェーダーのコンパイルとリンク

次に、シェーダーをコンパイルし、プログラムにリンクします:

function getShader(gl, source, type) {
var shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert('シェーダーのコンパイルにエラーが発生しました: ' + gl.getShaderInfoLog(shader));
return null;
}

return shader;
}

var vertexShader = getShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
var fragmentShader = getShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);

var 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));
}

gl.useProgram(shaderProgram);

これは、魔術師(シェーダー)に技を教え、ステージに立てるようなものです!

キューブの回転

回転の設定

キューブを回転させるためには、時間とともに回転角度を更新する必要があります:

var cubeRotation = 0.0;
var then = 0;

function render(now) {
now *= 0.001;  //秒に変換
const deltaTime = now - then;
then = now;

cubeRotation += deltaTime;

drawScene();

requestAnimationFrame(render);
}

この関数は繰り返し呼び出され、キューブの回転を更新します。

シーンの描画

次に、すべてをまとめ、回転するキューブを描画しましょう:

function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

const projectionMatrix = mat4.create();
mat4.perspective(projectionMatrix, 45 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.1, 100.0);

const modelViewMatrix = mat4.create();
mat4.translate(modelViewMatrix, modelViewMatrix, [-0.0, 0.0, -6.0]);
mat4.rotate(modelViewMatrix, modelViewMatrix, cubeRotation, [0, 1, 1]);

gl.uniformMatrix4fv(gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'), false, projectionMatrix);
gl.uniformMatrix4fv(gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'), false, modelViewMatrix);

gl.drawArrays(gl.TRIANGLE_STRIP, 0, 36);
}

この関数はキャンバスをクリアし、視点を設定し、回転を適用し、最後にキューブを描画します。

結論

そして、みなさん!私たちはWebGLを使って回転する3Dキューブを作成しました。WebGLをマスターすることは、ジャグリングするのと同じで - 練習は必要ですが、一度習ったら素晴らしいことができます!

以下に、私たちが使用した主要なメソッドの表を示します:

メソッド 説明
gl.createBuffer() 新しいバッファーオブジェクトを作成します
gl.bindBuffer() バッファーオブジェクトをターゲットにバインドします
gl.bufferData() バッファーオブジェクトのデータストアを作成および初期化します
gl.createShader() シェーダーオブジェクトを作成します
gl.shaderSource() シェーダーオブジェクトのソースコードを設定します
gl.compileShader() シェーダーオブジェクトをコンパイルします
gl.createProgram() プログラムオブジェクトを作成します
gl.attachShader() シェーダーオブジェクトをプログラムオブジェクトにアタッチします
gl.linkProgram() プログラムオブジェクトをリンクします
gl.useProgram() 指定されたプログラムを現在の描画状態として設定します
gl.clear() バッファーを预设の値にクリアします
gl.uniformMatrix4fv() 現在のプログラムのユニフォーム変数の値を設定します
gl.drawArrays() 配列データからプリミティブをレンダリングします

練習を続け、コードを書き続けると、すぐにブラウザ内で素晴らしい3Dグラフィックスを作成できるようになります。ハッピーコーディング!

Credits: Image by storyset