OpenGL ES
OpenGL ESOpenGL for Embedded Systems
是OpenGL的简化版本(OpenGL的子集),它消除了冗余功能(移动端用不到的),提供了一个既易于学习又更易于在移动图形硬件中实现的库.它是以手持和嵌入式为目标
的高级3D图形应用程序编程接口API,是目前智能手机中占据统治地位的图形API,支持的平台:iOS,Andriod,BlackBerry,Linux,Windows.
OpenGL ES所实现的跨平台,并不是说iOS、Andriod共用一个窗口,因为OpenGL ES只是一套接口API. 所以无论是iOS、Andriod都需要自己去给OpenGL ES提供载体.iOS中要使用OpenGL ES需要用的是GLKit库,由此作为OpenGL ES的载体
GLView,GLViewController
.跨平台的部分指的是GLSL所编写的顶点着色器、片元着色器的代码片段
OpenGL ES作为客户端-服务端体系结构
应用程序将
状态更改,纹理和顶点数据以及渲染命令
传达给OpenGL ES客户端。客户端将此数据 转换为图形硬件可以理解的格式
,并将其转发给GPU,GPU调用图形硬件,处理图形数据,例如光栅化等
- CPU
1.app代码通过OpenGL ES API,调用OpenGL ES framework
2.OpenGL ES framework 将图形数据传递给OpenGL ES Server
- GPU
1.图形硬件处理图形数据,光栅化,渲染显示
OpenGL ES图形管线
- 从API拿到顶点数据,从内存Copy到顶点缓存区中
- 将顶点缓存区中的顶点数据传递给顶点着色器,纹理坐标也需要传递给顶点着色器,通过
绘制连接方式
进行图元装配,然后顶点就会被确定为是什么样的图形.绘制方式见OpenGL渲染正方形&平移 - 光栅化步骤确定了图形对应在屏幕的位置
- 片元着色器用于处理图形像素的颜色值,将处理好的颜色值存储在帧缓存区,用于显示器显示
由上图可以看到,我们能够通过API操作的只有顶点缓冲区、顶点着色器、纹理坐标、片元着色器,其余部分插手不了
官方描述过程
执行绘图命令以将顶点数据向下发送到管线。流水线的连续阶段运行顶点着色器以处理顶点数据,将顶点组装为图元,将图元光栅化为片段,运行片段着色器以计算每个片段的颜色和深度值,并将片段混合到帧缓冲区中以进行显示。
- app代码提供图元装配顶点信息,图片信息
- Vertex:处理顶点信息,可能包含的旋转、平移、缩放等
- Geometry:图元装配,和对超过区域的裁剪
- Fragment:片元着色器对纹理、Fog雾化处理
- Framebuffer Operations(帧缓冲区):处理好的数据提交给帧缓冲区,进行透明度,模版,深度测试,最后进行blend混合
此过程只描述了可操作的部分,不可操作的(光栅化)未做描述
1.顶点着色器
顶点着色器是一种着色器程序,描述了顶点上执行操作的着色器程序源代码/可执行文件..
着色器其实和代码段、函数、方法类似,只是这段代码由GPU来执行
- 输入部分
1.属性atttubute:用顶点数组提供每个顶点的数据
2.统一变量uniform:用来输入在顶点、片元着色器中不变的数据,比如不发生变化的颜色值
3.采样器:代表顶点着色器中使用纹理的特殊统一变量类型,比如纹理坐标
- 输出部分
1.gl_Position:它属于GLSL的内建变量,顶点处理结束后的结果会赋值给它,
2.gl_PointSize:顶点的尺寸,在顶点点着色器中可以进行修改点的大小尺寸,不常用
顶点着色器的业务
- 矩阵变换位置
对投影矩阵、模型视图矩阵的变化,都是在顶点着色器中进行计算
- 计算光照方式,生成逐顶点颜色
- 生成/变换纹理坐标
上图图形管线我们也看到了,片元着色器是没有输入属性值,来传递纹理坐标属性的,需要使用顶点着色器来进行桥接,将纹理坐标的属性传递给片元着色器
顶点着色代码案例
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 = vPos; // 相乘的结果赋值给了gl_Position
}
2.图元装配
顶点着色器的下一步:图片装配
图元Primitive: 点、线、三角形
图元装配:将顶点数据计算成一个个图元,在这个阶段会执行裁剪、透视分割和ViewPort变换操作,这个阶段我们不能使用代码进行干涉的.
3.光栅化
光栅化就是将图元转化成一组二维片段的过程,而转化的片段将由片段着色器进行处理.
像素点是二维的,所以会转化为二维片段.有多少像素点,片元着色器就会执行多少次,因为片元着色器由GPU高并发执行,也就不存在严重的性能问题.
4.片元着色器
片元着色器是一种着色器程序,描述了在片段上执行操作的着色器程序源代码/可执行文件.
- 输入部分
1.输入从顶点着色器桥接传来的,单元化的颜色、纹理坐标等
2.统一变量uniform:顶点/片元着色器使用的不变数据
3.采样器:片元着色器使用纹理的特殊统一变量类型,
- 输出部分
1.gl_FragColor:经过片元着色器,对某一个像素点进行处理后的结果
片元着色器的业务
- 计算像素点颜色
- 获取像素点纹理值
- 往像素点中填充颜色值,(纹理值/颜色值)
使用片元着色器举例:图片滤镜->针对图片像素点进行处理->得到新的颜色->存放帧缓存区->显示.
片元着色器代码案例
varyinglowpvec2varyTextCoord;
uniformsampler2DcolorMap;
voidmain()
{
gl_FragColor=texture2D(colorMap,varyTextCoord);
}
5.逐片段操作
- 像素归属测试: 确定帧缓存区中位置(Xw,Yw)的像素⽬前是不是归属于OpenGL ES所有.例如,如果⼀个显示OpenGL ES帧缓存区View被另外⼀个View 所遮蔽.则窗⼝系统可以确定被遮蔽的像素不属于OpenGL ES 上下⽂.从⽽不全显示这些像素. ⽽像素归属测试是OpenGL ES 的⼀部分,它不由开发者开⼈为控制,⽽是由OpenGL ES 内部进⾏.
- 裁剪测试: 裁剪测试确定(Xw,Yw)是否位于作为OpenGL ES状态的⼀部分裁剪矩形范围内.如果该⽚段位于裁剪区域之外,则被抛弃.
- 深度测试: 输⼊⽚段的深度值进步⽐较,确定⽚段是否拒绝测试
- 混合: 混合将新⽣成的⽚段颜⾊与保存在帧缓存的位置的颜⾊值组合起来.
- 抖动: 抖动可⽤于最⼩化因为使⽤有限精度在帧缓存区中保存颜⾊值⽽产⽣的伪像.
这一阶段只做了解,因为开发接触不到内部的实现,只可以进行开关的操作,都属于GPU内部处理
6.EGL(Embedded Graphics Library)
- OpenGL ES 命令需要渲染
上下⽂
和绘制表⾯
才能完成图形图像的绘制,在iOS中OpenGL ES提供了GLKit框架,GLKView,GLKViewController来作为载体 - 渲染上下文:存储相关OpenGL ES状态
- 绘制表面:是⽤于绘制图元的表⾯,它指定渲染所需要的缓存区类型,例如颜⾊缓存区,深度缓冲区和模板缓存区.
- OpenGL ES API 并没有提供如何创建渲染上下⽂或者上下⽂如何连接到原⽣窗⼝系统. EGL 是Khronos渲染API(如OpenGL ES) 和原⽣窗⼝系统之间的接⼝.
唯⼀⽀持OpenGL ES 却不⽀持EGL 的平台是iOS. Apple 提供⾃⼰的EGL API的iOS实现,称为EAGL.
- 因为每个窗⼝系统都有不同的定义,所以EGL提供基本的不透明类型—EGLDisplay, 这个类型封装了所有系统相关性,⽤于和原⽣窗⼝系统接⼝.
7.GLKit框架概述
GLKit可以使用数学库、背景纹理加载、预先创建的着色器效果,以及标准视图和视图控制器来实现渲染循环.它提供了功能和类,可以减少创建新的基于着色器的应用程序所需的工作量
- GLKView:提供绘制场所View
- GLKViewController:扩展UIKit,用于绘制视图内容的管理与呈现
OpenGL ES已经被苹果弃用,但是iOS开发者也可以继续使用