- OpenGL ES(OpenGL for Embedded Systems)是以手持和嵌入式设备为目标的高级3D图形应用程序编程接口(API)。
- OpenGL ES是目前智能手机中占据统治地位的图形API,支持的平台包括:Andriod,BlackBerry,bada,Linux 和 Windows。
- OpenGL ES还是基于浏览器的3D图形Web标准WebGL的基础。
- OpenGL ES是OpenGL的简化版本,它消除了冗余功能,提供了一个既易于学习又易于在移动图形硬件中实现的库。
- OpenGL ES允许应用程序利用底层图形处理器的强大功能。
- iOS设备上的GPU可以执行复杂的2D、3D绘图,以及最终图像中每个像素的复杂着色计算。
OpenGL ES 客户端-服务器架构
苹果官方文档OpenGL ES as a Client-Server Architecture在下图中将OpenGL ES可视化为客户端-服务器架构。
- 应用程序向OpenGL ES客户端传递状态变化,纹理和顶点数据以及渲染命令。
- OpenGL ES客户端将此数据转换为图形硬件可以理解的格式,并将其转发给GPU。
- 由GPU对图形进行处理,如光栅化、显示等。
OpenGL ES图形管线
image.png- Application:提供原始的图元装配顶点信息,图片数据;
- Vertex:顶点着色器,用于处理图形变换,如平移、缩放、旋转;
- Geometry:图元装配,以及图形超出屏幕范围的裁剪处理;
- Fragment:片元着色器,纹理处理和雾化处理;
- Framebuffer Operations:帧缓冲区,完成颜色混合、深度测试等。
顶点着色器
顶点着色器实现了顶点操作的通用可编程方法。
顶点着色器程序是描述顶点上执行操作的顶点着色器程序代码/可执行文件。
顶点着色器输入输出
输入
- Attributes通道:输入顶点数据,提供每个顶点的数据。
- uniform通道:输入统一变量,即顶点着色器使用的不变的数据。
- 采样器:代表顶点着色器使用纹理的特殊统一变量类型。
输出
顶点着色器使用了2个内建变量接收最终处理结果的输出。
- gl_Position:经过处理后最终的顶点数据赋值给它。
- gl_PointSize:修改每个点大小后的最终值就赋值给它。一般情况下不对它进行赋值。
顶点着色器业务
- 矩阵变换位置
- 计算光照公式生成逐顶点颜色
- 生成/变换纹理坐标:片元着色器(下一节描述)是没有办法传递attributes,但是可以通过顶点着色器进行桥接,间接的将纹理坐标传递给片元着色器。
总结:它可以用于执行自定义计算,实施新的变换、照明或者传统的固定功能所不允许的基于顶点的效果。
顶点着色器GLSL代码示例
/*
GLSL定义变量的语法:
通道修饰符 类型 变量名
示例 attribute vec4 position;
*/
/*
attribute:通道修饰符,表示attribute通道
uniform:通道修饰符,表示uniform 通道
varying:通道修饰符,表示varying通道,通过varying可以传递纹理坐标,再经过顶点着色器的桥接将纹理坐标传递给片元着色器
vec4:四维向量
vec2:二维向量
mat4:4*4矩阵
lowp:低精度
*/
attribute vec4 position;
attribute vec2 textCoordinate;
uniform mat4 rotateMatrix;
varying lowp vec2 varyTextCoord;
void main()
{
//将纹理坐标传递给片元着色器
varyTextCoord = textCoordinate;
//定义一个临时的四维变量,并将当前顶点坐标赋值给它
vec4 vPos = position;
//将当前顶点进行旋转
vPos = vPos * rotateMatrix;
//将旋转后的顶点坐标赋值给gl_Position
gl_Position = vPos;
}
图元装配和光栅化
图元类型和顶点索引确定了被渲染的单独图元,对于每个单独图元及其对应的顶点,图元装配阶段执行的操作有:
- 将顶点着色器输出值执行裁剪
- 透视分割
- 视口变换后进入光栅化阶段
图元:点、线、三角形等。
图元装配:将顶点数据计算成一个一个图元,在这个阶段会进行裁剪、透视分割、viewport变换操作。
光栅化:将图元转化成一组二维片段的过程,而这些转化的片段将由片元着色器处理。这些二维片段就是屏幕上可绘制的像素。
片元着色器
片元着色器实现了片段操作的通用可编程方法。
片元着色器程序是描述片段上执行操作的片元着色器程序代码/可执行文件。
片元着色器输入输出
输入
- 由顶点着色器桥接过来的纹理坐标等。
- uniform通道:输入统一变量,即片元着色器使用的不变的数据。
- 采样器:代表片元着色器使用纹理的特殊统一变量类型。
输出
片元着色器使用了一个内建变量接收最终处理结果的输出。
- gl_FragColor:某个像素点通过片元着色器处理的最终结果赋值给它。
片元着色器业务
- 计算颜色
- 获取纹理值
- 往像素点中填充颜色值[纹理值/颜色值]。
总结:它可以用于图片/视频/图形每个像素的颜色填充,比如给视频添加滤镜,实际上就是将视频中每个图片的像素点颜色填充进行修改。
片元着色器GLSL代码示例
/*
varying:varying通道,由顶点着色器传递过来的纹理坐标
sampler2D:采样器类型
texture2D(采样器类型,纹理坐标):获取对应位置/坐标的颜色值的函数,简称获取纹素
gl_FragColor:内建变量,将最终的颜色值赋值给它
*/
//注意:此处必须和顶点着色器中一样,包括通道、精度、类型和变量名都要一致,否则无法传递纹理坐标
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main() {
gl_FragColor = texture2D(colorMap, varyTextCoord);
}
逐片段操作
这个过程是在GPU内部处理的,开发者一般不关心。
逐片段操作流程
- 像素归属测试:这个测试确定帧缓存区中位置 (Xw, Yw) 的像素目前是不是归 OpenGL ES 所有。例如,如果⼀个显示 OpenGL ES 帧缓存区窗口的窗口被另外一个窗口所遮蔽,则窗⼝系统可以确定被遮蔽的像素不属于 OpenGL ES 上下文。从⽽完全不显示这些像素。虽然像素归属测试是 OpenGL ES 的⼀部分,但它不由开发人员控制,⽽是在 OpenGL ES 内部进行。
- 裁剪测试:裁剪测试确定 (Xw, Yw) 是否位于作为 OpenGL ES 状态的一部分的裁剪矩形范围内。如果该⽚段位于裁剪区域之外,则被抛弃。
- 深度测试:输⼊片段的深度值比较,确定⽚段是否应该被拒绝。
- 混合:混合将新生成的⽚段颜⾊值与保存在帧缓冲区 (Xw, Yw) 位置的颜⾊值组合起来。
- 抖动:抖动可用于最⼩化,因为使用有限精度在帧缓存区中保存颜色⽽产生的伪像。
EGL(Embedded Graphics Library)
OpenGL ES命令需要渲染上下文和绘制表面才能完成图形图像的绘制。
- 渲染上下文:存储相关OpenGL ES状态。
- 绘制表面:是用于绘制图元的表面,它指定渲染所需要的缓冲区类型,例如:颜色缓冲区、深度缓冲区、模板缓冲区。
OpenGL ES API并没有提供如何创建渲染上下文或者上下文如何连接到原生窗口系统的函数,EGL是Khronos渲染API(如OpenGL ES)和原生窗口系统之间的接口。
唯一支持OpenGL ES却不支持EGL的平台是iOS,Apple提供自己的EGL API,称为EAGL。
因为每个窗口系统有着不同的定义,所以EGL提供基本的不透明类型-EGLDisplay。这个类型封装了所有系统相关的内容,用于与原生窗口系统建立连接。
网友评论