bambooflow Note

VAOを使ったレンダリング

最終更新:

bambooflow

- view
メンバー限定 登録/ログイン

VAOを使ったレンダリング


Vertex Array Objects(VAO)は、VBOとAttribute設定を包括するものとしてとらえることができます。
OpenGL ES 2.0では、VAOの使用が推奨されています。

今回のサンプルは、VBOのみを使ったCube描画を改変したものです。





環境
  • OpenGL 3.2
  • GLUT(freeglut) 2.6.0
  • GLEW 1.5.7
  • GLM 0.9.0.6

VAOを使う



void glGenVertexArrays(GLsizei n, GLuint *arrays);

void glDeleteVertexArrays(GLsizei n, const GLuint *arrays);

void glBindVertexArray(GLuint array);

VAOでは、次のステートを保持することができます。
  • glVertexAttribPointer
  • glEnableVertexAttribArray

なので、glDrawArraysもしくはglDrawElementsによるレンダー時、glBindVertexArrayを呼ぶだけで済むのでクライアント<->GPU間のやりとりが減り高速描画が期待できます。

プログラム


VAOを使うことで、glDrawElementsを使うときの設定がシンプルになります。
VBOのみを使っていたCube描画に比べて、Cubeクラスのrender()関数の中が記述が簡単になっていることを確認してください。


#include <cstdlib>
#include <iostream>
 
#include "load_shader.h"
 
#include <GL/glew.h>
#include <GL/glut.h>
 
// OpenGL Mathematics Library
#include <glm/glm.hpp>
#include <glm/gtc/matrix_projection.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform2.hpp>
#include <glm/gtc/type_ptr.hpp>
 
 
void reshape(int w, int h);
void init();
void timer(int t );
void display();
 
 
struct ShaderContext {
  GLuint programObject;
 
  GLint modelMatrixLocation;
  GLint viewMatrixLocation;
  GLint projectionMatrixLocation;
 
  GLint positionLocation;
  GLint normalLocation;
};
 
 
class Cube
{
private:
  struct Vertex_t {
    GLfloat position[3];       // (vx,vy,vz)
    GLfloat normal[3];         // (nx,ny,nz)
  };
  GLuint vao[1];               // Vertex array buffer objects
  GLuint eao[1];               // array buffer objects for elements
  GLint  positionLocation;
  GLint  normalLocation;
  GLuint numIndecies;
 
  glm::mat4 modelMat;
  glm::vec3 position;
  glm::vec3 size;
  glm::vec3 angle_axis;
  float angle;
 
public:
  void setup(const ShaderContext *context)
  {
    GLuint offset;
    GLuint vbo[1];
    Vertex_t vertex[] = { // position(x,y,z) , normal(x,y,z)
      { { -0.5f, -0.5f, -0.5f }, { +0.0f, -1.0f, +0.0f } },
      { { -0.5f, -0.5f, +0.5f }, { +0.0f, -1.0f, +0.0f } },
      { { +0.5f, -0.5f, +0.5f }, { +0.0f, -1.0f, +0.0f } },
      { { +0.5f, -0.5f, -0.5f }, { +0.0f, -1.0f, +0.0f } },
      { { -0.5f, +0.5f, -0.5f }, { +0.0f, +1.0f, +0.0f } },
      { { -0.5f, +0.5f, +0.5f }, { +0.0f, +1.0f, +0.0f } },
      { { +0.5f, +0.5f, +0.5f }, { +0.0f, +1.0f, +0.0f } },
      { { +0.5f, +0.5f, -0.5f }, { +0.0f, +1.0f, +0.0f } },
      { { -0.5f, -0.5f, -0.5f }, { +0.0f, +0.0f, -1.0f } },
      { { -0.5f, +0.5f, -0.5f }, { +0.0f, +0.0f, -1.0f } },
      { { +0.5f, +0.5f, -0.5f }, { +0.0f, +0.0f, -1.0f } },
      { { +0.5f, -0.5f, -0.5f }, { +0.0f, +0.0f, -1.0f } },
      { { -0.5f, -0.5f, +0.5f }, { +0.0f, +0.0f, +1.0f } },
      { { -0.5f, +0.5f, +0.5f }, { +0.0f, +0.0f, +1.0f } },
      { { +0.5f, +0.5f, +0.5f }, { +0.0f, +0.0f, +1.0f } },
      { { +0.5f, -0.5f, +0.5f }, { +0.0f, +0.0f, +1.0f } },
      { { -0.5f, -0.5f, -0.5f }, { -1.0f, +0.0f, +0.0f } },
      { { -0.5f, -0.5f, +0.5f }, { -1.0f, +0.0f, +0.0f } },
      { { -0.5f, +0.5f, +0.5f }, { -1.0f, +0.0f, +0.0f } },
      { { -0.5f, +0.5f, -0.5f }, { -1.0f, +0.0f, +0.0f } },
      { { +0.5f, -0.5f, -0.5f }, { +1.0f, +0.0f, +0.0f } },
      { { +0.5f, -0.5f, +0.5f }, { +1.0f, +0.0f, +0.0f } },
      { { +0.5f, +0.5f, +0.5f }, { +1.0f, +0.0f, +0.0f } },
      { { +0.5f, +0.5f, -0.5f }, { +1.0f, +0.0f, +0.0f } }
    };
    GLuint indices[] = {
      0, 2, 1,
      0, 3, 2,
      4, 5, 6,
      4, 6, 7,
      8, 9, 10,
      8, 10, 11,
      12, 15, 14,
      12, 14, 13,
      16, 17, 18,
      16, 18, 19,
      20, 23, 22,
      20, 22, 21
    };
    numIndecies = sizeof(indices)/sizeof(GLuint);
 
    // Create VBO
    glGenBuffers(1, vbo);
 
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);
 
    // Create and bind VAO
    glGenVertexArrays(1, vao);
    glBindVertexArray(vao[0]);
    {
 
      offset = 0;
      glVertexAttribPointer(context->positionLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex_t), (const void*)offset); 
      offset += 3 * sizeof(GLfloat);
      glVertexAttribPointer(context->normalLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex_t), (const void*)offset); 
 
      // Enable Attribute
      glEnableVertexAttribArray(context->positionLocation);
      glEnableVertexAttribArray(context->normalLocation);
 
    }
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
 
    // Delete VBO
    glDeleteBuffers(1, vbo);
 
    // Create Index Buffer
    glGenBuffers(1, eao);
    {
      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eao[0]);
      glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndecies*sizeof(GLuint), indices, GL_STATIC_DRAW);
    }
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 
    angle = 0.0;
  }
 
  void render()
  {
 
    glBindVertexArray(vao[0]);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eao[0]);
 
    glDrawElements(GL_TRIANGLES, numIndecies, GL_UNSIGNED_INT, 0);
  }
 
  void update() {
    modelMat = glm::mat4(1.0f);
    modelMat = glm::translate(modelMat, position);
    modelMat *= glm::rotate(angle, angle_axis);
  }
 
  glm::mat4 getMatrix() {
    return modelMat;
  }
 
  void setAngle(float a, float ax, float ay, float az) {
    angle = a;
    angle_axis = glm::vec3(ax, ay, az);
  }
 
  void setPosition(float x, float y, float z) {
    position = glm::vec3(x, y, z);
  }
 
  void setSize(float x, float y, float z) {
    size = glm::vec3(x, y, z);
  }
};
 
 
///////////////////////////////////////////////////////////////////////////////
//
// gloval variables
//
ShaderContext context;
glm::mat4 projectionMatrix;
glm::mat4 viewMatrix;
Cube cube; // Model
 
 
 
//
// initialize
//
void init()
{
  //
  // GL initialize
  //
  glClearColor(0.5, 0.5, 0.5, 1.0);
  glClearDepth(1.0f);
 
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
 
  viewMatrix = glm::lookAt(
      glm::vec3(3.0f, 4.0f, 5.0f),  // eye
      glm::vec3(0.0f, 0.0f, 0.0f),  // center
      glm::vec3(0.0f, 1.0f, 0.0f)   // up
  );
 
  //
  // GLSL initialize
  //
  context.programObject = createProgram( "simple.vert", "simple.frag" );
 
  context.modelMatrixLocation = glGetUniformLocation(context.programObject, "u_modelMatrix");
  context.viewMatrixLocation = glGetUniformLocation(context.programObject, "u_viewMatrix");
  context.projectionMatrixLocation = glGetUniformLocation(context.programObject, "u_projectionMatrix");
 
  context.positionLocation = glGetAttribLocation(context.programObject, "a_position");
  context.normalLocation = glGetAttribLocation(context.programObject, "a_normal");
 
  glBindFragDataLocation(context.programObject, 0, "fragColor");
}
 
void reshape(int w, int h)
{
    glViewport(0, 0, w, h); 
 
    projectionMatrix = glm::perspective(30.0f, (float)w/(float)h, 1.0f, 100.0f);
}
 
void timer(int t)
{
    glutPostRedisplay();
    glutTimerFunc(t, timer, 17);
}
 
 
//
// Main Loop
//
void display()
{
  static float angle = 0.0;
  cube.setAngle(angle, 0.0f, 1.0f, 0.0f);
  cube.update();
 
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
  glUseProgram(context.programObject);
 
  glUniformMatrix4fv(context.viewMatrixLocation, 1, GL_FALSE, glm::value_ptr(viewMatrix));
  glUniformMatrix4fv(context.projectionMatrixLocation, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
 
  //
  // Draw Cube
  //
  glUniformMatrix4fv(context.modelMatrixLocation, 1, GL_FALSE, glm::value_ptr(cube.getMatrix()));
  cube.render();
 
  glUseProgram(0);
 
  glutSwapBuffers();
 
  angle += 1.0;
  if (angle > 180.0) angle = 0.0;
}
 
 
int main(int argc, char *argv[])
{
  glutInit(&argc, argv);
  glutInitWindowSize(400, 300);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow("OpenGL with GLEW");
 
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  glutTimerFunc(100, timer, 17);
 
  GLenum err;
  //glewExperimental = GL_TRUE;
  err = glewInit();
  if (err != GLEW_OK) {
    std::cerr << "GLEW error : " << glewGetErrorString(err) << "\n";
    std::exit(1);
  }   
  if (!glewIsSupported("GL_VERSION_3_2")) {
    std::cerr << "OpenGL 3.2 not supported.\n";
    std::exit(1);
  }
 
  init();
 
  //
  // setup Cube
  //
  cube.setup(&context);
  cube.setAngle(0.0, 0.0f, 1.0f, 0.0f);
  cube.setPosition(0.0, 0.0, 0.0);
 
  glutMainLoop();
 
  return 0;
}
 

タグ:

OpenGL GLSL GLEW VAO
添付ファイル
記事メニュー
目安箱バナー