在將數據(頂點、紋理等)傳送給GPU之前,我們需要獲取到相對應緩衝的索引,之前我都是使用
GLint glGetAttribLocation(GLuint program,const GLchar *name);
其中,program指定查詢的程序對象,name指定要查詢位置的屬性變量的名稱,返回的就是屬性變量的位置。
glGetAttribLocation查詢由program指定的先前鏈接的程序對象,用於name指定的屬性變量,並返回綁定到該屬性變量的通用頂點屬性的索引。 如果name是矩陣屬性變量,則返回矩陣的第一列的索引。 如果指定的屬性變量不是指定程序對象中的活動屬性,或者名稱以保留前綴“gl_”開頭,則返回-1。
可以通過調用glBindAttribLocation隨時指定屬性變量名和通用屬性索引之間的關聯。 在調用glLinkProgram之前,屬性綁定不會生效。 成功鏈接程序對象後,屬性變量的索引值將保持固定,直到發生下一個鏈接命令。 如果鏈接成功,則只能在鏈接後查詢屬性值。 glGetAttribLocation返回上次爲指定程序對象調用glLinkProgram時實際生效的綁定。 glGetAttribLocation不返回自上次鏈接操作以來指定的屬性綁定。
一般也沒啥問題,只要shader裏面有的屬性,在這裏都可以獲取的到。但是這次頂點着色器中的三個屬性中的my_Color就是獲取不到,返回-1,以下是兩個着色器內容:
vs:
attribute vec4 my_Vertex;
attribute vec4 my_Color;
uniform mat4 my_TransformMatrix;
attribute vec2 my_Texcoor;
varying vec2 vTexcoor;
varying vec4 color;
void main()
{
vTexcoor = my_Texcoor;
color = my_Color;
gl_Position = my_TransformMatrix * my_Vertex;
}
fs:
varying vec4 color;
uniform sampler2D my_Sampler;
varying vec2 vTexcoor;
void main (void)
{
vec4 tex = texture2D(my_Sampler, vTexcoor);
gl_FragColor = tex;
}
接下來想查詢一下有哪些激活的屬性:
GLint count;
GLint size; // size of the variable
GLenum type; // type of the variable (float, vec3 or mat4, etc)
const GLsizei bufSize = 256; // maximum name length
GLchar name[bufSize]; // variable name in GLSL
GLsizei length; // name length
glGetProgramiv(programHandle, GL_ACTIVE_ATTRIBUTES, &count);
printf("Active Attributes: %d\n", count);
for (int idx = 0; idx < count; idx++)
{
glGetActiveAttrib(programHandle, (GLuint)idx, bufSize, &length, &size, &type, name);
printf("Attribute #%d Type: 0x%x Name: %s\n", idx, type, name);
GLuint location = glGetAttribLocation(programHandle, name);
printf("location = %d \n",location);
}
結果也還是一樣,沒有my_Color.
糾結了好久,最終發現是因爲shader在編譯的時候做了優化,對於一些沒有真正參與到計算的屬性直接移除掉了,所以怎麼找也找不到my_Color。
解決方案,使用glBindAttribLocation。
void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name);
其中,program指定要在其中建立關聯的程序對象的句柄。index指定要綁定的通用頂點屬性的索引。name指定一個以空終止符結尾的字符串,其中包含要綁定索引的頂點着色器屬性變量的名稱。
在調用glLinkProgram之前,屬性綁定不會生效。成功鏈接程序對象後,通用屬性的索引值保持固定(並且可以查詢它們的值),直到發生下一個鏈接命令。
可以在任何頂點着色器對象綁定到指定程序對象之前調用glBindAttribLocation。也允許將通用屬性索引綁定到從未在頂點着色器中使用的屬性變量名稱。
如果以前綁定了name,則該信息將丟失。因此,您不能將一個用戶定義的屬性變量綁定到多個索引,但您可以將多個用戶定義的屬性變量綁定到同一索引。
允許應用程序將多個用戶定義的屬性變量綁定到相同的通用頂點屬性索引。這稱爲aliasing(別名),僅當可執行程序中只有一個別名屬性處於活動狀態時,或者如果沒有通過着色器的路徑消耗屬於同一位置的一組屬性的多個屬性時,才允許使用別名。允許編譯器和鏈接器假定沒有進行別名,並且可以自由地使用僅在沒有別名的情況下工作的優化。不需要OpenGL實現來進行錯誤檢查以檢測別名。由於無法綁定標準屬性,因此無法使用常規屬性對通用屬性進行別名(通用屬性0除外)。
調用glLinkProgram時,鏈接器將綁定未顯式綁定的活動屬性。可以通過調用glGetAttribLocation來查詢分配的位置。
調用glBindAttribLocation時,OpenGL會複製名稱字符串,因此應用程序可以在函數返回後立即釋放其名稱字符串的副本。