OpenGL ES
简介
OpenGL 是 GPU 驱动的一套标准接口,OpenGL ES 为嵌入式设备 GPU 驱动(如手机)的标准接口。2003年由包含Apple、Intel、AMD、Google、ARM、Qualcomm、Nvidia 等170 家企业组成的开源、非盈利的成员驱动型组织khronos 制定了OpenGL ES标准并维护。
OpenGL ES 是 OpenGL 的子集,专门为嵌入式设备设计。2003年OpenGL ES1.0支持固定管线,2007年2.0支持可编程管线。可编程管线的出现极大程度的增加开发人员的自由度,通过着色器的编写实现不同的业务需求和效果。
OpenGL ES相较于OpenGL做了许多删减,以下列举出部分不同点。
- 在OpenGL ES的世界里,没有四边形、多边形,无论多复杂的图形都是由点、线和三角形组成的;
- 没有glBegin/glEnd/glVertex,只能用glDrawArrays/glDraw;
- 没有double型数据类型,但加入了高性能的定点小数数据类型;
- 没有实时将非压缩图片数据转成压缩贴图(纹理)的功能,程序必须直接提供压缩好的贴图;
- 删除了很多功能:显示列表、求值器、索引色模式等等;
- glDrawArrays等函数中数据必须紧密排列,即间隔为 0;
- 各种数据的堆栈深度较低。
OpenGL使用场景
OpenGL广泛应用于各图像处理领域,包括音视频开发、动画开发(实现动画的绘制)、游戏开发(游戏的场景、人物的渲染)、地图开发、视频处理(视频滤镜开发)。
快速入门的学习步骤
- 了解OpenGL渲染管线流程,包括流程中的各个步骤;
- 尝试构建EGL或使用封装好的GLSurface进行代码编写;
- 学习使用VBO、VAO、EBO等优化程序;
- 进一步学习纹理相关知识,了解纹理映射和FBO;
- 坐标系统、矩阵变换;
- 案例实践。
渲染管线
什么是管线
在计算机图形学中,计算机图形管线(渲染管线 或简称 图形管线)是一个概念模型,它描述了图形系统将 3D场景渲染到2D屏幕所需执行的步骤。
下图给出的是OpenGL渲染管线流程。顶点数据通过顶点着色器的位置变换后进行图元装配和光栅化,通过片段着色器对纹理进行处理和逐片段的混合裁剪等操作,最后渲染到屏幕上。每个流程的步骤将在后续内容中进一步介绍。
顶点/片段着色器
着色器(Shader)是用来实现图像渲染的,用来替代固定渲染管线的可编辑程序。
顶点着色器(Vertex Shader)主要负责顶点的几何关系等的运算。
片段着色器(Vertex Shader)主要负责片源颜色等的计算。
顶点着色器
顶点坐标
纹理坐标
纹理坐标就是纹理与图形的映射关系,图形中每个顶点都会关联一个纹理坐标,表示顶点需要从该位置读取纹理图像的数据。-
采样器
在后续的纹理处理中会用到的特殊变量,比如在实现画笔时,可以将画笔粗细和画笔随机角度作为两个不同的采样器传入。
-
统一变量
顶点着色器中不变的数据,通常会传入旋转矩阵实现模型-视图-投影坐标的变换。
在编写着色器时需要关注以下几点:
- 纹理坐标的范围是 0 到 1 之间;
- 顶点坐标一般是用( x,y,z)描述,纹理坐标是用( s,t,r)描述;
- 常规情况下,纹理坐标默认左下角为(0,0),右上角为(1,1)。
通过上述提及的旋转矩阵,可以将顶点坐标与纹理坐标的映射进行更改,从而达到下图不同的显示效果。
更加详细的OpenGL ES着色器和程序内容可以查看该篇内容OpenGL ES 着色器与程序解析
图元装配
在经过顶点变换等操作后得到的顶点数据会经过图元进行装配,得到既定好的图形。
图元primitive,即图形元素,是可以编辑的最小图形单位。图元是图形软件用于操作和组织画面的最基本的素材。一幅画面由图元组成,图元是一组最简单的、最通用的几何图形或字符。
- GL_POINTS:把每一个顶点作为一个点进行处理,顶点n即定义了点n,共绘制n个点。
- GL_LINES:把每一个顶点作为一个独立的线段,顶点2n-1和2n之间共定义了n个线段,总共绘制N/2条线段。如果N为奇数,则忽略最后一个顶点。
- GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,总共绘制N-1条线段。
- GL_LINE_LOOP:绘制从定义第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点与第一个顶点相连。第n和n+1个顶点定义了线段n,然后最后一个线段是由顶点N和1之间定义,总共绘制N条线段。
- 把每三个顶点作为一个独立的三角形。顶点3n-2,3n-1和3n定义了第n个三角形,总共绘制N/3个三角形。
- 绘制一组相连的三角形。对于奇数点n,顶点n,n+1和n+2定义了第n个三角形;对于偶数n,顶点n+1,n和n+2定义了第n个三角形,总共绘制N-2个三角形。
- 绘制一组相连的三角形。三角形是由第一个顶点及其后给定的顶点所确定。顶点1,n+1和n+2定义了第n个三角形。总共绘制N-2个三角形。
光栅化
数据经过图元装配后得到许多个图形集合,每个图形会经过光栅化得到一点点的像素。
- 形状图元:确定图元包含哪些由整数坐标确定的“小方块”(和屏幕像素对应,现在还不能叫片段,光栅化完成后才能叫片段)
- 光栅化:确定这些小方块的Depth值和Color值(从图片顶点的Depth和Color插值得到),这些颜色后来可能被其他如纹理操作修改。
片段着色器
片段着色器会将顶点着色器中生成的插值数据进行输入,顶点着色器的输出通过图元装配后传递给片段着色器作为输入变量。详细内容同样在OpenGL ES 着色器与程序解析已详细介绍。
逐片段处理
逐片段处理中会可以对帧缓冲区中已有数据进行进一步处理,包括混合、裁剪等操作。
- 像素归属测试
用来确定帧缓冲区中位置(x,y)的像素是不是归当前上下文所有。例如,如果一个显示帧缓冲区窗口被另一个窗口所遮蔽,则窗口系统可以确定被遮蔽的像素不属于此opengl的上下文,从而不显示这些像素 - 混合
将新生成的片段颜色值与保存在帧缓冲区的颜色值组合起来,产生新的RGBA。详细的混合使用和计算内容在另一篇OpenGL混合使用、算法和计算已详细介绍。 - 剪裁测试
如果该片段位于剪裁区域外,则被抛弃(如:对某颜色进行裁剪,得到特定图案) - 抖动
颜色边缘的过渡柔和 - 模板和深度测试
若片段着色器返回的深度小于缓冲区中的深度,则舍弃 - 透明度测试
透明度测试
案例
通过上述介绍的流程,我们以下图为例简单概述下,具体使用场景可以是我们在触控屏的画板应用上进行绘画,类似与Procreate软件。
我们在画板上绘制一个房屋或一架飞机,绘制的线条可以看成是一个个点拼凑而成的。这些点就是顶点数据。顶点数据输入到顶点着色器中,通过变换矩阵正确转换成屏幕上的坐标,保证我们绘制的内容和呈现的内容不会出现偏差。有了顶点数据可以进行图元装配,得到多个飞机示例图右上角的三角形图元,通过光栅化和片段着色器处理进行纹理贴图等操作,最后显示在屏幕上。
总结
本部分内容的介绍能够帮助我们了解从基础数据到最终屏幕显示的整个渲染过程。高度自定义的部分包括着色器和逐片段的处理能够让开发者做许多原数据的后处理,比如图片视频滤镜、游戏场景渲染等。该部分内容也为后续的EGL构建、GLSL语言学习、纹理处理和实际案例编写打下基础。