学习是一件开心的额事情
演示图
你不知道这个东西,请不要看了,请看我的其他文章先了解一下O!
掌握着色器程序的执行过程
<code>
uniform float t; // 时间
uniform mat4 gl_ModelViewMatrix; // 模型视图矩阵
attribute vec4 vel;
const vec4 g = vec4(0.0,-9.8,0.0) // 重力加速度
void main()
{
vec4 position = vel;
position += t*vel + t*t*g;
gl_Position = gl_ModelViewMatrix * position;
}
</code>
稍微解释一下:代码的作用是模拟重力加速度,对一个点的位置进行变换.
先上图
着色器创建流程
C语言,大家应该很熟悉吧! C 语言的编译过程步骤:
1.编译器检查错误
2.将他转换成目标代码(.o文件)
3.将一组目标文件进行链接,最后成为一个可执行文件
在OpenGL 程序中使用GLSL 着色器也是一个相似的过程,要在应用程序中使用顶点或者片段着色器需要按照顺序执行下面的步骤:
1.创建着色器对象
2.把着色器代码编译成源代码
3.验证是否着色器是否编译成功
为了把多个着色器对象链接起来,我们需要创建着色器程序
4.创建一个着色器程序
5.把着色器对象链接到这个着色器程序中
6.链接着色器
7.验证着色器链接阶段已经成功完成.
8.使用着色器进行顶点或者片段处理.
<code>
- (BOOL)loadShaders
{
// 第一步.创建标示
GLuint vertShader, fragShader;
// 第二步.获取文件路径
NSString *vertShaderPathname, *fragShaderPathname;
vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
NSLog(@"编译失败 vertex shader");
return NO;
}
// 创建 编译 片断着色器对象
fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
NSLog(@"Failed to compile fragment shader");
return NO;
}
// 第八步 创建一个着色器空程序
_program = glCreateProgram();
// 第九步 将顶点着色器链接到程序中
glAttachShader(_program, vertShader);
// 将片断着色器链接到程序中
glAttachShader(_program, fragShader);
//第十步 绑定着色器的属性
glBindAttribLocation(_program, GLKVertexAttribPosition, "position");
glBindAttribLocation(_program, GLKVertexAttribNormal, "normal");
if (![self linkProgram:_program]) {
NSLog(@"Failed to link program: %d", _program);
if (vertShader) {
glDeleteShader(vertShader);
vertShader = 0;
}
if (fragShader) {
glDeleteShader(fragShader);
fragShader = 0;
}
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
return NO;
}
// Get uniform locations.
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix");
// 第十三步 . 分离释放顶点着色器对象 和片段着色器对象
if (vertShader) {
glDetachShader(_program, vertShader);
glDeleteShader(vertShader);
}
if (fragShader) {
glDetachShader(_program, fragShader);
glDeleteShader(fragShader);
}
return YES;
}
-(BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
{
//第三步 获取文件的内容 并进行NSUTF8StringEncoding 编码
const GLchar *source;
source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
if (!source) {
NSLog(@"Failed to load vertex shader");
return NO;
}
//第四步 根据类型创建着色器对象
*shader = glCreateShader(type);
//第五步. 获取着色器源代码和着色器关联
glShaderSource(*shader, 1, &source, NULL);
//第六步. 开始编译着色器源代码
glCompileShader(*shader);
#if defined(DEBUG)
GLint logLength;
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(*shader, logLength, &logLength, log);
NSLog(@"Shader compile log:\n%s", log);
free(log);
}
#endif
//第七步. 查看是着色器源代码否编译成功
GLint status;
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
if (status == 0) {
glDeleteShader(*shader);
return NO;
}
return YES;
}
- (BOOL)linkProgram:(GLuint)prog
{
// 第十一 链接程序
glLinkProgram(prog);
#if defined(DEBUG)
GLint logLength;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
NSLog(@"Program link log:\n%s", log);
free(log);
}
#endif
// 第十二步 检查着色器程序链接结果
GLint status;
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if (status == 0) {
return NO;
}
</code>
OpenGL 编程指南>