回転行列を使ってアフィン変換を行います。
前回と変わっていないところは折りたたんでいますがコピペをすると展開されて張り付くので注意してください。
<!DOCTYPE html> <html> <head> <title>四角形描画</title> <style> </style> </head> <body> <!-- HTML5のキャンバス作成 --> <canvas id="MyCanvas" width="400" height="400"></canvas><!-- シェーダはGLSL (OpenGL Shading Language) で書く。つまり、ここはHTMLでもJavaScriptでもない --> <!-- scriptタグのid「vshader」を識別子として、コンパイル時にgetElementByIDを使って文字列としてこのシェーダプログラムを参照する --> <!-- ************************************** --> <!-- ** 頂点シェーダ*********************** --> <!-- ************************************** --> <script id="vshader" type="x-shader/x-vertex"> attribute vec3 position;//描画時にgetAttribLocationでアクセスするのでわかりやすい名前にしておくことが望ましい attribute vec3 color;//同上 uniform mat4 rot_matrix; varying lowp vec3 vColor; void main(void){ gl_Position = rot_matrix * vec4(position, 1.0); vColor = color; } </script><!-- ここもGLSLで書く。 --> <!-- 上と同様、コンパイル時にscriptタグのid「fshader」で参照する --> <!-- ************************************** --> <!-- ** フラグメントシェーダ*************** --> <!-- ************************************** --> <script id="fshader" type="x-shader/x-fragment"> precision mediump float;//これがないとコンパイルエラーになる varying lowp vec3 vColor; void main(void){ gl_FragColor = vec4(vColor, 1.0); } </script><!-- シェーダのコンパイル。ここはJavaScriptで書く --> <!-- ************************************** --> <!-- ** シェーダコンパイルとリンク********* --> <!-- ************************************** --> <script> var programID;// グローバル変数としてプログラム名の格納先を定義する function prepare_shaders(gl){ /////////////////////////////// /////////////////////////////// // 頂点シェーダコンパイル var vs = document.getElementById ("vshader"); var vertexShader = gl.createShader (gl.VERTEX_SHADER); gl.shaderSource (vertexShader, vs.text);//シェーダのプログラムをテキストで取得 gl.compileShader (vertexShader); if ( !gl.getShaderParameter (vertexShader, gl.COMPILE_STATUS) ){ throw new Error (gl.getShaderInfoLog(vertexShader)); } /////////////////////////////// /////////////////////////////// // フラグメントシェーダコンパイル var fs = document.getElementById ("fshader"); var fragmentShader = gl.createShader (gl.FRAGMENT_SHADER); gl.shaderSource (fragmentShader, fs.text);//シェーダのプログラムをテキストで取得 gl.compileShader (fragmentShader); if ( !gl.getShaderParameter (fragmentShader, gl.COMPILE_STATUS) ){ throw new Error (gl.getShaderInfoLog(fragmentShader)); } /////////////////////////////// /////////////////////////////// // プログラムのリンク programID = gl.createProgram (); gl.attachShader (programID, vertexShader); gl.attachShader (programID, fragmentShader); gl.linkProgram (programID); if ( !gl.getProgramParameter(programID, gl.LINK_STATUS) ) { throw new Error (gl.getProgramInfoLog(programID)); } } </script><!-- データの準備。ここもJavaScriptで書く --> <!-- ************************************** --> <!-- ** 三角形の準備********* --> <!-- ************************************** --> <!-- ************************************** --> <script> //各変数をグローバル変数として定義 var vertexesVboID; var colorsVboID; function prepare_data(gl){ //頂点バッファ作成 var vertexes = [ -0.7, 0.7, 0.0, 0.7, 0.7, 0.0, -0.7, -0.7, 0.0, 0.7, -0.7, 0.0 ]; vertexesVboID = gl.createBuffer (); gl.bindBuffer (gl.ARRAY_BUFFER, vertexesVboID); gl.bufferData (gl.ARRAY_BUFFER, new Float32Array (vertexes), gl.STATIC_DRAW); //カラーバッファ作成 var colors = [ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 ]; colorsVboID = gl.createBuffer (); gl.bindBuffer (gl.ARRAY_BUFFER, colorsVboID); gl.bufferData (gl.ARRAY_BUFFER, new Float32Array (colors), gl.STATIC_DRAW); } </script><!-- ************************************** --> <!-- ** アフィン変換行列を作る関数 ******** --> <!-- ************************************** --> <script> function rotate_z16(rad){ var m = new Float32Array(16); m[ 0] = Math.cos(rad); m[ 1] = -Math.sin(rad); m[ 2] = 0;m[ 3] = 0; m[ 4] = Math.sin(rad); m[ 5] = Math.cos(rad); m[ 6] = 0; m[ 7] = 0; m[ 8] = 0; m[ 9] = 0; m[10] = 1; m[11] = 0; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; return m; } </script><!-- やっと描画部分 --> <!-- ここもJavaScriptで書く --> <!-- ////////////////////////////////////// --> <!-- // 初回のみ実行 ////////////////////// --> <!-- ////////////////////////////////////// --> <!-- ////////////////////////////////////// --> <script> // 初回表示時に呼び出される window.onload = function(){ var mycanv = document.getElementById("MyCanvas"); // GLコンテキストを取得 var gl = mycanv.getContext('webgl') || mycanv.getContext('experimental-webgl'); // 画面を黒でクリア gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); prepare_shaders(gl);//シェーダの準備 prepare_data(gl);//描画データの準備 gl.useProgram(programID);//行列の設定 (ここを追加) var rotmat = rotate_z16(0.4); var rotation_location = gl.getUniformLocation(programID, 'rot_matrix'); gl.uniformMatrix4fv(rotation_location, false, rotmat);//バッファへアクセス var vertex_location = gl.getAttribLocation (programID, 'position'); var color_location = gl.getAttribLocation (programID, 'color'); //頂点バッファを有効にする gl.enableVertexAttribArray (vertex_location); gl.bindBuffer (gl.ARRAY_BUFFER, vertexesVboID); gl.vertexAttribPointer (vertex_location, 3, gl.FLOAT,false, 0, 0); //カラーバッファを有効にする gl.enableVertexAttribArray (color_location); gl.bindBuffer (gl.ARRAY_BUFFER, colorsVboID); gl.vertexAttribPointer (color_location, 3, gl.FLOAT,false, 0, 0); //四角形を描く gl.drawArrays (gl.TRIANGLE_STRIP, 0, 4); //バッファを無効にする gl.disableVertexAttribArray(vertex_location); gl.disableVertexAttribArray(color_location); gl.flush (); } </script></body> </html>
OpenGL知っている所からWebGL入門(1) – 画面クリア
OpenGL知っている所からWebGL入門(2) – 図形描画
OpenGL知っている所からWebGL入門(3) – 図形を回転