Lesson06 – 座標変換

前回作ったライブラリを使って実際に座標変換をしてみたいと思います。

まず、座標変換ライブライを読み込む必要がありますので、HTMLの<head></head>を次のように書き変えてください。

<head>
  <title>WebGL sample06-1</title>
  <script type="text/javascript" src="mat.js" ></script>
  <script type="text/javascript">
    // ここに必要な実装を追加していきます。
  </script>
</head>

※これ以降のLessonでも同様にmat.jsを読み込んでおいてください。(mat.jsはLesson05の本文からコピーするか、こちらからダウンロードできます。)

それではWebGL部分の実装に進みたいと思います。

var gl;
var posVAttrib;

function start()
{
  var canvas = document.getElementById('canvas');

  initGL(canvas);
  if(gl){
    initShader();

    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    drawScene();
  }
}

function initGL(canvas){
  gl = null;

  try{
    gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  }
  catch(e){
  }

  if(!gl){
    alert('Unable to Initialize WebGL.');
  }
}

function initShader()
{
  // Vertex shader
  var vshader = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vshader, 'attribute vec3 pos; void main(void){ gl_Position = vec4(pos, 1.0); }');
  gl.compileShader(vshader);
  if(!gl.getShaderParameter(vshader, gl.COMPILE_STATUS)){
    alert(gl.getShaderInfoLog(vshader));
    return;
  }

  // Fragment shader
  var fshader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fshader, 'void main(void){ gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); }');
  gl.compileShader(fshader);
  if(!gl.getShaderParameter(fshader, gl.COMPILE_STATUS)){
    alert(gl.getShaderInfoLog(fshader));
    return;
  }

  // Create shader program
  var program = gl.createProgram();
  gl.attachShader(program, fshader);
  gl.attachShader(program, vshader);
  gl.linkProgram(program);
  if(!gl.getProgramParameter(program, gl.LINK_STATUS)){
    alert(gl.getProgramInfoLog(program));
    return;
  }
  gl.useProgram(program);

  // attribute
  posVAttrib = gl.getAttribLocation(program, 'pos');
  gl.enableVertexAttribArray(posVAttrib);
}

function drawScene(){
  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

  var vertices = new Float32Array([0.0, 0.8, 0.0, -0.8, -0.8, 0.0, 0.8, -0.8, 0.0]);

  for(var vec4,i=0; i<3; ++i){
    vec4 = vec4_create(vertices.subarray(i*3, i*3+3));
    vec4_translate(vec4, 0.5, 0.5, 0.5);
    vertices.set(vec4.subarray(0, 3), i*3);
  }

  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
  gl.vertexAttribPointer(posVAttrib, 3, gl.FLOAT, false, 0, 0);

  gl.drawArrays(gl.TRIANGLES, 0, 3);
  gl.flush();
}

今回、修正した部分はdrawSceneの中だけです。まずは前回と同じ三角形の頂点[0.0, 0.8, 0.0, -0.8, -0.8, 0.0, 0.8, -0.8, 0.0]を用意し、それを3つずつに分け、前回作成した関数を適用していきます。

上のサンプルでは平行移動vec4_translateを使ってx軸方向、y軸方向、z軸方向にそれぞれ0.5ずつ平行移動した頂点の座標を計算しています。

サンプルを確認する場合はこちらをクリックしてください。
右上の方向に平行移動した三角形が表示されます。

せっかくですので、もう1つ回転のサンプルも試してみようと思います。

var gl;
var posVAttrib;

function start()
{
  var canvas = document.getElementById('canvas');

  initGL(canvas);
  if(gl){
    initShader();

    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    drawScene();
  }
}

function initGL(canvas){
  gl = null;

  try{
    gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
  }
  catch(e){
  }

  if(!gl){
    alert('Unable to Initialize WebGL.');
  }
}

function initShader()
{
  // Vertex shader
  var vshader = gl.createShader(gl.VERTEX_SHADER);
  gl.shaderSource(vshader, 'attribute vec3 pos; void main(void){ gl_Position = vec4(pos, 1.0); }');
  gl.compileShader(vshader);
  if(!gl.getShaderParameter(vshader, gl.COMPILE_STATUS)){
    alert(gl.getShaderInfoLog(vshader));
    return;
  }

  // Fragment shader
  var fshader = gl.createShader(gl.FRAGMENT_SHADER);
  gl.shaderSource(fshader, 'void main(void){ gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); }');
  gl.compileShader(fshader);
  if(!gl.getShaderParameter(fshader, gl.COMPILE_STATUS)){
    alert(gl.getShaderInfoLog(fshader));
    return;
  }

  // Create shader program
  var program = gl.createProgram();
  gl.attachShader(program, fshader);
  gl.attachShader(program, vshader);
  gl.linkProgram(program);
  if(!gl.getProgramParameter(program, gl.LINK_STATUS)){
    alert(gl.getProgramInfoLog(program));
    return;
  }
  gl.useProgram(program);

  // attribute
  posVAttrib = gl.getAttribLocation(program, 'pos');
  gl.enableVertexAttribArray(posVAttrib);
}

function drawScene(){
  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

  var vertices = new Float32Array([0.0, 0.8, 0.0, -0.8, -0.8, 0.0, 0.8, -0.8, 0.0]);

  for(var vec4,i=0; i<3; ++i){
    vec4 = vec4_create(vertices.subarray(i*3, i*3+3));
    vec4_rotate_z(vec4, 30 * Math.PI / 180);
    vertices.set(vec4.subarray(0, 3), i*3);
  }

  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
  gl.vertexAttribPointer(posVAttrib, 3, gl.FLOAT, false, 0, 0);

  gl.drawArrays(gl.TRIANGLES, 0, 3);
  gl.flush();
}

vec4_translatevec4_rotate_zに置きかえてz軸を中心に回転させた頂点の座標を計算しています。

サンプルを確認する場合はこちらをクリックしてください。
30°回転した三角形が表示されます。

前回の記事
次回の記事
目次ページ

コメントを残す

メールアドレスが公開されることはありません。