簡介
Uniform是一種從CPU中的應(yīng)用向GPU中的著色器發(fā)送數(shù)據(jù)的方式,但uniform和頂點屬性有些不同。
首先,uniform是全局的(Global)。全局意味著uniform變量必須在每個著色器程序?qū)ο笾卸际仟氁粺o二的,而且它可以被著色器程序的任意著色器在任意階段訪問。
第二,無論你把uniform值設(shè)置成什么,uniform會一直保存它們的數(shù)據(jù),直到它們被重置或更新。
單獨統(tǒng)一變量
聲明
uniform vec3 color
賦值
//獲取指定統(tǒng)一變量的location
int vertexColorLocation = glGetUniformLocation(_program, "test");
//為vec3 的統(tǒng)一變量 賦值
glUniform3f(vertexColorLocation, 0.0f, 1.0f, 0.0f);
賦值函數(shù)是根據(jù) 統(tǒng)一變量類型的不同而調(diào)整的.其中函數(shù)名中包含數(shù)字(1、2、3、4)表示接受這個數(shù)字個用于更改uniform變量的值,i表示32位整形,f表示32位浮點型,ub表示8位無符號byte,ui表示32位無符號整形,v表示接受相應(yīng)的指針類型(或者就是傳入的是數(shù)組)。
glUniform1f(GLint locaation,GLFloat x)
表示 float類型
glUniform2f(GLint locaation,GLFloat x,GLFloat y)
表示 二位向量 分量類型為float
glUniform1fv(GLint locaation,GLSize count,const GLfloat* value)
float類型指針
glUniformMatrix4x3(Glint location,GLsizei count,GLboolean transpose,const GLfloat* value)
表示為 4x3矩陣. 參數(shù): transpose 表示是否采用 行優(yōu)先順序(GL_TRUE)
UBO
UBO(Uniform Buffer Object)是用來存儲著色語言中Uniform類型變量的緩沖區(qū)對象,使用UBO可以讓uniform變量在不同的著色語言程序中實現(xiàn)共用,也可以在著色語言程序中實現(xiàn)uniform類型變量的設(shè)置與更新。
提到UBO就必須要提到著色語言GLSL中的Uniform Blocks,它將眾多的Uniform類型的變量集中在一起進行統(tǒng)一的管理,對于需要大量Uniform類型變量的程序可以顯著地提高性能。(有點像全局版的VBO)
原理
在顯存中創(chuàng)建緩存對象(Buffer),在buffer中存儲統(tǒng)一變量數(shù)據(jù), 將Buffer與 指定的point綁定, 將統(tǒng)一變量緩沖區(qū)的索引 和 point綁定. 這樣通過point 將變量 和 緩存 連接.
設(shè)置UBO
//統(tǒng)一變量塊
layout (std140) uniform colorBlock{
vec4 cc;
};
GLuint blockid,bufferid;
GLint blocksize;
GLint point = 1;
// 統(tǒng)一變量數(shù)據(jù)
GLfloat blockData[] = {
1.0f,1.0f,1.0f,1.0f
};
//獲取統(tǒng)一變量塊索引
blockid = glGetUniformBlockIndex(_program, "colorBlock");
//獲取統(tǒng)一變量塊大小
glGetActiveUniformBlockiv(_program, blockid, GL_UNIFORM_BLOCK_DATA_SIZE, &blocksize);
//將變量索引 和 point 綁定
glUniformBlockBinding(_program, blockid, point);
//創(chuàng)建與綁定緩沖區(qū)
glGenBuffers(1, &bufferid);
glBindBuffer(GL_UNIFORM_BUFFER, bufferid);
//向緩沖區(qū)中賦值
glBufferData(GL_UNIFORM_BUFFER, blocksize, blockData, GL_DYNAMIC_DRAW);
//將UBO 和 point 綁定
glBindBufferBase(GL_UNIFORM_BUFFER, point, bufferid);
修改UBO
GLfloat uploadData[] = {
0.0f,0.0f,1.0f,1.0f
};
// 綁定當然統(tǒng)一變量塊的 buffer
glBindBuffer(GL_UNIFORM_BUFFER, bufferid);
//獲取統(tǒng)一變量塊 中 指定變量的 偏移量
const GLchar *names[] = {"cc"};
GLuint indices[1];
glGetUniformIndices(_program, 1, names, indices);
GLint offset[1];
glGetActiveUniformsiv(_program, 1, indices, GL_UNIFORM_OFFSET, offset);
glBufferSubData(GL_UNIFORM_BUFFER, offset[0], blocksize, uploadData);
函數(shù)補充
1, glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const *uniformNames, GLuint* uniformIndices)
該函數(shù)用于獲取統(tǒng)一變量塊中 變量們的索引 參數(shù):
program 程序?qū)ο?br> uniformCount 變量名稱數(shù)組的元素數(shù)量
uniformNames 變量名稱數(shù)組
uniformIndices 用于接受變量索引的數(shù)組
2,glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
該函數(shù)用于 通過變量索引 查詢變量信息. 參數(shù):
program 程序?qū)ο?br> uniformCount 變量數(shù)量
uniformIndices 變量索引數(shù)組
pname 表示要查詢變量的那個屬性 GL_UNIFORM_OFFSET(變量偏移量) GL_UNIFORM_SIZE(變量大小) GL_UNIFORM_NAME_LENGTH(變量名長度) GL_UNIFORM_TYPE(變量類型)....
params 接受查詢結(jié)果的數(shù)組
注意
著色語言編譯優(yōu)化
如果你聲明了一個uniform卻在GLSL代碼中沒用過,編譯器會靜默移除這個變量,導(dǎo)致最后編譯出的版本中并不會包含它.
UBO限定符
在UBO中,針對不同的限定符 還存在不同的字節(jié)補齊的情況.所以獲取偏移量,大小最好還是通過查詢進行,避免自己計算出現(xiàn)錯誤.
這是 std140(標準統(tǒng)一變量塊布局)限定符的內(nèi)存分配情況:
其他的限定符 在我學了之后會補上~