2013-03-13 72 views
8

我正在閱讀關於OpenGL和OpenGLES的教程,我對在這兩個API中使用函數glVertexAttribPointer有點困惑。OpenGL和OpenGLES中的glVertexAttribPointer

OpenGL教程這個函數使用最後一個參數的數值偏移量(通過強制轉換爲常量GLVoid *),我假設頂點直接取自當前的數組緩衝區。

glVertexAttribPointer(vs_position, 2, GL_FLOAT, GL_TRUE, 5 * sizeof(GLfloat), (const GLvoid*) (3*sizeof(GLfloat))); 

OpenGLES直接教程的最後一個參數指向代表頂點的結構:

GLFloat vertices[] = {...definition}; 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices); 

我無法理解這兩個函數是如何工作的。他們完全不同的功能?

回答

25

它們是以兩種不同方式使用的相同功能。我會解釋它爲什麼會這樣工作,但你不會在意,這是非常愚蠢和不相干的原因。

重要的是他們在做什麼。他們在做什麼取決於你沒有顯示的東西:什麼是GL_ARRAY_BUFFER

請參閱,glVertexAttribPointer的行爲更改取決於此。如果在調用glVertexAttribPointer時沒有綁定到GL_ARRAY_BUFFER的緩衝區對象,則該函數將假定最終值爲指針(如函數的名稱所示:glVertexAttrib 指針)。具體而言,它是一個指向客戶端擁有的內存的指針。

當需要渲染時,頂點屬性數據將來自之前提供的指針。因此,第二個示例僅使用以標準C風格聲明的客戶端數據數組作爲源數據。不涉及任何緩衝對象。

注意:OpenGL 3.1+的核心配置文件刪除了使用客戶端內存的能力;在那裏,你必須使用使用緩衝區對象,如下所述。

如果在調用glVertexAttribPointer時緩衝區對象被綁定到GL_ARRAY_BUFFER,則會發生一些特殊情況。 OpenGL將假裝指針(就C/C++而言,最後一個參數是什麼)實際上是一個字節偏移量,與緩衝區綁定到GL_ARRAY_BUFFER。它會將指針轉換爲整數,然後存儲該整數偏移量和當前綁定到GL_ARRAY_BUFFER的緩衝區對象。

因此,上面的代碼需要3*sizeof(GLfloat),字節偏移量,並將其轉換爲指針。 OpenGL將獲取指針並將其轉換回偏移量,再次產生3*sizeof(GLfloat)

當需要渲染時,OpenGL將使用先前給定的偏移量從先前給定的緩衝區對象中讀取數據。

第一個示例將頂點數據放入GPU內存中的緩衝區對象中。第二個示例將頂點數據放入CPU內存中的常規C/C++數組中。

+0

完美的解釋!謝謝。 - 你從哪裏得到這些信息?我找不到有關這方面的文件。 - 你說OpenGL3.1而不使用內存客戶端對OpenGLEs 2.0也有效? – MatterGoal 2013-03-13 09:10:19

+0

@MatterGoal:一般來說,應用程序總是使用客戶端內存或緩衝區對象。所以沒有人需要談論它們之間的差異。大部分的桌面OpenGL文檔都轉向了核心配置文件行爲,所以它也不會談論它。但是它正好在[GL ES的手冊頁](http://www.khronos.org/opengles/sdk/docs/man/xhtml/glVertexAttribPointer.xml)中。請閱讀說明的第二段。 – 2013-03-13 09:15:03

+0

@MatterGoal:它也在[這個答案](http://stackoverflow.com/a/5402762/734069)中解釋了相關的問題。 – 2013-03-13 09:17:00

1

GL spec清楚地提到了這一點:

殼體1:如果在指定的一個通用的頂點屬性陣列非零命名緩衝器對象綁定到GL_ARRAY_BUFFER目標,指針將被視爲一個字節偏移到緩衝對象的數據存儲。

情況2:指定指向數組中第一個通用頂點屬性的第一個組件的指針。