OpenGL ES 3.0之Uniform詳解


  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;
  }
}

 

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM