2021年01月09日 - WebVR・Three.js
WebGLで四角形ポリゴンをアニメーション

「WebGLで三角形ポリゴンを表示」に続き「インデックスバッファによる描画-wgld.org」を参考に、WebGLで四角形ポリゴンをアニメーションさせました。
WebGLで四角形ポリゴンをアニメーション
四角形ポリゴンはインデックスを設定して生成し、インデックスを設定した場合は、gl.drawArraysではなくgl.drawElementsを使用して描画します。生成した四角形ポリゴンをアニメーションさせるには、行列を使用します。行列の演算はライブラリを使用するため、数学的な計算をする必要はありません。
● 行列演算用ライブラリ
「行列演算とライブラリ-wgld.org」を参考に行列演算用ライブラリを読み込みます。
<script src="js/lib/minMatrix.js"></script> <script src="js/script.js" type="module"></script>
● script.js
//===============================================================
// GLSL
//===============================================================
const vertexShader =`
attribute vec3 position;
attribute vec4 color;
uniform mat4 mvpMatrix;
varying vec4 vColor;
void main(void){
vColor = color;
gl_Position = mvpMatrix * vec4(position,1.0);
}
`;
const fragmentShader =`
precision mediump float;
varying vec4 vColor;
void main(void){
gl_FragColor = vColor;
}
`;
//===============================================================
// Init & Redering
//===============================================================
window.addEventListener('load',function(){
init();
rendering();
});
let canvas,gl;
let m,mMatrix,vMatrix,pMatrix,vpMatrix,mvpMatrix;
let uniLocation;
let count = 0;
let index;
function init(){
canvas = document.getElementById('webgl-canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
gl = canvas.getContext('webgl');
const vShader = createShader(gl.VERTEX_SHADER,vertexShader);
const fShader = createShader(gl.FRAGMENT_SHADER,fragmentShader);
const prg = createProgram(vShader,fShader);
let attLocation = [];
attLocation[0] = gl.getAttribLocation(prg,'position');
attLocation[1] = gl.getAttribLocation(prg,'color');
let attStride = [];
attStride[0] = 3;
attStride[1] = 4;
//頂点座標の設定
const vertexPositions = [
0.0,1.0,0.0,
1.0,0.0,0.0,
-1.0,0.0,0.0,
0.0,-1.0,0.0
];
//頂点色の設定
const vertexColors = [
1.0,0.0,0.0,1.0,
0.0,1.0,0.0,1.0,
0.0,0.0,1.0,1.0,
1.0,1.0,0.0,1.0
];
//インデックスの設定
index = [
0,1,2,
1,2,3
];
//VBOの生成
const positionVbo = createVbo(vertexPositions);
const colorVbo = createVbo(vertexColors);
//VBOの登録
setAttribute([positionVbo,colorVbo],attLocation,attStride);
//IBO(インデックスバッファオブジェクト)の生成
const ibo = createIbo(index);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,ibo);
uniLocation = gl.getUniformLocation(prg,'mvpMatrix');
m = new matIV();
mMatrix = m.identity(m.create());
vMatrix = m.identity(m.create());
pMatrix = m.identity(m.create());
vpMatrix = m.identity(m.create());
mvpMatrix = m.identity(m.create());
m.lookAt([0.0,0.0,4.0],[0,0,0],[0,1,0],vMatrix);
m.perspective(90,canvas.width/canvas.height,0.1,100,pMatrix);
m.multiply(pMatrix,vMatrix,vpMatrix);
}
//アニメーション
function rendering(){
//画面の初期化
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clearDepth(1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//ラジアンを算出
count ++;
const rad = (count % 360) * Math.PI / 180;
//モデル座標変換
m.identity(mMatrix);
//回転アニメーション
m.rotate(mMatrix,rad,[0,1,0],mMatrix);
//各行列を掛け合わせる
m.multiply(vpMatrix,mMatrix,mvpMatrix);
gl.uniformMatrix4fv(uniLocation,false,mvpMatrix);
gl.drawElements(gl.TRIANGLES,index.length,gl.UNSIGNED_SHORT,0);
//コンテキストの再描画
gl.flush();
requestAnimationFrame(rendering);
}
//===============================================================
// Function
//===============================================================
function createShader(shaderType,shaderText){
const shader = gl.createShader(shaderType);
gl.shaderSource(shader,shaderText);
gl.compileShader(shader);
return shader;
}
function createProgram(vs,fs){
const program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
gl.useProgram(program);
return program;
}
function createVbo(data){
const vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vbo);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(data),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER,null);
return vbo;
}
//IBOを生成
function createIbo(data){
const ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,ibo);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,new Int16Array(data),gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,null);
return ibo;
}
//VBOのバインド、登録
function setAttribute(vbo,attL,attS){
for(let i in vbo){
gl.bindBuffer(gl.ARRAY_BUFFER,vbo[i]);
gl.enableVertexAttribArray(attL[i]);
gl.vertexAttribPointer(attL[i],attS[i],gl.FLOAT,false,0,0);
}
}
完成したデモになります。WebGLで四角形ポリゴンをアニメーションさせました。

