VBO

VBOです。
頂点配列はPC本体のRAM(メモリ)にデータを置いておいて、
描画する時にビデオカードにデータを転送し、それを使って描画していました。
データの少ない物を描画する分には問題ありませんがポリゴン数の多いモデルを
大量に描画したりする時に一々毎回データを転送していてはかなりの無駄が
生じています。
そこで描画を高速化する為にビデオカードのRAMに予めデータを置いておき
PC本体から毎回データを転送しなくても良いようにするのがVBOです。
今回のプログラムは頂点配列の解説で使ったプログラムをVBOにしています。

 

ファイル
main.cpp

main.cpp

#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib,"glew32.lib")

#include <gl/glew.h>
#include <GL/freeglut/freeglut.h>

#define WIDTH 320
#define HEIGHT 240

GLuint VboId[3];//3つ分
float angle=0.0f;

//頂点データ 3面を4頂点で作成する 1頂点はx,y,zの3要素
GLfloat Vertex[3][4][3] ={
 {{1.0f,0.0f,0.0f},{1.0f,0.0f,0.5f},{0.0f,1.0f,0.5f},{0.0f,1.0f,0.0f}},//1枚目
 {{1.0f,0.0f,0.0f},{1.0f,0.0f,0.5f},{-1.0f,0.0f,0.5f},{-1.0f,0.0f,0.0f}},//2枚目
 {{-1.0f,0.0f,0.0f},{-1.0f,0.0f,0.5f},{0.0f,1.0f,0.5f},{0.0f,1.0f,0.0f}},//3枚目
};
GLfloat Normal[6][4][3] ={
 {{1.0f,0.5f,0.0f},{1.0f,0.5f,0.0f},{1.0f,0.5f,0.0f},{1.0f,0.5f,0.0f}},//右上
 {{0.0f,-1.0f,0.0f},{0.0f,-1.0f,0.0f},{0.0f,-1.0f,0.0f},{0.0f,-1.0f,0.0f}},//下
 {{-1.0f,0.5f,0.0f},{-1.0f,0.5f,0.0f},{-1.0f,0.5f,0.0f},{-1.0f,0.5f,0.0f}},//左上
};
GLfloat Color[6][4][3] ={
 {{1.0f,0.0f,0.0f},{1.0f,0.0f,0.0f},{1.0f,0.0f,0.0f},{1.0f,0.0f,0.0f}},//赤
 {{0.0f,0.0f,1.0f},{0.0f,0.0f,1.0f},{0.0f,0.0f,1.0f},{0.0f,0.0f,1.0f}},//青
 {{0.0f,1.0f,0.0f},{0.0f,1.0f,0.0f},{0.0f,1.0f,0.0f},{0.0f,1.0f,0.0f}},//緑
};
void DrawArray(void)
{
  //データの場所を知らせる
 //座標
 glBindBuffer(GL_ARRAY_BUFFER,VboId[0]);
 glVertexPointer(3, GL_FLOAT, 0, 0);
 //法線
 glBindBuffer(GL_ARRAY_BUFFER,VboId[1]);
 glNormalPointer(GL_FLOAT, 0, 0);
 //色
 glBindBuffer(GL_ARRAY_BUFFER,VboId[2]);
 glColorPointer(3,GL_FLOAT, 0, 0);

 //有効化
 glEnableClientState(GL_VERTEX_ARRAY);
 glEnableClientState(GL_NORMAL_ARRAY);
 glEnableClientState(GL_COLOR_ARRAY);

 glDrawArrays(GL_QUADS,0,4*3); //描画(4頂点*3面)

 //無効化
 glDisableClientState(GL_COLOR_ARRAY);
 glDisableClientState(GL_NORMAL_ARRAY);
 glDisableClientState(GL_VERTEX_ARRAY);
}
void display(void)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glViewport(0,0,WIDTH,HEIGHT);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(30.0, WIDTH/HEIGHT, 0.1, 200.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

 glRotatef(angle,1.0f,0.0f,0.0f);//回転
 glRotatef(angle,0.0f,1.0f,0.0f);//回転

 DrawArray();

 glutSwapBuffers();
}
void idle(void)
{
 angle+=0.2f;
 Sleep(1);
 glutPostRedisplay();
}
void Init(){
 glewInit();
 glClearColor(0.0, 0.0, 0.0, 1.0);
  glEnable(GL_DEPTH_TEST);
 glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
 glEnable(GL_COLOR_MATERIAL);
 glEnable(GL_LIGHT0);
 glEnable(GL_LIGHTING);
 glEnable(GL_NORMALIZE);//法線の正規化

  glGenBuffers(3,&VboId[0]);//座標、法線、色の3つ
 
 //頂点
 glBindBuffer(GL_ARRAY_BUFFER,VboId[0]);
 glBufferData(GL_ARRAY_BUFFER,sizeof(Vertex),
    Vertex,GL_DYNAMIC_DRAW);

 //法線
 glBindBuffer(GL_ARRAY_BUFFER,VboId[1]);
 glBufferData(GL_ARRAY_BUFFER,sizeof(Normal),
    Normal,GL_DYNAMIC_DRAW);

 //色
 glBindBuffer(GL_ARRAY_BUFFER,VboId[2]);
 glBufferData(GL_ARRAY_BUFFER,sizeof(Color),
     Color,GL_STREAM_DRAW);

}
int main(int argc, char *argv[])
{
 glutInitWindowPosition(100, 100);
 glutInitWindowSize(WIDTH, HEIGHT);
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
 glutCreateWindow("VBO");
 glutDisplayFunc(display);
 glutIdleFunc(idle);
 Init();
 glutMainLoop();
 return 0;
}

 

最終更新:2015年03月22日 17:19
添付ファイル