歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

OpenGL超級寶典學習筆記——頂點緩沖區對象

顯示列表可以快速簡單地優化立即模式(glBegin/glEnd)的代碼。在最壞的情況下,顯示列表的命令被預編譯存到命令緩沖區中,然後發送給圖形硬件。在最好的情況下,是編譯後放在圖形硬件中以減少傳輸的帶寬。顯示列表的優化根據實現的不同而有所不同,而且顯示列表一旦被創建就不可以修改,靈活性差。

頂點數組提供了我們想要的靈活性,最壞的結果不過是把數據塊復制給硬件而已(比立即模式快的多)。而索引頂點數組可以減少向硬件傳輸的頂點數據的數量,減少變換的開銷。

OpenGL還提供了一個特性對圖形的吞吐量進行終極的控制。當我們使用頂點數組時,可以把單個數組從客戶內存(CPU可以訪問)傳輸到圖形硬件。這個特性稱為頂點緩沖區對象,允許我們按照類似於管理紋理的方式來管理頂點數組數據,而且頂點緩沖區對象要更靈活。

 

管理和使用緩沖區對象

首先要使用緩沖區對象得有頂點數組。第二步創建頂點緩沖區對象,使用函數:

void glGenBuffers(GLsizei n, GLuint *buffers);

這個函數工作方式像glGenTextures一樣。其對應的刪除緩沖區對象的函數是glDeleteBuffers。

然後綁定頂點緩沖區對象:

void glBindBuffer(GLenum target, GLuint buffer);

這裡的target參數指定了要綁定什麼樣的數組。類型有很多,可以是頂點數組GL_ARRAY_BUFFER,頂點索引數組GL_ELEMENT_ARRAY_BUFFER(用於glDrawElements和其他基於索引的渲染函數)等。

 

加載緩沖區對象

在綁定了緩沖區對象之後,我們就可以往圖形硬件拷貝頂點數組了。

void glBufferData(GLenum target, GLsizeptr size, GLvoid *data, GLenum usage);

target可以是GL_ARRAY_BUFFER或者GL_ELEMENT_ARRAY_BUFFER等。size指定了頂點數組的大小(以字節為單位)。最後一個參數是用法提示。如下表:

用法提示 描述 GL_DYNAMIC_DRAW 存儲在緩沖區對象中的頂點數組經常要更新,並且可能多次作為繪圖的來源。這個提示告訴OpenGL實現把數據放置在更新開銷不大的地方。 GL_STATIC_DRAW 數組很少更新,但可能多次作為繪圖的來源。這個提示告訴OpenGL實現把數據放置在能夠快速渲染但不需要快速更新的地方。 GL_STREAM_DRAW 數據極少變化,並且最多只有幾次作為繪圖的源數據。這個提示告訴OpenGL實現有一些時間敏感的數據(例如動畫)將只使用一次,然後被替換。

 

從頂點緩沖區對象渲染

從頂點緩沖區對象渲染有兩個地方需要改動。首先,需要在調用glVertexPointer之前綁定緩沖區對象,然後把真實的數組指針改成頂點緩沖區對象的偏移值。例如:

glVertexPointer(3, GL_FLOAT, 0, pVerts);

現在變成了:

glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[0]);

glVertexPointer(3, GL_FLOAT, 0, 0);

渲染 就變成了:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObjects[3]);

glDrawElements(GL_TRIANGLES, nNumIdexes, GL_UNSIGNED_SHORT, 0);

最後一個參數會偏移量。從技術上說,緩沖區對象的這個偏移量基於本地體系結構的NULL指針。在大多數系統中,可設置為0.

 

總體步驟

  1. 生成緩沖區對象標識符glGenBuffers(可選步驟)

  2. 綁定一個緩沖區對象,確定它是用於存儲頂點數組還是索引(GL_ARRAY_BUFFER,還是GL_ELEMENT_BUFFER)

  3. 請求數據的存儲空間,並且對這些數據元素進行初始化

  4. 指定相對於緩沖區起始位置的偏移量。

  5. 綁定適當的緩沖區對象,用於渲染。

  6. 使用適當的頂點數組渲染函數進行渲染如glDrawArrays glDrawElements

簡單示例:

#include "gltools.h"

//宏定義
#define VERTICES 0
#define INDICES 1
#define NUM_BUFFERS 2

//緩沖區標示符
GLuint buffers[NUM_BUFFERS];

static GLfloat cube[]={-1.0f, -1.0f, -5.0f, //前面的正方形
1.0f, -1.0f,-5.0f,
1.0f, 1.0f, -5.0f, 
-1.0f, 1.0f, -5.0f,
-1.0f, -1.0f, -10.0f,//背面的正方形
1.0f, -1.0f, -10.0f,
1.0f, 1.0f, -10.0f,
-1.0f, 1.0f, -10.0f};

static GLubyte index[]={0, 1, 2, 3, //前面
0, 3, 7, 4, //左面
5, 6, 2, 1, //右面
7, 6, 5, 4, //後面
3, 2, 6, 7, //上面
1, 0, 4, 5 //地面
};



void SetupRC()
{
  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

  //生成緩沖區標示符
  glGenBuffers(NUM_BUFFERS, buffers);
  //綁定緩沖區對象,並設置頂點數組
  glBindBuffer(GL_ARRAY_BUFFER, buffers[VERTICES]);
  glBufferData(GL_ARRAY_BUFFER, sizeof(cube), cube, GL_STATIC_DRAW);
  glVertexPointer(3, GL_FLOAT, 0, 0);


}

void RenderScene()
{
  glClear(GL_COLOR_BUFFER_BIT);

  glColor3f(0.0f, 0.0f, 1.0f);

  glPushMatrix();

  glEnableClientState(GL_VERTEX_ARRAY);

  //綁定緩沖區對象,並進行渲染
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[INDICES]);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(index), index, GL_STATIC_DRAW);
  glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, 0);

  glDisableClientState(GL_VERTEX_ARRAY);
  glPopMatrix();
  glutSwapBuffers();
}

void ChangeSize(GLsizei w, GLsizei h)
{
  if(h == 0)
    h = 1;

  glViewport(0, 0, w, h);

  GLfloat fAspect = (GLfloat)w / (GLfloat)h;

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  gluPerspective(35.0f, fAspect, 1.0f, 100.0f);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

int main(int args, char* argv[])
{
  glutInit(&args, argv);
  glutInitWindowPosition(200, 200);
  glutInitWindowSize(800, 600);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
  glutCreateWindow("VBO");
  glutDisplayFunc(RenderScene);
  glutReshapeFunc(ChangeSize);
  SetupRC();
  glutMainLoop();
  return 0;
}

 

OpenGL超級寶典 第4版 中文版PDF+英文版+源代碼 見  http://www.linuxidc.com/Linux/2013-10/91413.htm

OpenGL編程指南(原書第7版)中文掃描版PDF 下載 http://www.linuxidc.com/Linux/2012-08/67925.htm

OpenGL 渲染篇 http://www.linuxidc.com/Linux/2011-10/45756.htm

Ubuntu 13.04 安裝 OpenGL http://www.linuxidc.com/Linux/2013-05/84815.htm

OpenGL三維球體數據生成與繪制【附源碼】 http://www.linuxidc.com/Linux/2013-04/83235.htm

Ubuntu下OpenGL編程基礎解析 http://www.linuxidc.com/Linux/2013-03/81675.htm

如何在Ubuntu使用eclipse for c++配置OpenGL http://www.linuxidc.com/Linux/2012-11/74191.htm 

更多《OpenGL超級寶典學習筆記》相關知識 見 http://www.linuxidc.com/search.aspx?where=nkey&keyword=34581

Copyright © Linux教程網 All Rights Reserved