OpenGL ES
什么是 OpenGL ES?
OpenGL ES(OpenGL for Embedded Systems)是 OpenGL 三维图形API的子集,针对手机、PDA和游戏主机等嵌入式设备而设计,各显卡制造商和系统制造商来实现这组 API。1
OpenGL 基本概念
因为 OpenGL ES 是 OpenGL 的一个子集,所以下面就主要介绍一些有关 OpenGL 的一些基本概念。
OpenGL 的结构可以从逻辑上划分为下面 3 个部分:
- 图元(Primitives)
- 缓冲区(Buffers)
- 光栅化(Rasterize)
图元(Primitives)
在 OpenGL 的世界里,我们只能画点、线、三角形这三种基本图形,而其它复杂的图形都可以通过三角形来组成。所以这里的图元指的就是这三种基础图形:
- 点:点存在于三维空间,坐标用(x,y,z)表示。
- 线:由两个三维空间中的点组成。
- 三角形:由三个三维空间的点组成。
缓冲区(Buffers)
OpenGL 中主要有 3 种 Buffer:
-
帧缓冲区(Frame Buffers) 帧缓冲区:这个是存储OpenGL 最终渲染输出结果的地方,它是一个包含多个图像的集合,例如颜色图像、深度图像、模板图像等。
-
渲染缓冲区(Render Buffers) 渲染缓冲区:渲染缓冲区就是一个图像,它是 Frame Buffer 的一个子集。
-
缓冲区对象(Buffer Objects) 缓冲区对象就是程序员输入到 OpenGL 的数据,分为结构类和索引类的。前者被称为“数组缓冲区对象”或“顶点缓冲区对象”(“Array Buffer Object”或“Vertex Buff er Object”),即用来描述模型的数组,如顶点数组、纹理数组等; 后者被称为“索引缓冲区对象”(“Index Buffer Object”),是对上述数组的索引。
光栅化(Rasterize)
在介绍光栅化之前,首先来补充 OpenGL 中的两个非常重要的概念:
- Vertex Vertex 就是图形中顶点,一系列的顶点就围成了一个图形。
- Fragment Fragment 是三维空间的点、线、三角形这些基本图元映射到二维平面上的映射区域,通常一个 Fragment 对应于屏幕上的一个像素,但高分辨率的屏幕可能会用多个像素点映射到一个 Fragment,以减少 GPU 的工作。
而光栅化是把点、线、三角形映射到屏幕上的像素点的过程。
着色器程序(Shader)
Shader 用来描述如何绘制(渲染),GLSL 是 OpenGL 的编程语言,全称 OpenGL Shader Language,它的语法类似于 C 语言。OpenGL 渲染需要两种 Shader:Vertex Shader 和 Fragment Shader。
- Vertex Shader Vertex Shader 对于3D模型网格的每个顶点执行一次,主要是确定该顶点的最终位置。
- Fragment Shader Fragment Shader对光栅化之后2D图像中的每个像素处理一次。3D物体的表面最终显示成什么样将由它决定,例如为模型的可见表面添加纹理,处理光照、阴影的影响等等。
OpenGL 流水线
OpenGL 中有两种流水线,一种是固定流水线,另外一种则是可编程流水线。
其中,OpenGL 1.0 版本支持固定流水线。其结构如下图所示:
从OpenGL 2.0版本开始,OpenGL支持可编程的流水线。也就是说,程序员可以通过Shader(一种程序)来控制GPU渲染的过程。
EGL
什么是 EGL?
EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现。EGL提供如下机制:
- 与设备的原生窗口系统通信
- 查询绘图表面的可用类型和配置
- 创建绘图表面
- 在OpenGL ES 和其他图形渲染API之间同步渲染
- 管理纹理贴图等渲染资源
为了让OpenGL ES能够绘制在当前设备上,我们需要EGL作为OpenGL ES与设备的桥梁。
使用 EGL 绘图的基本步骤
- Display(EGLDisplay) 是对实际显示设备的抽象。
- Surface(EGLSurface)是对用来存储图像的内存区域
- FrameBuffer 的抽象,包括 Color Buffer, Stencil Buffer ,Depth Buffer。Context (EGLContext) 存储 OpenGL ES绘图的一些状态信息。
使用EGL的绘图的一般步骤:
- 获取 EGL Display 对象:eglGetDisplay()
- 初始化与 EGLDisplay 之间的连接:eglInitialize()
- 获取 EGLConfig 对象:eglChooseConfig()
- 创建 EGLContext 实例:eglCreateContext()
- 创建 EGLSurface 实例:eglCreateWindowSurface()
- 连接 EGLContext 和 EGLSurface:eglMakeCurrent()
- 使用 OpenGL ES API 绘制图形:gl_*()
- 切换 front buffer 和 back buffer 送显:eglSwapBuffer()
- 断开并释放与 EGLSurface 关联的 EGLContext 对象:eglRelease()
- 删除 EGLSurface 对象
- 删除 EGLContext 对象
- 终止与 EGLDisplay 之间的连接
OpenGL ES 和 EGL 的联系
一个类比的例子
我们来思考一下画家绘画的过程:首先要有一名懂得各种绘画技艺的画家,然后他需要一张画布,一些笔,一些颜料,一些辅助工具(尺、模板、橡皮、调色板等等),然后他在画布上绘制第一幅画,完成之后展示给人们看;在人们观赏第一幅画的时候,他可以在第二张画布上绘制第二幅画,绘制完成后收回第一幅画,将第二幅画展现给人们看;接着使用工具擦除第一幅画,在同一张画布上绘制第三幅画;周而复始,人们便看到了一幅接一幅的画。
对比 OpenGL ES/EGL,各要素的对应关系大体如下:
- 画家:编程人员
- 笔、颜料、辅助工具:OpenGL ES API
- 画布:EGL 创建的 Surface
所以计算机绘画的本质就是选择图像显示的像素格式,申请一块内存(画布),填充像素(颜色),绘制完成之后,通知计算机显示到屏幕上(按比例发射RGB光),最终就看到了所绘制的画面。之所以要先选择像素格式,是因为无论是所申请内存的大小,还是硬件驱动解析这块内存的方式,都是由像素格式决定的。
参考资料
- EGL 的官方介绍说明
- Understaing Android EGL
- 安卓 OpenGL ES 2.0 完全入门(一):基本概念和 hello world
- EGL 参考资料1: 学习OpenGL-ES: 1 - 像素、颜色、显存、初始化
- EGL 参考资料2: 学习OpenGL-ES: 2 - EGL解析
- OpenGL ES 2.0 编程三步曲
- OpenGL 参考资料1: 学习OpenGL-ES: 3 - 3D绘图原理
- Android OpenGL ES 离屏渲染(offscreen render)
- OpenGL基本概念
- All about OpenGL ES 2.x - (part 1/3)
- All about OpenGL ES 2.x - (part 2/3)
- All about OpenGL ES 2.x - (part 3/3)
- 关于EGL
-
https://zh.wikipedia.org/wiki/OpenGL_ES ↩
Tags: Android, Graphic, OpenGLES, EGL
Subscribe via RSS