在开始我们的学习之旅之前首先定义下什么是OpenGL。OpenGL主要被认为是一个API(anApplication Programming Interface:应用程序编程接口),它为我们提供了大量的功能,我们可以使用它来处理图形和图像。然而,OpenGL本身并不是一个API,只是一个规范,由Khronos组织开发和维护。
GLKViewController:UIViewController的子类,接收当视图需要重绘时的消息
GLKView:UIView的子类,简化了通过用Core Animation层来自动创建并管理帧缓存和渲染缓存共享内存所需要做的工作。
创建OpenGL ES上下文
创建一个GLKViewController,在ViewdidLoad生命周期中:
GLKView *view = (GLKView *)self.view;
//创建OpenGL ES2.0上下文
view.context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
//设置当前上下文
[EAGLContext setCurrentContext:view.context];
声明一个GLKBaseEffect属性
@property (nonatomic,strong)GLKBaseEffect *baseEffect;
并且在ViewDidLoad实例化
self.baseEffect = [[GLKBaseEffect alloc]init];
//使用静态颜色绘制
self.baseEffect.useConstantColor = GL_TRUE;
//设置默认绘制颜色,参数分别是 RGBA
self.baseEffect.constantColor = GLKVector4Make(1.0f, 1.0f, 1.0f, 1.0f);
//设置背景色为黑色
glClearColor(0.0f,0.0f,0.0f,1.0f);
我们需要绘制一个三角形自然需要三个顶点,OpenGL ES采用的笛卡尔坐标系
//顶点结构体
typedef struct{
GLKVector3 positionCoords;
}sceneVertex;
//三角形的三个顶点
static const sceneVertex vertices[] = {
{{-0.5f,-0.5f,0.0}},
{{0.5f,-0.5f,0.0}},
{{-0.5f,0.5f,0.0}},
};
- 生成缓存并且为缓存提供数据,这是最重要的一步
//声明缓存ID属性
@property (nonatomic,assign)GLuint *vertextBufferID;
//viewdidload中生成并绑定缓存数据
glGenBuffers(1, &vertextBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertextBufferID); //绑定指定标识符的缓存为当前缓存
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
- glGenBuffers申请一个标识符
- glBindBuffer 将标识符绑定到GL_ARRAY_BUFFER
- glBufferData复制顶点数据从CPU到GPU
接下来在GLKViewController的
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect
代理方法中
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
[self.baseEffect prepareToDraw];
//Clear Frame Buffer
glClear(GL_COLOR_BUFFER_BIT);
//开启缓存
glEnableVertexAttribArray(GLKVertexAttribPosition);
//设置缓存数据指针
glVertexAttribPointer(GLKVertexAttribPosition,
3,
GL_FLOAT,
GL_FALSE, //小数点固定数据是否被改变
sizeof(sceneVertex),
NULL); //从开始位置
//绘图
glDrawArrays(GL_TRIANGLES,
0,
3);
}
- glEnableVertexAttribArray 开启对应的顶点缓存属性
- glVertexAttribPointer 设置指针从顶点数组中读取数据
- glDrawArrays 绘制图形
- 释放缓存数据
在dealloc方法中释放掉缓存数据
- (void)dealloc{
GLKView *view = (GLKView *)self.view;
[EAGLContext setCurrentContext:view.context];
if ( 0 != vertextBufferID) {
glDeleteBuffers(1,
&vertextBufferID);
vertextBufferID = 0;
}
}
最后的运行结果图如下
[图片上传失败...(image-9af797-1523929667421)]
拓展小问题:1. 如何将背景色改成红色 2. 如何将三角形颜色改成黑色,而不是现在的白色
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect是GLKViewController系统给我们回调的绘制消息,该方法会一直被调用,和display方法一致
EAGLContext上下文本质上是个状态机,只有在当前上下文下,Opengl ES API调用才会生效
链接:https://www.jianshu.com/p/9c002f2583f6