頂點屬性數(shù)據(jù)可以用一個頂點數(shù)組對每個頂點指定澳盐,也可以將一個常量值用于一個圖元的所有頂點
OpenGLES支持最少16個頂點屬性。準確查詢頂點數(shù)量方法如下:
GLint maxVertexAttribs;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
一糠爬、指定頂點數(shù)組
1、常量頂點屬性:
常量頂點屬性對于一個圖元的所有頂點都相同举庶,所以對一個圖元的所有頂點只需指定一個值秩铆。函數(shù)如下:
void glVertexAttrib1f(GLuint index, GLfloat x);
void glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
void glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
void glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void glVertexAttrib1fv(GLuint index, GLfloat x);
void glVertexAttrib2fv(GLuint index, GLfloat x, GLfloat y);
void glVertexAttrib3fv(GLuint index, GLfloat x, GLfloat y, GLfloat z);
void glVertexAttrib4fv(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
glVertexAttrib* 命令用于加載index 指定的通用頂點屬性。
2灯变、頂點數(shù)組
頂點數(shù)組指定每個頂點的屬性殴玛,是保存應用程序地址空間的緩沖區(qū)。他們作為頂點緩沖對象的基礎添祸,提供指定頂點屬性數(shù)據(jù)的一個高效滚粟、靈活的手段。
void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *ptr);
void glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void *ptr);
index - 指定通用頂點屬性索引刃泌。
size - 頂點數(shù)組中為索引引用的頂點屬性所指定的分量數(shù)量凡壤。
type - 數(shù)據(jù)格式署尤,兩條函數(shù)均有的值:GL_BYTE,GL_UNSIGNED_BYTE亚侠,GL_SHORT曹体,GL_UNSIGNED_SHORT,GL_INT硝烂,GL_UNSIGNED_INT箕别,glVertexAttribPointer還包括GL_HALF_FLOAT,GL_FLOAT滞谢,GL_FIXED串稀,GL_INT_2_10_10_10_REV,GL_UNSIGNED_INT_2_10_10_10_REV
normalized - 用于表示非浮點數(shù)據(jù)格式類型在轉換為浮點值時是否應該規(guī)范化狮杨。對于glVertexAttribIPointer來說母截,這些值被當作整數(shù)對待
stride - 每個頂點由size指定頂點屬性分量順序存儲。stride指定頂點索引 表示頂點數(shù)據(jù)之間的位移橄教,大于0清寇,表示使用該值作為下一個索引表示的頂點數(shù)據(jù)的跨距。
ptr - 如果使用客戶端頂點數(shù)據(jù)护蝶,則保存頂點屬性數(shù)據(jù)的緩沖區(qū)的指針华烟,如果使用頂點緩沖區(qū)對象,則表示該緩沖區(qū)內的偏移量滓走。
分配和存儲頂點屬性數(shù)據(jù)有兩種常用的方法:
在一個緩沖區(qū)中存儲頂點屬性 —— 這種方法稱為結構數(shù)組。結構表示頂點的所有屬性帽馋,每個頂點有一個屬性的數(shù)組搅方。結構數(shù)組的分配方法通常是最高效的。
在單獨的緩沖區(qū)中保存每個頂點屬性 —— 這個方法稱為數(shù)組結構绽族。
頂點屬性使用哪種數(shù)據(jù)格式
glVertexAttribPointer 中用type參數(shù)指定的頂點屬性數(shù)據(jù)格式不僅影響頂點屬性數(shù)據(jù)的圖形內存存儲需求姨涡,而且影響整體性能。OpenGLES 3.0開始支持GL_HALF_FLOAT 的16位浮點頂點格式吧慢,建議盡可能使用GL_HALF_FLOAT涛漂,即紋理、坐標检诗、法線匈仗、副法線、切向量等使用GL_HALF_FLOAT逢慌,顏色存儲為GL_UNSIGNED_BYTE悠轩,每個頂點顏色具有4個分量。
glVertexAttribPointer中規(guī)范化標志是如何工作的攻泼?
在用于頂點著色器之前火架,頂點屬性在內部保存為單精度浮點數(shù)鉴象。如果數(shù)據(jù)類型表示頂點屬性不是浮點數(shù),頂點屬性將在用于頂點著色器之前轉換為單精度浮點數(shù)何鸡。規(guī)范化標志控制非浮點數(shù)頂點屬性數(shù)據(jù)到單精度浮點值的轉換纺弊,標志為假時,頂點數(shù)據(jù)被肢解轉換為浮點數(shù)骡男,如果為真且數(shù)據(jù)類型為GL_BYTE淆游、GL_SHORT、GL_FIXED洞翩,則頂點數(shù)據(jù)被映射到[-1.0, 1.0]范圍內稽犁,如果數(shù)據(jù)類型為GL_UNSIGNED_BYTE或GL_UNSIGNED_SHORT,則被映射到[0.0, 1.0]范圍內骚亿。如果想要按照整數(shù)的形式訪問整數(shù)型頂點已亥,應該使用glVertexAttribIPointer。
常量頂點屬性和頂點數(shù)組之間選擇
glEnableVertexAttribArray 和 glDisableVertexAttribArray 命令分別用于啟用和禁用通用頂點屬性數(shù)組来屠。
二虑椎、在頂點著色器中聲明頂點屬性變量
屬性變量也可以選擇包含一個布局限定符,提供屬性索引俱笛。示例:
layout(location = 0) in vec4 a_postion;
layout(location = 1) in vec2 a_texcoord;
layout(location = 2) in vec3 a_normal;
頂點著色器中聲明為頂點屬性的變量是只讀變量捆姜,不能修改。屬性可以在頂點著色器內部聲明迎膜,不使用不會被認為是活動屬性泥技,著色器屬性數(shù)量不能大于GL_MAX_VERTEX_ATTRIBS,否則無法被鏈接磕仅。
將頂點屬性綁定到頂點著色器中的屬性變量
頂點屬性由in限定符指定珊豹,活動屬性數(shù)量可以用glGetProgramiv查詢,程序中活動屬性列表可以用glGetActiveAttrib查詢榕订。
指定通用頂點屬性和綁定到頂點著色器中的屬性名稱:
OpenGLES3.0中店茶,可以使用3種方法將通用頂點屬性索引映射到頂點著色器中的一個屬性變量名稱。
1劫恒、索引在源碼中用layout(location = N)聲明指定
2贩幻、OpenGLES3.0將通用頂點屬性索引綁定到屬性名稱
3、應用程序可以將頂點屬性索引綁定到屬性名稱
使用glBindAttribLocation命令可以將通用頂點屬性索引綁定到頂點著色器中的一個屬性變量两嘴。這種綁定在下一個程序鏈接時生效——不會改變當前鏈接的程序中使用的綁定丛楚。
另外,也可以使用glGetAttribLocation命令查詢分配的綁定憔辫,需要在返回program定義的程序獨享最后一次鏈接時綁定到屬性變量的通用屬性索引鸯檬。
三、頂點緩沖區(qū)對象
頂點數(shù)組指定的頂點數(shù)據(jù)保存在客戶內存中螺垢。在進行glDrawArrays活著glDrawElements等繪圖調用時喧务,這些數(shù)據(jù)必須同客戶內存復制到圖形內存赖歌。
沒必要每次繪圖時都復制頂點數(shù)據(jù),而是在圖形內存中緩存這些數(shù)據(jù)功茴,這樣可以顯著改善渲染性能庐冯,也可以降低內存帶寬和電力消耗需求。這就是頂點緩沖區(qū)對象發(fā)揮作用的地方坎穿。
不緊緊是頂點數(shù)據(jù)展父,描述圖元頂點索引、作為glDrawElements參數(shù)傳遞的元素索引也可以緩存玲昧。
GL_ARRAY_BUFFER 指定的數(shù)組緩沖區(qū)對象用于創(chuàng)建保存頂點數(shù)據(jù)的緩沖區(qū)對象栖茉。
GL_ELEMENT_ARRAY_BUFFER 指定的元素數(shù)組緩沖區(qū)對象用于保存圖元索引的緩沖區(qū)對象。
創(chuàng)建和綁定頂點緩沖區(qū)對象例子:
void initVertexBufferObjects(vertex_t *vertexBuffer,
GLushort *indices,
GLuint numVertices,
GLuint numIndices,
GLuint *vboIds) {
// 獲取vboIds中兩個未用的緩沖區(qū)對象名稱孵延。然后vboIds返回的未使用的緩沖區(qū)對象名稱用于創(chuàng)建一個數(shù)組緩沖區(qū)對象
// 和一個元素數(shù)組緩沖區(qū)對象吕漂。數(shù)組緩沖區(qū)對象用于保存一個或多個圖元的頂點屬性數(shù)據(jù)。
glGenBuffers(2, vboIds);
glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]);
glBufferData(GL_ARRAY_BUFFER, numVertices *sizeof(vertex_t),
vertexBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices *sizeof(GLushort),
indices, GL_STATIC_DRAW);
}
glGenBuffers(GLsizei n, GLuint * buffers) :分配n個緩沖區(qū)對象名稱尘应,并在buffers中返回它們惶凝。
glBindBuffer 用于指定當前緩沖區(qū)對象。第一次通過調用glBindBuffer綁定緩沖區(qū)對象名稱時犬钢,緩沖區(qū)對象可以默認狀態(tài)分配苍鲜;如果分配成功,則分配的對象綁定微目標的當前緩沖區(qū)對象玷犹。
glBufferData 用于創(chuàng)建和初始化頂點數(shù)組或元素數(shù)組