Lesson07 – 頂点シェーダー その1

前回までのLessonではシェーダーの中身をできるだけ見ないようにしてきましたが、いよいよその中身を見る時がやってきました。

まずは、前回のサンプルで用いた頂点シェーダー関係の部分を抜き出してみます。

// 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;
}

シェーダーはコンパイル&リンクして使うということは以前説明しましたが、今回の注目はそのソースコードの中身です。shaderSourceに渡している文字列がそれになります。

ただ、このままでは少し見づらいと思いますので適当に改行したソースコードを次に再掲します。

attribute vec3 pos;

void main(void)
{
  gl_Position = vec4(pos, 1.0);
}

頂点シェーダーは頂点毎に計算されます。

何となく想像できるかもしれませんがposという変数で頂点座標が与えられています。関係している部分はinitShaderdrawSceneです。

initShader

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

drawScene

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

initShaderでは頂点シェーダーのposとJavaScriptのposVAttribの関係を設定しています。そして、drawSceneで頂点座標をposVAttribに渡しています。

こう書くと何か分かったような、分からないような気分になってきます。そこで、1つサンプルとして前回紹介した平行移動のサンプルを頂点シェーダーのソースコードを修正して実現してみたいと思います。

平行移動の場合、結局のところ0.5足せば良いのですから、次のように書き変えれば実現できそうな気がします。

attribute vec3 pos;

void main(void)
{
  gl_Position = vec4(0.5, 0.5, 0.5, 0) + vec4(pos, 1.0);
}

不要かもしれませんが、念のために全ソースコードを掲載しておきます。これを修正して、x軸方向にのみ平行移動した図やy軸方向にのみ平行移動した図を描く練習をしてみるのも面白いと思います。

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(0.5, 0.5, 0.5, 0) + 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]);
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
  gl.vertexAttribPointer(posVAttrib, 3, gl.FLOAT, false, 0, 0);

  gl.drawArrays(gl.TRIANGLES, 0, 3);
  gl.flush();
}
サンプルを確認する場合はこちらをクリックしてください。
右上の方向に平行移動した三角形が表示されます。

更に、もう1つサンプルを追加したいと思います。上のようにvec4で足しても今回の平行移動は実現できますが、後々のことを考えて、Lesson05で紹介した平行移動行列を使ってみようと思います。

頂点シェーダーの部分のみ抜き出てみますと、次のようにできます。(見やすいように改行していますが、実際に試す場合は改行を削除してください。)

attribute vec3 pos;

void main(void)
{
  mat4 m = mat4(1,0,0,0, 0,1,0,0, 0,0,1,0, 0.5,0.5,0.5,1);
  gl_Position = m * vec4(pos, 1.0);
}
サンプルを確認する場合はこちらをクリックしてください。
右上の方向に平行移動した三角形が表示されます。

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

コメントを残す

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