一、创建与编译一个着色器的API参照
1. 创建一个shader(根据type类型)GLuint glCreateShader(GLenum type);
type
— 创建着色器的类型,GL_VERTEX_SHADER
或者GL_FRAGMENT_SHADER
返回值 — 是指向新着⾊器对象的句柄.可以调用glDeleteShader
删除
2. 将着色器源码附加到着色器对象上void glShaderSource(GLuint shader , GLSizei count ,const GLChar * const *string, const GLint *length);
shader
— 指向着色器对象的句柄
count
— 着⾊器源字符串的数量,着⾊器可以由多个源字符串组成,但是每个着⾊器只有一个main函数
string
— 指向保存数量的count 的着⾊器源字符串的数组指针
length
— 指向保存每个着色器字符串大小且元素数量为count 的整数组指针
3. 把着色器源代码编译成目标代码void glCompileShader(GLuint shader);
shader — 需要编译的着⾊器对象句柄
4. 释放不需要的shadevoid glDeleteShader(GLuint shader);
shader
— 要删除的着色器对象句柄
5. others
void glGetShaderiv(GLuint shader , GLenum pname , GLint *params );
shader
— 需要编译的着色器对象句柄
pname
— 获取的信息参数,可以为 GL_COMPILE_STATUS/GL_DELETE_STATUS/ GL_INFO_LOG_LENGTH/GL_SHADER_SOURCE_LENGTH/ GL_SHADER_TYPE
params
— 指向查询结果的整数存储位置的指针.
void glGetShaderInfolog(GLuint shader , GLSizei maxLength, GLSizei *length , GLChar *infoLog);
shader
— 需要获取信息日志的着⾊器对象句柄
maxLength
— 保存信息日志的缓存区⼤小
length
— 写⼊的信息日志的⻓度(减去null 终⽌符); 如果不需要知道长度. 这个参数可以为
Null infoLog
— 指向保存信息日志的字符缓存区的指针
二、创建与链接程序API参照
创建⼀个程序对象
GLUint glCreateProgram( )
返回值: 返回一个执行新程序对象的句柄
void glDeleteProgram( GLuint program )
program : 指向需要删除的程序对象句柄
着⾊器与程序连接/附着
void glAttachShader( GLuint program , GLuint shader );
program : 指向程序对象的句柄
shader : 指向程序连接的着⾊器对象的句柄
链接
glLinkProgram(GLuint program);
链接之后获取链接状态
void glGetProgramiv (GLuint program,GLenum pname, GLint *params);
断开连接
void glDetachShader(GLuint program);
program : 指向程序对象的句柄
shader : 指向程序断开连接的着色器对象句柄
从程序信息⽇志中获取信息
void glGetPorgramInfoLog( GLuint program ,GLSizei maxLength, GLSizei *length , GLChar *infoLog )
三、顶点着⾊程序与片元着色程序如何实现编译、绑定和连接的?
1.读取顶点着色程序、片元着色程序 -> 2.加载shader(封装为函数) -> 3. 链接
1. 读取顶点着色器、片元着色器程序
NSString *vertFile = [[NSBundle mainBundle]pathForResource:@"shaderv" ofType:@"vsh"];
NSString *fragFile = [[NSBundle mainBundle]pathForResource:@"shaderf" ofType:@"fsh"];
2. 加载shader
//加载shader
-(GLuint)loadShaders:(NSString *)vert Withfrag:(NSString *)frag
{
//1.定义2个零时着色器对象
GLuint verShader, fragShader;
//创建program
GLint program = glCreateProgram();
//2.编译顶点着色程序、片元着色器程序
//参数1:编译完存储的底层地址
//参数2:编译的类型,GL_VERTEX_SHADER(顶点)、GL_FRAGMENT_SHADER(片元)
//参数3:文件路径
[self compileShader:&verShader type:GL_VERTEX_SHADER file:vert];
[self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:frag];
//3.创建最终的程序
glAttachShader(program, verShader);
glAttachShader(program, fragShader);
//4.释放不需要的shader
glDeleteShader(verShader);
glDeleteShader(fragShader);
return program;
}
//编译shader
- (void)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file{
//1.读取文件路径字符串
NSString* content = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];
const GLchar* source = (GLchar *)[content UTF8String];
//2.创建一个shader(根据type类型)
*shader = glCreateShader(type);
//3.将着色器源码附加到着色器对象上。
//参数1:shader,要编译的着色器对象 *shader
//参数2:numOfStrings,传递的源码字符串数量 1个
//参数3:strings,着色器程序的源码(真正的着色器程序源码)
//参数4:lenOfStrings,长度,具有每个字符串长度的数组,或NULL,这意味着字符串是NULL终止的
glShaderSource(*shader, 1, &source,NULL);
//4.把着色器源代码编译成目标代码
glCompileShader(*shader);
}
3.链接
//4.链接
glLinkProgram(self.myPrograme);
GLint linkStatus;
//获取链接状态
glGetProgramiv(self.myPrograme, GL_LINK_STATUS, &linkStatus);
if (linkStatus == GL_FALSE) {
GLchar message[512];
glGetProgramInfoLog(self.myPrograme, sizeof(message), 0, &message[0]);
NSString *messageString = [NSString stringWithUTF8String:message];
NSLog(@"Program Link Error:%@",messageString);
return;
}
NSLog(@"Program Link Success!");
//5.使用program
glUseProgram(self.myPrograme);