2013年6月27日木曜日

座標変換とシェーダ

追加のライブラリ

glm:OpenGL用の行列演算を行うヘッダライブラリ

追加のヘッダファイル

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

行列の変数とシェーダでのメモリ位置

シェーダソースコード内の変数の位置を指定する

  //利用するシェーダを登録
  glAttachShader(shader_id_, vertex_shader_id_);
  glAttachShader(shader_id_, fragment_shader_id_);
  .
  .
  .
  //シェーダの入力変数のメモリ位置を指定
  glBindAttribLocation(shader_id_, 0, "vertex");
  .
  .
  .
  
  //各シェーダの接続
  glLinkProgram(shader_id_);

座標変換に必要な行列の準備とシェーダでのメモリ位置を取得する

  glm::mat4 projection_matrix_;
  glm::mat4 view_matrix_;
  glm::mat4 model_matrix_;
  int projection_location_;
  int view_location_;
  int model_location_;

  //透視投影変換行列を計算
  projection_matrix_ = glm::perspective(
      60.0f,
      static_cast<GLfloat>(800)/static_cast<GLfloat>(600),
      1.0f,
      100.0f);
  //ビュー行列を計算
  view_matrix_ = 
  glm::lookAt( glm::vec3(0.0f, 0.0f, -5.0f), glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
  //glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f));
  //モデル行列を計算
  model_matrix_= glm::scale(glm::mat4(1.0f), glm::vec3(0.5f));

  //シェーダ変数と関連付けるために
  //シェーダ変数のメモリ位置を取得する
  projection_location_ = glGetUniformLocation(shader_->shader_id(), "projection_matrix");
  view_location_       = glGetUniformLocation(shader_->shader_id(), "view_matrix");
  model_location_      = glGetUniformLocation(shader_->shader_id(), "model_matrix");

描画処理

  //画面のクリア
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  //シェーダ開始
  shader_->Begin();

  //ビュー行列の回転
  view_matrix_ = glm::rotate(view_matrix_, 0.1f, glm::vec3(0.f, 1.f, 0.f));
  //シェーダへデータを送る
  glUniformMatrix4fv(projection_location_, 1, GL_FALSE, &projection_matrix_[0][0]);
  glUniformMatrix4fv(view_location_      , 1, GL_FALSE, &view_matrix_[0][0]);
  glUniformMatrix4fv(model_location_     , 1, GL_FALSE, &model_matrix_[0][0]);

  //図形の描画
  triangle_->Draw();

  //シェーダ終了
  shader_->End();

  //画面を表示
  SDL_GL_SwapWindow(window_);

シェーダ

shader.vs

#version 150
in vec4 vertex;
out vec3 pass_color;
uniform mat4 projection_matrix;
uniform mat4 view_matrix;
uniform mat4 model_matrix;

void main(void) {
  gl_Position = projection_matrix * view_matrix * model_matrix * vertex;
  pass_color = vec3(1.0f);
}

shader.ps

#version 150
in vec3 pass_color;
out vec4 out_color;
void main(void) {
  out_color = vec4(pass_color, 1.0);
}

最初にglBindAttribLocation(shader_id_, 0, "vertex")で シェーダプログラム内の変数vertexの位置を0に指定します。
この位置はglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr)の第一引数と 連動します。

次にglmの関数を用いて座標変換行列を生成しています。(ここでは詳細を割愛)
そして、glGetUniformLocation(shader_->shader_id(), "projection_matrix")で、 shader.vs内のprojection_matrix変数の位置を取得します。
この位置を利用して、描画ごとに glUniformMatrix4fv(projection_location_, 1, GL_FALSE, &projection_matrix_[0][0]) とすることで、行列をシェーダへ転送します。

シェーダプログラムの一行目#versioin 150は、 GLSLのバージョン1.50を利用する宣言です。
これを宣言しない場合には1.10が利用されるようです。
二行目のin vec4 vertexinvertexが入力変数であることを示しています。
三行目で指定しているoutは次のシェーダへ渡される変数であることを示します。
また、uniformは、外部から渡される定数であることを示し、 値はglUniformMatrix4fvで指定しています。

0 件のコメント:

コメントを投稿