簡述 GLProgram是GPUImage中代表openGL ES 中的program,具有glprogram功能。其實是作者對OpenGL ES program的面向對象封裝 初始化 program shader c語言編譯流程:預編譯、編譯、彙編、鏈接 glsl的編譯過程類似c語言,主要有glC ...
簡述
GLProgram是GPUImage中代表openGL ES 中的program,具有glprogram功能。其實是作者對OpenGL ES program的面向對象封裝
初始化
- (id)initWithVertexShaderString:(NSString *)vShaderString
fragmentShaderString:(NSString *)fShaderString;
- (id)initWithVertexShaderString:(NSString *)vShaderString
fragmentShaderFilename:(NSString *)fShaderFilename;
- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename
fragmentShaderFilename:(NSString *)fShaderFilename;
program
program = glCreateProgram();
shader
c語言編譯流程:預編譯、編譯、彙編、鏈接
glsl的編譯過程類似c語言,主要有glCompileShader、glAttachShader、glLinkProgram三步
創建shader
分別根據兩個Shader String來創建兩個Shader。但是要註意區別的是,兩個Shader的type對應的GLEnum是不一樣的。
創建並且compile shader的過程包括幾步:
- 創建OpenGL ES Shader:VertexShader的type是GL_VERTEX_SHADER;而FragmentShader是GL_FRAGMENT_SHADER。
shader = glCreateShader(type);
- 載入Source String:
source = (GLchar *)[shaderString UTF8String];
glShaderSource(*shader, 1, &source, NULL);
- 編譯Shader:
glCompileShader(*shader);
- 檢查Shader的狀態;如果創建失敗,則獲取log:
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) {
GLint logLength;
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(*shader, logLength, &logLength, log);
if (shader == &vertShader)
{
self.vertexShaderLog = [NSString stringWithFormat:@"%s", log];
}
else
{
self.fragmentShaderLog = [NSString stringWithFormat:@"%s", log];
}
free(log);
}
}
- 將生成的兩個Shader Attach到Program上:
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
- link program並且檢查program的狀態,如果link失敗,則獲取log;如果link成功,則表示GLProgram的初始化完畢:
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
return NO;
if (vertShader)
{
glDeleteShader(vertShader);
vertShader = 0;
}
if (fragShader)
{
glDeleteShader(fragShader);
fragShader = 0;
}
self.initialized = YES;
- use
glUseProgram(program);
Attribute的管理
簡介
attribute變數是只能在vertex shader中使用的變數。它不能在fragment shader中聲明attribute變數,也不能被fragment shader中使用)
在application中,一般用函數glBindAttribLocation()來綁定每個attribute變數的位置,然後用函數glVertexAttribPointer()為每個attribute變數賦值。
在GPUImage中,作者通過一個attributes數組來管理attribute變數。
- (void)addAttribute:(NSString *)attributeName
{
if (![attributes containsObject:attributeName])
{
[attributes addObject:attributeName];
glBindAttribLocation(program,
(GLuint)[attributes indexOfObject:attributeName],
[attributeName UTF8String]);
}
}
// END:addattribute
// START:indexmethods
- (GLuint)attributeIndex:(NSString *)attributeName
{
return (GLuint)[attributes indexOfObject:attributeName];
}
如上述函數所示,每當加入一個attribute時,會先判斷在數組中有沒有這個變數,如果沒有的話,就加到數組中,並且綁定到shader中。變數獲取的位置也就是在數組中的位置
uniform的管理
簡介
uniform變數 外部程式傳遞給shader的變數.
函數glUniform**()函數賦值的.shader 中是只讀變數,不能被 shader 修改.
在GPUImage中,作者同樣通過一個uniforms數組來管理attribute變數。(然而並沒有用到