WebGL - モデルの描画:入門ガイド

こんにちは、未来的なWebGLの魔法使いさんたち!この3Dグラフィックスプログラミングの興奮する旅におけるあなたのガイドとして、私はとても嬉しいです。コンピュータサイエンスを多年間教えてきた者として、WebGLでモデルを描くことはデジタルなレゴブロックで建築するようなものだと言えます。それは挑戦的ですが、非常に報酬があります。では、画面に魔法を創り出すために一緒に潜りましょう。

WebGL - Drawing a Model

基礎を理解する

モデルを描く前に、まずWebGLとは何か簡単に復習しましょう。WebGL(Web Graphics Library)は、プラグインなしでブラウザ内で3DグラフィックスをレンダリングできるJavaScript APIです。まるであなたのウェブページにスーパーパワーを与えるようなものです!

さて、WebGLでモデルを描く際には、主に以下の2つの方法があります。

描画方法

メソッド 説明 使用シーン
drawArrays() 配列データを使用してプリミティブを描画 単純な形状、インデックスなしの幾何学形状
drawElements() インデックス付きプリミティブを描画 複雑なモデル、効率化されたレンダリング

これらの方法を詳しく見ていきましょう。

drawArrays() メソッド:簡略化された描画

drawArrays() とは?

drawArrays() メソッドは、単純でシンプルな形状を描くのに適しています。このメソッドは、頂点データの配列を使用して幾何学プリミティブを描画します。

文法とパラメータ

gl.drawArrays(mode, first, count);
  • mode: 描画するプリミティブの種類(例:gl.TRIANGLES、gl.LINES)
  • first: 配列内の開始インデックス
  • count: 描画する頂点の数

例:三角形の描画

drawArrays() を使用して単純な三角形を描いてみましょう:

// 三角形の頂点データ
const vertices = [
0.0,  0.5,  0.0,  // 上部の頂点
-0.5, -0.5,  0.0,  // 左下の頂点
0.5, -0.5,  0.0   // 右下の頂点
];

// バッファの作成とバインド
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

// 属性ポインタの設定
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);

// 三角形の描画
gl.drawArrays(gl.TRIANGLES, 0, 3);

この例では、三角形の3つの頂点を定義し、データを格納するバッファを作成し、頂点データの読み方をWebGLに指示して、最後に drawArrays() を呼び出して三角形をレンダリングします。

drawElements() メソッド:複雑なモデルの作成

drawElements() とは?

drawArrays() が鉛筆でのスケッチングであるなら、drawElements() はブラシでの絵の描き方です。このメソッドは、複雑な形状を描く際により多くの制御と効率を提供します。このメソッドはインデックスレンダリングを使用しており、頂点データを再利用できます。

文法とパラメータ

gl.drawElements(mode, count, type, offset);
  • mode: 描画するプリミティブの種類
  • count: 描画する要素の数
  • type: エレメント配列バッファ内の値の種類
  • offset: エレメント配列バッファ内的オフセット

例:正方形の描画

drawElements() を使用して正方形を描いてみましょう:

// 正方形の頂点データ
const vertices = [
-0.5,  0.5,  0.0,  // 左上
0.5,  0.5,  0.0,  // 右上
0.5, -0.5,  0.0,  // 右下
-0.5, -0.5,  0.0   // 左下
];

// インデックスデータ
const indices = [
0, 1, 2,  // 最初の三角形
0, 2, 3   // 二つ目の三角形
];

// 頂点バッファの作成とバインド
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

// インデックスバッファの作成とバインド
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

// 属性ポインタの設定
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);

// 正方形の描画
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);

この例では、正方形の4つの頂点を定義し、インデックスを使用してこれらの頂点がどのように接続されるべきかを指定します。頂点バッファとインデックスバッファを作成し、属性ポインタを設定した後、drawElements() を呼び出して正方形をレンダリングします。

必要な操作:成功のレシピ

WebGLでモデルを無事に描画するためには、いくつかの鍵となるステップを踏む必要があります。これをレシピとして考えてください。

WebGL描画チェックリスト

  1. バッファの作成: モデルデータを格納するための頂点バッファとインデックスバッファを設定します。
  2. シェーダーのコンパイル: 頂点シェーダーとフラグメントシェーダーを書き、コンパイルします。
  3. プログラムの作成: コンパイルされたシェーダーをリンクしてプログラムを作成します。
  4. 属性ポインタの設定: WebGLが頂点データをどのように解釈するかを指示します。
  5. ユニフォームの設定: シェーダーに必要なユニフォーム値を渡します。
  6. バッファのバインド: 描画に使用するバッファを有効にします。
  7. 描画: drawArrays() または drawElements() を呼び出してモデルをレンダリングします。

以下に、これらすべてを含めたより完全な例を示します:

// 頂点シェーダー
const vsSource = `
attribute vec4 a_position;
void main() {
gl_Position = a_position;
}
`;

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

// シェーダーをコンパイルする関数
function compileShader(gl, source, type) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
}

// プログラムを作成する関数
function createProgram(gl, vertexShader, fragmentShader) {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
return program;
}

// メインの描画関数
function drawModel(gl) {
// シェーダーをコンパイル
const vertexShader = compileShader(gl, vsSource, gl.VERTEX_SHADER);
const fragmentShader = compileShader(gl, fsSource, gl.FRAGMENT_SHADER);

// プログラムを作成
const program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);

// バッファとデータの設定(前の例に従ってください)
// ...

// 属性ポインタの設定
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);

// 描画
gl.drawArrays(gl.TRIANGLES, 0, 3);  // または gl.drawElements() でインデックス付き幾何学形状
}

この例では、シェーダーをコンパイルし、プログラムを作成し、バッファと属性ポインタを設定し、最後にモデルを描画します。

結論

おめでとうございます!あなたは刚刚、WebGLの素晴らしい世界への第一歩を踏み出しました。新しいスキルを習得するには、練習と忍耐が必要です。初めての試みで完璧にいくまいことを忘れないでください。最も経験豊かなグラフィックスプログラマーでさえ、時々不经意にピンクの立方体を描いてしまったりします!

実験を続け、学び続け、そして何より楽しみましょう。それを続けることで、 browserの中で素晴らしい3D世界を創造できるようになるでしょう。未来の3Dアーティストとして、お楽しみに!

Credits: Image by storyset