見出し画像

十三、サイズの異なる複数の点を描画する。

■サンプルページはコチラ↓

■このプログラムの解説は、次のExcelファイルをご覧下さい。


■htmlのコードです。↓

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <title>サイズの異なる複数の点を描画する</title>
  </head>

  <body onload="main()">
    <canvas id="webgl" width="400" height="400">

    </canvas>

    <script src="webgl-utils.js"></script>
    <script src="webgl-debug.js"></script>
    <script src="sano-func.js"></script>

    <script src="dot-7-size.js"></script>
  </body>
</html>


■JavaScriptのコードです。↓


// 頂点シェーダのプログラム
var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'attribute float a_PointSize;\n' +
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +
  '  gl_PointSize = a_PointSize;\n' +
  '}\n';

// フラグメントシェーダのプログラム
var FSHADER_SOURCE =
  'void main() {\n' +
  '  gl_FragColor = vec4(0.957, 0.957, 0.973, 1.0);\n' +
  '}\n';

function main() {
  // Canvas要素を取得する
  var canvas = document.getElementById('webgl');

  // WebGL描画用のコンテキストを取得する
  var gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('WebGLコンテキストの取得に失敗');
    return;
  }

  // シェーダを初期化する
  if (!initShaders2(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('シェーダの初期化に失敗');
    return;
  }

  // 頂点座標を設定する
  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('頂点座標の設定に失敗');
    return;
  }

  // Canvasをクリアする色を設定する
  gl.clearColor(0.02, 0.043, 0.173, 1);

  // Canvasをクリアする
  gl.clear(gl.COLOR_BUFFER_BIT);

  // 3点描画する
  gl.drawArrays(gl.POINTS, 0, n);
}

function initVertexBuffers(gl) {
  var vertices = new Float32Array([
-0.50, 0.00, -0.42, 0.17, -0.13, 0.13, -0.12, -0.06, 0.08, -0.18, 0.23, -0.28, 0.50, -0.28
  ]);
  var n = 7; // 頂点数


  var sizes = new Float32Array([
    5.03, 3.85, 3.73, 2.71, 5.11, 4.41, 4.84  // 点のサイズ
  ]);

  // バッファオブジェクトを作成する
  var vertexBuffer = gl.createBuffer();  
  var sizeBuffer = gl.createBuffer();
  if (!vertexBuffer || !sizeBuffer) {
    console.log('バッファオブジェクトの生成に失敗');
    return -1;
  }

  // 頂点の座標をバッファオブジェクトに書き込み、有効化する
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
    if(a_Position < 0) {
    console.log('a_Positionの格納場所の取得に失敗');
    return -1;
  }
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(a_Position);

  // 点のサイズをバッファオブジェクトに書き込み、有効化する
  gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW);
  var a_PointSize = gl.getAttribLocation(gl.program, 'a_PointSize');
  if(a_PointSize < 0) {
    console.log('a_PointSizeの格納場所の取得に失敗');
    return -1;
  }
  gl.vertexAttribPointer(a_PointSize, 1, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(a_PointSize);

  // バッファオブジェクトのバインドを解除する
  gl.bindBuffer(gl.ARRAY_BUFFER, null);

  return n;
}

■参考文献:WebGL+HTML5 3DCGプログラミング入門 (良い本ですが、絶版)

■以下は私が検索する時に使うヤツです。
星の色。

50行目あたり。自作関数。

夜空の色。

座標データの、0番目を最初として、n個のデータを参照して、点を描く。

Float32Array は”型付き配列”。 JavaScriptの配列は文字列が使えたりするが、明らかに実数型のデータしか使わない部分には、型を指定した配列を使った方が処理が速くなるらしい。
北斗七星の座標データ。”六”の時は向きを間違えていました。

【重要】バッファオブジェクトは、WebGLにおいて、グラフィックスのデータ(例えば、頂点の座標や色、法線など)を一時的に保存するための領域です。

vertexBufferの中身が負 (使えるデータが無い) の場合、-1を返す。

vertexBufferという頂点バッファオブジェクトを現在のバッファとしてバインドすることを意味します。

gl.ARRAY_BUFFERに、verticesの情報を書き込む。

a_Positionの中身が負 (使えるデータが無い) の場合、-1を返す。

”五”などに出て来た、gl.vertexAttrib [1234] f () では、1つ(または1組)のデータしか、attribute変数に代入できない。
今回はいっぱい点があるので、gl.vertexAttribPointer を使っている。
gl.vertexAttribPointer(attribute変数の格納場所, サイズ(1~4。3次元なら3など), データの形式, 正規化するかどうか(通常はしない), データの間隔, 何番目のデータから読み込むか(通常は0番目));
gl.vertexAttribPointerの第3引数は以下のとおり。
gl.UNSIGNED_BYTE → Unit8Array用 → 符号なしバイト
gl.SHORT → Int16Array用 → 符号付単精度整数
gl.UNSIGNED_SHORT → Uint16Array用 → 符号なし単精度整数
gl.INT → Int32Array用 → 符号付整数
gl.UNSIGNED_INI → Uint32Array → 符号なし整数 (インデックスなどに使われる)
gl.FLOAT → Float32Array用 → 浮動小数点数

これはやらなくてもいいらしい。
バッファをバインドしたままだとかわいそうなので、解放してあげる的な。

gl.vertexAttribPointer()は、attribute変数にバッファオブジェクトを割り当てますが、”有効”にしないと使えない。
なので、gl.enableVertexAttribArray()で”有効”にする。

以上です。


頂戴したサポートは、レンタルサーバーの費用に充てさせて頂きます🙇 心より感謝いたします❤️