WebGL行列パレットスキニング(ウェイトなし) - jsdo.it - share JavaScript, HTML5 and CSS

頂点ごとに行列のインデクスを1つ持っておいて、100%のウェイトで座標変換する方式。とりあえず行列は2つまで。

実装

頂点シェーダー内で

uniform mat4 uMMatrix[2];  // モデル行列配列

とボーン用の行列の配列を用意して、js側でシェーダーの初期化時に

shaderProgram.uMMatrix = [
  gl.getUniformLocation(shaderProgram, 'uMMatrix[0]'),
  gl.getUniformLocation(shaderProgram, 'uMMatrix[1]')
];

と取得しておく。

頂点ごとのアトリビュートとして行列インデクスを定義

attribute float aBlendIndices;

する。js側からは

shaderProgram.aBlendIndices = gl.getAttribLocation(shaderProgram, 'aBlendIndices');
gl.enableVertexAttribArray(shaderProgram.aBlendIndices);

としてアトリビュートを取得しておく。 モデルの頂点バッファとして行列インデクスを

var blendIndicesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, blendIndicesBuffer);
var blendIndices = [
  ...
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(blendIndices), gl.STATIC_DRAW);
blendIndicesBuffer.itemSize = 1;
blendIndicesBuffer.numItems = blendIndices.length / blendIndicesBuffer.itemSize;

などとして作成する。

描画時は行列を計算して

for (var i = 0; i < 2; ++i) {
  mat4.multiply(modelMatrices[i], model.basePose[i]);
  gl.uniformMatrix4fv(shaderProgram.uMMatrix[i], false, modelMatrices[i]);
}

としてシェーダーに渡す。

頂点シェーダーでブレンドインデクスと行列パレットから頂点座標を計算:

gl_Position = uVPMatrix * uMMatrix[int(aBlendIndices)] * vec4(aVertexPosition, 1.0);

int() でキャストしないと配列アクセスでエラーが出る。

課題

  • 行列の配列を渡す方法
  • ブレンドウェイト
  • 3x4行列またはクォータニオンを使う