从零开始学习OpenGL ES(1)--基础概念

这篇文章主要学习,如何用OpenGL ES来渲染一张图片。

准备资料

OpenGL(Open Graphics Library) 是 Khronos Group (一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准)开发维护的一个规范,它是硬件无关的。它主要为我们定义了用来操作图形和图片的一系列函数的 API,OpenGL 本身并非 API。

OpenGL ES(OpenGL for Embedded Systems) 是 OpenGL 的子集,针对手机、PDA 和游戏主机等嵌入式设备而设计。该规范也是由 Khronos Group 开发维护。

OpenGL ES 去除了四边形(GL_QUADS)、多边形(GL_POLYGONS) 等复杂图元,以及许多非绝对必要的特性,剩下最核心有用的部分。可以理解成是一个在移动平台上能够支持 OpenGL 最基本功能的精简规范

一、基本概念

1. 缓存


OpenGL ES一部分运行在CPU上, 一部分运行在GPU上, 为了协调这两部分的数据交换, 定义了Buffers(缓存)的概念. CPU和GPU都有独自控制的内存区域, 缓存可以避免数据在这两块区域之间进行复制, 提高效率

2. 纹理、渲染和纹理渲染


纹理是一个用来保存图像颜色的元素值的缓存,
渲染是指将数据生成图像的过程;
纹理渲染就是将保存在内存中的颜色值等数据, 生成图像的过程

3. 坐标系


3.1 OpenGL ES中的坐标系

OpenGL ES中的坐标系

OpenGL ES中的坐标系是一个三维坐标系, 用x,y,z来表示, 坐标系的范围是-1~1.
z轴的正方向指向屏幕外. 如果不考虑z轴, 左下角坐标应该为(-1, -1, 0), 右上角坐标为(1,1,0).

3.2 纹理坐标系

纹理坐标系

纹理坐标系是一个二维坐标系,用s,t轴来表示, t轴为数轴., s轴为横轴 范围是0~1.
在坐标系中, 点的横坐标一般用u来表示, 点的纵坐标一般用v来表示. 左下角坐标为(0, 0), 右上角坐标为(1, 1). 在UIKit中, 左下角为(0, 1), 右上角为(1. 0)

4. 纹理的相关概念


  • 纹理元素(Texel) : 简称纹素. 当一个图像初始化为一个纹理缓存后, 每个像素会变成一个纹素, 纹理的坐标范围是0~1, 在这个单位长度内, 可能包含任意多个纹素.

  • 片段(Fragment) : 视口坐标中的颜色像素. 没有使用纹理时, 会使用对象顶点来计算片段的颜色; 使用纹理时, 会根据纹素来计算.

  • 光栅化(Rasterizing) : 将几何形状数据转换为片段的步骤.

  • 映射(Mapping) : 对齐顶点和纹素的方式. 即将顶点坐标(x,y,z)和纹理坐标(u,v)对应起来.

  • 取样(Sampling) : 在顶点固定后, 每个片段根据计算出来的(u, v)坐标, 去找相应的纹素的过程.

  • 帧缓存(Frame Buffer) : 一个接收渲染结果的缓冲区, 为GPU指定存储渲染结果的区域.

5. 缓存的使用

在实际应用中, 我们需要用到各种缓存. 例如, 在纹理渲染之前, 会将图像的数据初始化为一块纹理缓存. 这块缓存保存了图像的数据.

使用缓存可分为以下步骤:

    1. 生成(Generate) : 生成缓存标识符, 函数: glGenBuffers().
    1. 绑定(Bind) : 为接下来的操作, 绑定一个缓存. 函数: glBindBuffer().
    1. 缓存数据(Buffer Data): 从CPU的内存复制数据到缓存的内存中. 函数: glBufferData() / glBufferSubData().
    1. 启用(Enable) / 禁用(Disable) : 设置在接下来的渲染中是否使用缓存的数据. 函数: glEnableVertexAttribArray() / glDisableVertexAttribArray().
    1. 设置指针(Set Pointers) : 告知缓存的数据类型, 以及相应数据的偏移量. 函数: glVertexAttribPointer().
    1. 绘图(Draw) : 使用缓存的数据进行绘制. 函数: glDrawArrays() / glDrawElements().
    1. 删除(Delete) : 清空缓存, 释放内存. 函数:glDeleteBuffers().

6. OpenGL ES上下文

OpenGL ES 是一个状态机, 相关的配置信息会保存在一个上下文(context)当中. 这些值会被一直保存, 直到被修改.
我们也可以配置多个context, 通过调用[EAGLContext setCurrentContext:context]来进行切换当前context.

7. OpenGL ES 中的图元

图元(Primitive) 是指 OpenGL ES 中支持渲染的基本图形. OpenGL ES 只支持三种基本图形: 顶点, 线段三角形. 复杂的图形需要通过渲染多个三角形来实现.

8. 如何去渲染三角形?

OpenGL ES渲染三角形的流程

渲染流程如上图. 在流程中, 顶点着色器片段着色器都是可编程的部分. 着色器(Shader) 也是一个程序, 它们运行在GPU上, 在主程序运行的时候, 进行动态编,不用写死在代码中. 编写着色器的语言是GLSL(OpenGL Shading Language) .

下面具体分析一下, 途中流程每一步都做了什么:

8.1 顶点数据

为了渲染一个三角形, 我们需要传入一个包含3个三维顶点坐标数组.
每个顶点都有对应的顶点属性, 顶点属性中可以包含任何我们想要的数据.

为了让OpenGL ES知道我们需要绘制的是一个三角形, 而不是顶点或者线段, 我们需要在调用绘制(Draw)指令的时候, 将图元信息传递给OpenGL ES

8.2 顶点着色器

顶点着色器是运行在GPU上的一个程序, 它会对每个顶点执行一次运算. 它可以使用顶点数据来计算该顶点的颜色, 光照, 纹理, 左边等
顶点着色器的一个重要任务是进行坐标转换. 例如将模型的原始坐标系(一般为三维坐标系)转换为屏幕坐标系

8.3 形状(图元)装配

在顶点着色器输出顶点坐标后, 各个顶点按照绘制命令中的图元信息参数, 以及顶点索引数组, 被组装成一个个图元

通过这一步, 模型中的3D图元已经被转换成屏幕上的2D图元.

8.4 几何着色器

在OpenGL的版本中, 顶点着色器和片段着色器中间, 还有一个可选的着色器, 叫做几何着色器(Geometry Shader).
几何着色器将图元形式的一系列顶点的集合作为输入, 它可以通过产生新的顶点来构造出新的图元, 从而生成其他的形状.

OpenGL ES 目前不支持几何着色器.

8.5 光栅化

在光栅化阶段, 基本图元被转换成供片段着色器使用的片段.
片段表示可以被渲染到屏幕上的像素, 它包含位置, 颜色值, 纹理坐标等信息. 这些是由图元的顶点信息进行插值计算得到的.

在片段着色器运行之前会进行裁剪, 处于视图以外的部分会被裁剪掉, 用来提升执行效率.

8.6 片段着色器

片段着色器的主要作用是计算每一个片段最终的颜色值(或者是否被丢弃), 片段着色器决定了最终屏幕上每一个像素点的颜色值.

8.7 测试与混合

在这一步, OpenGL ES 会根据片段是否被遮挡, 视图上是否已存在绘制好的片段等情况, 对片段进行混合或者丢弃.
最终保留下来的片段会被写入帧缓存(Frame Buffer), 呈现在屏幕上.

9. 如何渲染多边形?

多边形

如图所示,一个五边形. 由于OpenGL ES 只能渲染三角形, 所以我们可以把它拆分成 3 个三角形来渲染。

渲染一个三角形,我们需要一个保存 3 个顶点的数组。这意味着我们渲染一个五边形,需要用 9 个顶点。而且我们可以看到,其中 V0 、 V2 、V3 都是重复的顶点,显得有点冗余。

那么我们想复用这些重复的顶点, OpenGL ES 有没有提供方法呢?
有的.
OpenGL ES中, 对于三角形有三种渲染方式, 在给定的顶点数组相同的情况下, 我们可以指定我们想要的连接方式, 如下图所示:


三角形的三种连接方式
9.1 GL_TRIANGLES

GL_TRIANGLES就是没有复用顶点的方式, 以每个顶点绘制一个三角形, 第一个三角形使用 V0 、 V1 、V2 ,第二个使用 V3 、 V4 、V5 ,以此类推. 如果顶点的个数不是 3 的倍数,那么最后的 1 个或者 2 个顶点会被舍弃.

9.2 GL_TRIANGLES_STRIP

GL_TRIANGLES_STRIP 在绘制三角形的时候,会复用前两个顶点。第一个三角形依然使用 V0 、 V1 、V2 ,第二个则会使用 V1 、 V2 、V3,以此类推。第 n 个会使用 V(n-1) 、 V(n) 、V(n+1) .

9.3 GL_TRIANGLES_FAN

GL_TRIANGLES_FAN 在绘制三角形的时候,会复用第一个顶点和前一个顶点。第一个三角形依然使用 V0 、 V1 、V2 ,第二个则会使用 V0 、 V2 、V3,以此类推. 第 n 个会使用 V0 、 V(n) 、V(n+1) 。这种方式看上去像是在绕着 V0 画扇形.

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