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