Uniform是變量類型的一種修飾符,是OpenGL ES 中被着色器中的常量值,使用存儲各種着色器需要的數據,例如:轉換矩陣、光照參數或者顏色。
uniform 的空間被頂點着色器和片段着色器分享。也就是說頂點着色器和片段着色器被鏈接到一起進入項目,它們分享同樣的uniform。因此一個在頂點着色器中聲明的uniform,相當於在片段着色器中也聲明過了。當應用程序裝載uniform 時,它的值在頂點着色器和片段着色器都可用。在鏈接階段,鏈接器將分配常量在項目里的實際地址,那個地址是被應用程序使用和加載的標識。
另一個需要注意的是,uniform 被存儲在硬件被稱為常量存儲,這是一種分配在硬件上的存儲常量值的空間。因為這種存儲需要的空間是固定的,在程序中這種uniform 的數量是受限的。這個限制能通過讀gl_MaxVertexUniformVectors 和gl_MaxFragmentUniformVectors編譯變量得出。( 或者用GL_MAX_VERTEX_UNIFORM_VECTORS 或GL_MAX_FRAGMENT_UNIFORM_ VECTORS 為參數調用glGetIntegerv)OpenGL ES 2.0必須至少提供256 個頂點着色器uniform 和224個片段着色器uniform。
獲取和設置Uniform
在程序中使用glGetProgramiv函數,將GL_ACTIVE_UNIFORMS作為參數來查詢Uniforms,可以獲取程序中Uniform的數量,,如果常量處於active,說明它正在被程序使用。另外你可以只聲明Uniform而不使用它,鏈接器將會優化掉這些Uniform,不將它存儲到實際使用的常量列表中。你能使用GL_ACTIVE_UNIFORM_MAX_LENGTH 為參數調用glGetProgramiv,找出在程序里最大的常量列表名字(甚至是空的)。一旦我們知道實際使用的常量數目和描述的數目,我們可以使用glGetActiveUniform 和glGetActiveUniformsiv查找常量:
使用glGetActiveUniform函數你可以確定Uniform幾乎所有的屬性。你可以通過它的類型來確定它的名稱。另外如果變量是一個數組,你可以找出數組中的最大值。我們可以通過glGetUniformLocation函數來獲取Uniform的位置,位置值是一個整型數據,用來標識Uniform在程序中的位置。注意:不在uniform 塊中指定位置。這個位置值用於后面函數使用這個Uniform。
glGetUniformLocation將根據Uniform名稱獲取Uniform的位置,通過下列函數根據位置來裝載uniform
裝載uniforms函數大部分是自動完成的。使用哪個函數裝載uniforms取決於glGetActiveUniform函數返回的類型。例如類型如果是GL_FLOAT_VEC4,glUniform4f 或glUniform4fv 被使用。如果返回的類型大於一個,glUniform4fv 將被使用一次裝載整個數組。如果uniform不是一個數組類型,glUniform4f 或glUniform4fv 被使用。一個值得注意的地方是glUniform*調用不使用程序對象句柄做參數。原因是因為glUniform*調用總是在當前的程序中綁定glUseProgram 執行。uniform值在程序對象中總是保持一致。也就是說,一旦你在項目里設定一個uniform值,這個值將保持不變,甚至你激活另一個程序。
GLint maxUniformLen; GLint numUniforms; char *uniformName; GLint index; glGetProgramiv ( progObj, GL_ACTIVE_UNIFORMS, &numUniforms ); glGetProgramiv ( progObj, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen ); uniformName = malloc ( sizeof ( char ) * maxUniformLen ); for ( index = 0; index < numUniforms; index++ ) { GLint size; GLenum type; GLint location; // Get the uniform info glGetActiveUniform ( progObj, index, maxUniformLen, NULL, &size, &type, uniformName ); // Get the uniform location location = glGetUniformLocation ( progObj, uniformName ); switch ( type ) { case GL_FLOAT: // break; case GL_FLOAT_VEC2: // break; case GL_FLOAT_VEC3: // break; case GL_FLOAT_VEC4: // break; case GL_INT: // break; // ... Check for all the types ...
default:
// Unknown type
break;
}
}