OpenGL ES(一)----基本概念与简单使用

OpenGL ES基本概念

CPU和GPU各自有着专门为其分配的内存空间,渲染图形的速度绝大部分取决于这两部分内存的交互。OpenGL ES是一种软件技术,用于协调这两部分内存区域之间的数据交换。

缓存

缓存是为CPU与GPU的内存区域交换数据产生的。CPU内存中的数据复制到缓存中后,CPU一般不会再访问这个缓存,GPU会独占缓存,有效的读写内存。几乎所有GPU数据都应该放入缓存中。

为缓存提供数据步骤如图:
WX20190801-202720.png

具体C语言函数:

  1. glGenBuffers():为缓存生成一个独一无二的标识符;
  2. glBindBuffer():绑定缓存,接下来的运算将要使用这个;
  3. glBufferData()或glBufferSubData():为缓存分配内存,并复制数据到其中
  4. glEnableVertexAttribArray()或glDisableVertexAttribArray():告诉OpenGL ES在接下来的渲染中是否使用缓存中的数据
  5. glVertexAttribPointer():告诉OpenGL ES在缓存中的数据类型和所有需要访问的数据内存偏移值
  6. glDrawArrays():使用当前绑定并启用的缓存数据执行绘图
  7. glDeleteBuffers ():删除缓存并释放相关的资源

3D坐标系

左右为X轴,上下为Y轴,前后为Z轴


image.png

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}}, // 左上点
    
    {{ 0.5f, -0.5f, 0.0}}, // 右下点
    {{-0.5f,  0.5f, 0.0}}, // 左上点
    {{0.5f,  0.5f, 0.0}}   // 右上点
};

创建GLKViewController子类,生成EAGLContext实例,并将其设为当前上下文,初始化GLKBaseEffect,配置OpenGL缓存信息。点击GLKViewController 查看该类更多信息。

// 视频将要加载
- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    // CLKit 为简化iOS中OpenGL ES的使用提供类和函数
    // 获取GLKView对象,GLKView简化了通过用Core Animation层来自动创建并管理帧缓存和渲染缓存共享内存所需要做的工作。
    GLKView *view = (GLKView *)self.view;
    NSAssert([view isKindOfClass:[GLKView class]], @"View controller's view is not a GLKView");
    
    // 初始化EAGLContext实例,并指定OpenGL ES版本为2.0
    // 这个实例会封装一个特定于某个平台的OpenGL ES上下文
    view.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    
    // 设置当前上下文
    // (一个应用可以使用多个上下文,所有的的OpenGL ES操作都是针对当前上下文的,不重新设置的话,会在原来的上下文中操作)
    [EAGLContext setCurrentContext:view.context];
    
    // 初始化GLKBaseEffect实例,简化OpenGL ES的常用操作
    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);
    
    // 1.为缓存生成一个独一无二的标识符
    glGenBuffers(1, &vertexBufferID);
    // 2.绑定缓存,接下来的运算将要使用这个
    // 第一个参数:指定要绑定哪一种类型的缓存,GL_ARRAY_BUFFER类型代表指定一个顶点数组
    // 第二个参数:标识ID
    glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
    // 3.为缓存分配内存,并复制数据到其中
    glBufferData(GL_ARRAY_BUFFER,  // 指定要绑定哪一种类型的缓存
                 sizeof(vertices), // 数据字节数
                 vertices,         // 被复制数据的地址
                 GL_STATIC_DRAW);  // 缓存在未来将会被怎么使用
    // GL_STATIC_DRAW:缓存中的内容很少被修改,适合复制到GPU控制的内存
    // GL_DYNAMIC_DRAW:缓存中的内容会频繁改变
}

绘制图片

// 已经准备好当前OpenGL ES的上下文,可以开始绘图
// 该方法的语义与drawRect:方法相同,用来绘制view的内容的
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    
    // 开始绘图
    [self.baseEffect prepareToDraw];
    // 开始清除颜色,前面有用glClearColor设置过
    glClear(GL_COLOR_BUFFER_BIT);
    
    // 4.告诉OpenGL ES在接下来的渲染中使用缓存中的数据
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    // 5.告诉OpenGL ES在缓存中的数据类型和所有需要访问的数据内存偏移值
    glVertexAttribPointer(GLKVertexAttribPosition,
                          3,                   // 每个位置有3部分
                          GL_FLOAT,            // 每个部分都是一个浮点型的值
                          GL_FALSE,            // 小数点固定数据是否可以改变,使用可节省内存,不使用可减少GPU运算且提高精度,
                          sizeof(SceneVertex), // 步幅,每个顶点的保存需要多少字节
                          NULL);               // OpenGL ES可以从当前绑定的顶点缓存的开始位置访问顶点数据
    // 6.使用当前绑定并启用的缓存数据执行绘图
    glDrawArrays(GL_TRIANGLES,  //怎么处理在绑定的顶点缓存内的顶点数据(这里是渲染三角形)
                 0,  // 第一个顶点的位置
                 6); // 需要渲染的顶点数量
}

清空数据

// 控制器要销毁时,清空数据
- (void)dealloc {
    
    GLKView *view = (GLKView *)self.view;
    [EAGLContext setCurrentContext:view.context];
    // 避免缓存已被删除
    if (0 != vertexBufferID) {
        // 7.删除缓存并释放相关的资源
        glDeleteBuffers (1, &vertexBufferID);
        vertexBufferID = 0;
    }
    ((GLKView *)self.view).context = nil;
    [EAGLContext setCurrentContext:nil];
}

你可能感兴趣的:(OpenGL ES(一)----基本概念与简单使用)