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];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,976评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,249评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,449评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,433评论 1 296
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,460评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,132评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,721评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,641评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,180评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,267评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,408评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,076评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,767评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,255评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,386评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,764评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,413评论 2 358