正文
3、配置program。注意不要马上链接program。
GLuint vertShader, fragShader;
NSString *vertShaderPathname, *fragShaderPathname;
// Create shader program.
_program = glCreateProgram();
// Create and compile vertex shader.
vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
NSLog(@"Failed to compile vertex shader");
return NO;
}
// Create and compile fragment shader.
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;
}
// Attach vertex shader to program.
glAttachShader(_program, vertShader);
// Attach fragment shader to program.
glAttachShader(_program, fragShader);
4、在链接program前配置transform feedback输出属性名。
仔细观察,本文使用的Vertex Shader与正常绘图所用的着色器略有区别:没输出顶点坐标给Fragment Shader使用。因此,需要glTransformFeedbackVaryings告诉ES欲捕获到输出缓冲区的属性属性。
GLchar *varyings[] = {"outValue"};
glTransformFeedbackVaryings(_program, sizeof(varyings) / sizeof(varyings[0]), varyings, GL_INTERLEAVED_ATTRIBS);
glTransformFeedbackVaryings需要输出变量的数量及名称,在varyings数组指定Vertex Shader将输出的属性名。
5、链接program。链接操作包含检查链接状态(glLinkProgram),查找编译错误,在调试模式下还可验证当前ES状态是否可执行program中的程序(glValidateProgram),即找出其中运行时错误,根据校验情况,输出错误信息。glValidateProgram操作消耗资源较多,Release模式下通常不调用此函数。示例如下。
// 1、检查链接状态
glLinkProgram(_program);
GLint linkStatus = GL_FALSE;
glGetProgramiv(_program, GL_LINK_STATUS, &linkStatus);if (linkStatus == GL_FALSE) {
GLint logLength = 0;
glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) {
GLchar *logBuffer = calloc(1, logLength);
glGetProgramInfoLog(_program, logLength, NULL, logBuffer); printf("%s", logBuffer);
free(logBuffer);
}
}
// 2、验证Shader是否可执行
glValidateProgram(_program);
glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &logLength);if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(_program, logLength, &logLength, log);
NSLog(@"Program validate log:\n%s", log);
free(log);
}
glGetProgramiv(_program, GL_VALIDATE_STATUS, &status);if (status == 0) { return NO;
}return YES;
6、配置GPU的输入数据缓冲区。
这里需要注意,若直接上传数据,则不能映射上传缓冲区到主存去查看上传的数据。用缓冲区(Vertex Buffer Object)则正常。
使用VBO前,可以配置VAO,不配置也不影响运行结果。
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
上传数据方式A、直接上传数据至GPU的实现,yourData为数组。
GLfloat yourData[] = {2, 3, 4, 5, 6};