OpenGL ES

646 阅读6分钟

一、OpenGL ES的定义

OpenGL ES(OpenGL for Embedded Systems)是以手持和嵌入式为目标的高级3D图形应用程序编程接口(API),OpenGL ES是目前智能手机中占据统治地位的图形API,支持的平台:iOS、andriod、BlackBerry、bada、Linux、Windows

  • 属于OpenGL的子集,只是一套标准
  • OpenGL ES和OpenGL ES一样只是一个标准,所以不同平台都是基于OpenGL ES来开发了一套对应平台的API
  • 本质是一个多功能开放标准图形库,可以加载二维和三维的数据
  • 是OpenGL的简化版本,消除了冗余功能,去掉了移动客户端不需要的api

二、OpenGL ES 的图形处理过程

客户端调用过程:

客户端通过调用OpenGL ES framework的api在GPU上调度OpenGL ES Server(也就是OpenGL ES的一套标准),例如显示、光栅化等显示效果

然后顶点着色器从内存中取到顶点数据,然后顶点着色器将顶点数据进行处理后交给图元装配,通过光栅化按照需求装配成需要的样式,装配完成后再将数据交给片元着色器,片元着色器将对应的像素该显示的颜色进行处理,处理完成后交个帧缓存区,等待屏幕显示

苹果的官方文档提供的图形管道:

  • app代码提供图元装配信息以及图片信息
  • 对顶点数据进行平移、缩放、旋转
  • 再进行图元装配,例如裁剪等
  • 再通过片元着色器进行纹理的处理
  • 在提供到帧缓冲区进行混合、透明、深度测试等

三、顶点着色器

1、定义

  • 顶点注射器是一个着色器程序(也就是一段代码),是描述顶点上执行操作的顶点着色器程序源代码
  • 顶点着色器需要参数,也就是用顶点数组提供每个顶点的数据
  • 统一变量(uniform)也就是顶点和片元着色器经常使用,但很少发生变化的数据
  • 采样器--代表顶点着色器使用纹理的特殊统一变量类型
  • 顶点着色器会输出内建变量(gl_Position)

2、业务处理

  • 矩阵变换
  • 计算光照公式生成琢顶点颜色
  • 生成/变换纹理坐标
  • 给片元着色器传递纹理信息

3、代码案例

因为GPU是没法处理复杂的逻辑处理,所以顶点着色器的代码很简单

attribute vec4 position;
attribute vec2 textCoordinate;
uniform mat4 rotateMatrix;
varying lowp vec2 varyTextCoord;
void main(){
	varyTextCoord = textCoordinate;
    vec4 vPos = position;
    vPos = vPos * rotateMatrix;
    gl_Postition = vPos;
}
  • atttribute、uniform表示client与server之间的通道。
  • 其中的vec4、vec2都是向量类型,表示四维向量和二维向量
  • mat4:4 * 4 矩阵
  • varying是修饰符:通过varying将纹理坐标传入到片元着色器
  • lowp : 低精度
  • main中的操作:
    • 实现纹理坐标的桥接
    • 实现了顶点选择矩阵的相乘:列向量与列矩阵相乘,得到旋转后的顶点坐标
    • 将上述得到的顶点坐标赋值给gl_Position

四、图元装配

顶点着色器处理完后,下一阶段就是图元装配,图元装配就是将顶点数据计算成一个个图元,在这个阶段会执行裁剪、透视分割和viewport变换操作,下一个阶段就进入到光栅化阶段

但是图元装配和光栅化这一阶段基本无法让开发者进行处理

五、光栅化

光栅化就是将图元转化成一组二维片段(因为屏幕是二维的)的过程,而这些转化的片段将由片元着色器处理,这些二维片段就是屏幕上可绘制的像素

假如有100个像素点,那么片元着色器就要执行100遍

六、片元着色器

1、定义

  • 片元着色器就是描述片段上执行操作的片元着色器程序源代码,也是一段代码
  • 需要的参数就是光栅化单元用插值为每个片段生成的顶点着色器输出
  • 统一变量(uniform)-顶点着色器经常使用,但是很少变化的数据
  • 采样器--代表片元着色器使用纹理的特殊统一变量类型

顶点着色器输出的是gl_fragColor,也就是片元着色器对某一个像素点进行处理之后的结果

2、片元着色器的业务

  • 计算颜色
  • 获取纹理值
  • 往像素点中填充颜色值(纹理值/颜色值)

片元着色器可以用于图片/视频/图形中每个像素的颜色填充(比如给视频添加滤镜,实际上就是将视频中每个图片的像素点颜色填充进行修改)

3、代码示例

varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
vord main(){
	gl_FragColor = texture2D(colorMap,varyTextCoord);
}
  • varying:必须和顶点着色器中一模一样,这样才能传递纹理坐标
  • sampler2D:采样器类型
  • texture2D:纹理采样器,纹理坐标,获取对应位置/坐标的颜色值,简称获取纹素
  • gl_FragColor(内建变量):将最终的颜色值赋值给它

总结:

顶点着色器、片元着色器都是代码段,类似于iOS中的函数、方法,有返回值

  • 顶点着色器的返回值会被赋值给gl_Position
  • 片元着色器的结果会赋值给gl_FragColor

这两个返回值都属于GLSL中的内建变量,是封装好的,直接将数据赋值给它即可

  • gl_Position:顶点着色器中某一个顶点经过一系列处理后得到的结果
  • gl_fragColor:经过片元着色器对某一个像素点来进行处理之后的结果

OpenES的应用

图片滤镜

  • 获取图片中的每一个像素点
  • 像素点做饱和度处理
  • 得到新的颜色
  • 将新的颜色放入帧缓存区
  • 进行展示

视频滤镜 原理和处理方式和图片滤镜是一样的(GLSL代码)

  • 获取视频MP4文件
  • 拿到h264(视频压缩文件)
  • 将视频解码(解压),还原成一帧一帧的图片
  • 针对一帧一帧图片进行处理

EGL(Embedded Graphics Library)

  • OpenGL ES 命令需要渲染上下文绘制表面才能完成图形图形的绘制
  • 渲染上下文:存储相关OpenGL E状态,是一个状态机
  • 绘制表面:用于绘制图元的表面,需要指定渲染的缓存区,例如颜色缓存区、深度缓冲区、模板缓冲区
  • OpenGL ES API 并没有提供如何创建渲染上下文或者上下文如何链接到原生窗口系统。
  • EGL是Khronos渲染API(如OpenGL ES)和原生窗口系统之间的接口。
  • 唯一支持OpenGL ES 却不支持EGL的平台是iOS,Apple 提供自己的EGL API的iOS实现,称为EAGL
  • 因为每个窗口系统都有不同的定义,所以EGL提供基本的不透明类型-EGLDisplay,这个类型封装了所有系统相关性,用于和原生窗口系统接口