OpenGL ES 简介
OpenGL ES (OpenGL for Embedded Systems) 是以手持和嵌入式为目标的高级3D图形应用程序编程接口(API)。OpenGL ES是目前只能手机中占统治地位的图形API。⽀持的平台: iOS, Andriod , BlackBerry ,bada ,Linux ,Windows.
OpenGL ES 开放式图形库(OpenGL的)用于可视化的⼆维和三维数据。它是一个多功能开放标准图形库,⽀持2D和3D数字内 容创建,机械和建筑设计,虚拟原型设计,⻜行模拟,视频游戏等应⽤程序。您可以使⽤OpenGL配置3D图形管道并向其提交数据。顶点被变换和点亮,组合成图元,并光栅化以创建2D图像。OpenGL旨在将函数调用转换为可以发送到底层图形硬件的图形命令。由于此底层硬件专用于处理图形命令,因此OpenGL绘图通常非常快。
OpenGL for Embedded Systems(OpenGL ES)是OpenGL的简化版本,它消除了冗余功能,提供了一个既易于学习又更易于在移动图形硬件中实现的库。
- Application:客户端,不是Ios客户端,是OpenGl的客户端。
- OpenGL ES Framework: Ios开发是没有办法直接去Run GPU的,要通过一个标准,这个标准是OpenGL ES,通过OpenGL ES 间接的去操作GPU。
OpenGL ES允许应用程序利用底层图形处理器的强大功能。iOS设备上的GPU可以执行复杂的2D和3D绘图,以及最终图像中每个像素的复杂着色计算。
苹果opengles官网地址
OpenGL ES 1.0 是固定管线。
OpenGL ES 3.0 图形管线
着色器渲染流程
流程:
用API来创建顶点数据。
顶点缓存区是我们GPU的缓存区,显存上面的区域,顶点数组存在内存中间,方便读取的时候直接访问,他们存储的是一个数据,都是顶点坐标。 纹理坐标其实也是顶点数据。
把顶点数据叫给顶点着色器,顶点着色器算顶点数据。
图元装配简单理解,设置几何的连接方式等等。这你告诉它这个图形已什么样的方式连接,连接多少个顶点,就是这些顶点连接以后长什么样子。
光栅化就是确定好图形在屏幕上的有哪些个像素点,在那些个点上填充颜色。在光栅化这个步骤这没确定了像素点的颜色。在这是确定可位置,确定可像素点。
纹理那对应的是纹理坐标,纹理坐标它会放到顶点着色器,也会传到片元着色器,纹理坐标通过顶点着色器的属性通道传到片元着色器的。纹理坐标跟顶点坐标一样是不断变化的。纹理坐标最终是不是得传到片元着色器呢?一定,你不传过来,我不知道这个颜色怎么对应。
片段着色器,主要做颜色的填充,纯色填充(绿色的三角形),获取图片上对应位置的对应颜色。
逐片段操作,就是把每一个片段,把图形中的每一个像素点, 都填充。
把最后的结果放到
帧缓冲区
,最后显示到屏幕上面。变换反馈指的是图片的旋转、缩放等等。
每一个片段指的是一个图元,每个图元是以像素点为单位的,屏幕上某一个位置有1个图元就计算一次,有2个就计算2次,图元装配、光栅化开发者不管。
OpenGL ES 图形管道
- 顶点或者图片数据
- Vertex顶点着色器 计算 光照等等
- 图元装配、裁剪
- 片元着色器 纹理颜色计算 fog填充
- FrameBuffer 关于我们的透明度、模板、深度测试,最后颜色混合。
顶点着⾊器
顶点着⾊器要做些什么呢?输入顶点数据。
顶点着⾊器输入:
- 着色器程序---描述顶点上执行操作的顶点着色器程序源代码(GLSL)/可执行文件。
- 顶点着色器输入[属性]---用顶点数组提供每个顶点的数据。
- 统一变量[uniform]---顶点/片元着色器使用的不变数据。
- 采样器---代表顶点着色器使用纹理的特殊统一变量类型。
uniform一般指的是不变数据,旋转矩阵,旋转90度,在客户端计算出来,是在这一次渲染中,是这个图形渲染90度,在外面算出来,算出旋转矩阵,通过uniform传递到片元。在GLSL里面,让每一个顶点使用这个矩阵,都旋转90度。
采样器是我们处理纹理的时候一个特殊变量。
我们在获取纹理的时候,不会把纹理的数据或者文件,传递到glsl里面,会把一个id传递到glsl里面,纹理存储在内存中,我们只需要告诉他id,让他自己找就行。
你想让你的顶点着色器有效,计算出最后的顶点,你必须对gl_Position这个内建变量赋值,你不赋值,即使你算了一大堆内容,也没有用。gl_Position这个变量的意思是告诉着顶点色器最终的顶点坐标是多少。
顶点着⾊器业务
- 矩阵变换位置
- 计算光照公式生成逐顶点颜色
- ⽣成/变换纹理坐标
总结: 它可以用于执⾏⾃定义计算,实施新的变换,照明或者传统的固定功能所不允许的基于顶点的效果。
所以的阵数据类型只支持浮点类型。
顶点着⾊代码案例
attribute vec4 position;
attribute vec2 textCoordinate; //纹理
uniform mat4 rotateMatrix; //旋转矩阵4行4列
varying lowp vec2 varyTextCoord;
void main()
{
//把纹理数据传给varying变量,他就会传递到片元着色器中。
varyTextCoord = textCoordinate;
vec4 vPos = position;
//每一个顶点 * 旋转矩阵 = 最新的顶点(vPos)
vPos = vPos * rotateMatrix;
// 把最新的顶点传给内建变量
gl_Position = vPos;
}
position变量名称。
vec4: 4维向量
vec2: 2维纹理
uniform:统一通道,修饰符。
mat4:是我们的矩阵,4行4列的矩阵。
varying:纹理数据通过顶点着色器,传到片元着色器中。通过varying传递的。
lowp:精度 低精度、中精度、高精度。
gl_Position:内建变量,定义好了。必须给他赋值,前面计算完了,必须给他赋值,告诉顶点着色器最终的值。
attribute:把顶点数据输送到顶点着色器,需要attribute通道。它是一个修饰符,修饰position就说明position是通过attribute这个通道进来的,
一个顶点计算一次,上面的代码(GPU代码执行),三角形三个顶点,并行计算三次,GPU并行运算。
图元装配
顶点着⾊器之后,下一个阶段就是图元装配。
图元(Primitive): 点,线,三角形等.
图元装配: 将顶点数据计算成一个个图元.在这个阶段会执行裁剪、透视分割和 Viewport变换操作。
图元类型和顶点索确定将被渲染的单独图元。对于每个单独图元及其对应的顶点,图元装配阶段执行的操作包括:将顶点着⾊器的输出值执行裁剪、透视分割、视口变换后进⼊光栅化阶段。
图元装配开发者只能指定,不能写代码操作它。
光栅化
在这个阶段绘制对应的图元(点/线/三⻆形). 光栅化就是将图元转化成一组⼆维片段的过程.⽽这些转化的⽚段将由片元着⾊器处理.这些二维片段就是屏幕上可绘制的像素。
点光栅化:屏幕上的那几个像素点的光栅化。
线光栅化:屏幕上的那个线的那几个像素点光栅化。
面_光栅化:屏幕上的那个面的那几个像素点光栅化。
片段着⾊器/⽚元着⾊器
⽚元着⾊器/⽚段着⾊器 (干啥) 输入:
- 着色器程序—描述片段上执⾏操作的顶点着⾊器程序源代码/可执行文件
- 输⼊变量— 光栅化单元用插值为每个片段⽣成的顶点着色器输出
- 统⼀变量(uniform)—顶点/片元着色器使⽤的不变数据
- 采样器—代表片元着⾊器使用纹理的特殊统一变量类型.
输入变量从顶点着色器来,统一变量uniform、采样器都可以到片元着色器,最后输出的是颜色,得到每个像素点的颜色,最终一个像素点只有一个颜色。纹理会找到这个位置上的颜色值。颜色输出给gl_FragColor。gl_FragColor为内建变量,你必须给他赋值。
⽚元着⾊器业务
- 计算颜⾊
- 获取纹理值
- 往像素点中填充颜色值(纹理值/颜色值)
总结: 它可以用于图片/视频/图形中每个像素的颜色填充(⽐如给视频添加滤镜,实际上就是将视频中每个图片的像素点颜色填充进⾏修改.)
⽚元着⾊代码案例
//纹理坐标 在顶点着色器里面看过
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main(){
// 取到纹素赋值给gl_FragColor这个内渐变量
gl_FragColor = texture2D(colorMap, varyTextCoord);
}
varying lowp vec2 varyTextCoord;
在顶点和片元着色器定义,是一模一样的,用varying修饰的。
这个怎么确定顶点着色器传到片元着色器的是同一个呢? 是因为顶点着色器和片元着色器里面的定义的名字、类型、修饰都一模一样。
uniform sampler2D colorMap;
通过uniform(通道)传进来的纹理采样器(sampler2D)。通过colorMap就可以拿到对应的纹理。它不是通过文件数据,也不是通过文件指针。通过uniform。
⽚元着⾊没有属性变量,只有输入变量,从顶点着色器输出给我。attribute来不了这。得从顶点着色器传进来。
什么时候需要颜色混合?需要开发者自己来写。
片元着色器就是计算这个像素点最终的颜色值。
texture2D -- 参数
- 纹理采样器
- 纹理坐标
texture2D只用4个顶点和采样器就可以知道每个像素点的值。
目的:拿到这个纹理对应坐标上的颜色值(像素值)。简称取得纹素
。
逐⽚段操作
片段数据:就是把颜色取出来之后。
像素归属测试:比如这个像素是不是你的OpenGL处理的,颜色存在颜色缓冲区里,并不是说所有的颜色处理都是OpenGL处理的。
像素归属测试: 确定帧缓存区中位置(Xw,Yw)的像素目前是不是归属于OpenGL ES所有. 例如,如果一个显示OpenGL ES帧缓存区View被另外⼀一个View 所遮蔽.则窗口系统可以确定被遮蔽的像素不属于OpenGL ES上下文.从⽽不全显示这些像素.而像素归属测试是OpenGL ES 的一部分,它不由开发者开人为控制,⽽是由OpenGL ES 内部进⾏。
裁剪测试:裁剪测试确定(Xw,Yw)是否位于作为OpenGL ES状态的⼀部分裁剪矩形范围内.如果该片段位于裁剪区域之外,则被抛弃。
深度测试:输⼊片段的深度值进步比较,确定⽚段是否拒绝测试。
混合:混合将新生成的片段颜色与保存在帧缓存的位置的颜色值组合起来. 这跟片元着色器的混合不一样啊,片元着色器是有需求就混合,没需求就不写。
抖动: 抖动可用于最小化因为使⽤有限精度在帧缓存区中保存颜⾊值⽽产生的伪像。
上面的这几步是OpenGL帮你干的,你只需要打开这个开关就行。
EGL (Embedded Graphics Library )
OpenGL ES 命令需要渲染上下文
和绘制表面
才能完成图形图像的绘制.
渲染上下文:存储相关OpenGL ES 状态。
绘制表⾯: 是⽤于绘制图元的表面,它指定渲染所需要的缓存区类型,例如颜色缓存区,深度缓冲区和模板缓存区都叫绘制表⾯。
OpenGL ES API 并没有提供如何创建渲染上下文或者上下⽂如何连接到原⽣窗口系统. EGL 是Khronos 渲染API(如OpenGL ES) 和原生窗口系统之间的接口. 唯一⽀持 OpenGL ES 却不⽀持EGL 的平台是iOS. Apple 提供⾃己的EGL API的iOS实现,称为EAGL。
因为每个窗口系统都有不同的定义,所以EGL提供基本的不透明类型—EGLDisplay, 这个类型封装了所有系统相关性,用于和原⽣窗⼝系统接口.
由于OpenGL ES是基于C的API,因此它非常便携且受到广泛⽀支持。作为C-API,它与Objective-C Cocoa Touch应用程序⽆无缝集成。OpenGL ES规范没有定义窗口层; 相反,托管操作系统必须提供函数来创建一个接受命令的OpenGL ES 渲染上下文和一个帧缓冲区,其中写入任何绘图命令的结果。在iOS上使⽤OpenGL ES需要使用iOS类来设置和呈现绘图表面,并使⽤用平台中立的API来呈现其内容。
EGL的主要功能如下:
- 和本地窗口系统(native windowing system)通讯。
- 查询可⽤的配置。
- 创建OpenGL ES可⽤的“绘图表面”(drawing surface)
- 同步不同类别的API之间的渲染,⽐如在OpenGL ES和OpenVG之间同步,或者在OpenGL和本地窗⼝的绘图命令之间
- 管理“渲染资源”,⽐如纹理映射(rendering map)
OpenGL ES 错误处理
如果不正确的使用OpenGL ES命令,应用程序就会产生一个错误编码,这个错误编码将会被记录,可以用glGetError查询。在应用程序用glGetError查询第一个错误代码之前,不会记录其他的错误代码,当前的错误代码便复位为GL_NO_ERROR.
GLenum glGetError(void)
错误代码 | 描述 |
---|---|
GL_NO_ERROR | 从上一次调用glGetError 以来没有生成任何错误 |
GL_INVALID_ENUM | GLenum 参数超出范围,忽略⽣成错误命令 |
GL_INVALID_VALUE | 数值型 参数超出范围,忽略生成错误命令 |
GL_INVALID_OPERATION | 特定命令在当前OpenGL ES 状态无法执⾏ |
GL_OUT_OF_MEMORY | 内存不⾜时执⾏该命令,如果遇到这个错误,除⾮当前错误代码,否则OpenGL ES 管线的状态被认为未定义 |
动画实现原理
动画分为2种
- 关键帧动画
- 逐帧动画
动画:会动的画。
由一张一张的图片组成的。这个叫逐帧动画。
2者区别:
逐帧动画表示我的每一张图片我都要有。把这个过程拿一张张图片展示出来。按照60帧每秒的速度连上,你就觉得它是连贯的。
关键帧动画:我只记录关键信息,然后由计算机计算所得。
首先拿到起始位置,比如说我现在有个按钮在左上角,然后要移动到右上角,我只要得到4个值就行,从这4个值计算机就能算出它的过度帧。
4个值
起始位置、结束位置、动画时间(从左上角移动到又上角,动画花多少时间)、它是匀速运动还是怎么运动的。
CADisplayLin简介
CADisplayLink不能被继承的。
GLKit是ios封装的OpenGL框架,简单的可以用它写。