X
2021年01月09日 - WebVR・Three.js

WebGLで四角形ポリゴンをアニメーション

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で四角形ポリゴンをアニメーションさせました。

  • このエントリーをはてなブックマークに追加

関連記事

スポンサーリンク

前の記事へ

WebGLで三角形ポリゴンを表示

次の記事へ

WebGLでポイントライト