OpenGL ES是一个应用编程接口(API),用于针对手机、个人数字助理(PDAs)、控制台、电器、车辆和航空电子设备等手持和嵌入式设备的高级3D图形。OpenGL ES是Khronos团队创建的一套API之一。专注于为手持设备和嵌入式设备创建开放标准和免版税的应用编程接口。
桌面世界有两个标准的3D APIs,
- DirectX:是运行微软视窗操作系统的任何系统的事实上的标准3D应用编程接口,被该平台上的大多数3D游戏使用。
- OpenGL是一个跨平台的标准3D应用编程接口,适用于运行Linux、各种风格的UNIX、Mac OS X和微软Windows的桌面系统。这是一个被广泛接受的标准3D应用编程接口,在现实世界中得到大量使用。
简单总结:opengles是一个编程的接口,用于手持设备。桌面版有两个3D的api,一个是opengl一个是directX。
由于OpenGL作为3D API的广泛采用,在为手持和嵌入式设备开发开放标准3D API并对其进行修改以满足手持和嵌入式设备空间的需求和限制时,从桌面OpenGL API开始是有意义的。OpenGL ES解决的设备非常有限的处理能力和内存可用性、低内存带宽、对电源的敏感性的限制。
- OpenGL API非常大且复杂,OpenGL ES工作组的目标是创建一个适用于受限设备的API。为了实现这个目标,工作组从OpenGL API中移除了任何冗余。在任何情况下,如果执行相同操作的方式不止一种,则采用最有用的方法,并删除冗余技术。一个很好的例子是指定几何图形,在OpenGL中,应用程序可以使用立即模式、显示列表或顶点数组。在OpenGL ES中,只有顶点数组存在,即时模式和显示列表被删除
- 消除冗余是一个重要的目标,但保持与OpenGL的兼容性也很重要。OpenGL ES的设计尽可能地使那些被写入OpenGL中嵌入式功能子集的应用程序也能在OpenGL ES上运行。这是一个重要目标的。原因是,它允许开发人员利用两个应用编程接口,并开发使用公共功能子集的应用程序和工具。虽然这是一个重要的目标,但也有偏离的情况,尤其是OpenGL ES 2.0。这将在后面的章节中详细讨论。
- 引入了新功能来解决手持设备和嵌入式设备的特定限制。例如,为了降低功耗和提高着色器的性能,在着色语言中引入了精度限定符。
- OpenGL ES的设计者旨在确保图像质量的最小特征集。大多数手持设备的屏幕尺寸有限,因此屏幕上绘制的像素质量必须尽可能好。
- OpenGL ES工作组希望确保任何OpenGL ES实现都将满足某些可接受的和一致同意的图像质量、正确性和鲁棒性标准。这是通过开发适当的一致性测试来实现的,OpenGL ES实现必须通过这些测试才能被认为是兼容的。
简单总结:
opengl是一个跨平台的图形编程API,使用在手持设备上会因为显示屏幕或者是内存,电量等因素的影响,所以就出现了opengles,
1.使用了最有效的绘制方式进行绘制
2.在不影响绘制质量的前提下删除掉了冗余的技术
3.引入了精度限制
4.绘制质量会尽量的好
5.具有良好的兼容性。
OpenGL ES 2.0规范实现了一个可编程的图形流水线,是从OpenGL 2.0规范衍生而来的。源自OpenGL规范的修订意味着相应的OpenGL规范被用作确定OpenGL ES的特定修订中的特征集的基线。然后创建了一个不同的规范,描述了OpenGL ES相对于其派生的OpenGL规范的变化和增加。
OpenGL ES 2.0实现了一个可编程着色的图形管道,由两个规范组成:OpenGL ES 2.0 API规范和OpenGL ES着色语言规范(OpenGL ES SL)。图1-1展示了OpenGL ES 2.0图形流水线。图中的阴影框表示OpenGL ES 2.0中流水线的可编程阶段。概述
描述各个阶段的概述
顶点着色器
顶点着色器实现了顶点进行操作的通用可编程方法。
顶点着色器的输入包括以下内容:属性、uniform、采样器、着色器程序、可变变量
- Attributes—使用顶点数组提供的每个顶点的数据
- Uniforms-顶点着色器使用的恒定数据。
- Samplers-代表顶点着色器使用的纹理的特定制服类型。顶点着色器中的采样器是可选的。
- Shader program-顶点着色器程序源代码或可执行文件,描述将在顶点上执行的操作。(在我的使用过程中使用很少)
- 顶点着色器的输出称为可变变量。在图元光栅化阶段,为每个生成的片段计算变化的值,并将其作为输入传递给片段着色器。用于从分配给图元的每个顶点的变化值为每个片段生成变化值的机制称为插值。顶点着色器的输入和输出如图1-2所示。
顶点着色器可用于传统的基于顶点的操作,如通过矩阵变换位置、计算光照方程以生成逐顶点颜色,以及生成或变换纹理坐标。或者,因为顶点着色器是由应用程序指定的,所以顶点着色器可用于进行自定义顶点变换。
示例1-1显示了一个用OpenGL ES着色语言编写的顶点着色器。我们将在本书后面详细解释顶点着色器。我们现在展示这个着色器,只是为了让您了解顶点着色器是什么样子的。示例1-1中的顶点着色器将位置及其相关的颜色数据作为输入属性,通过4 × 4矩阵转换位置,并输出转换后的位置和颜色
Example 1-1 A Vertex Shader Example
示例 1-1 顶点着色器示例
1. // uniforms used by the vertex shader 固定值 是不会变化
2. uniform mat4 u_mvpMatrix; //描述了存储组合模型视图和投影矩阵的统一变量u_mvpMatrix。
5. // attributes input to the vertex shader 属性值 是可以进行变化的(也就是可以传递进来的值)
6. attribute vec4 a_position; // position value
7. attribute vec4 a_color; // input vertex color
9. // varying variables – input to the fragment shader
10. varying vec4 v_color; // output vertex color 值传输给片段着色器 计算每一个点的值
12. void
13. main()
14. {
15. v_color = a_color;
16. gl_Position = u_mvpMatrix * a_position;
17.}
简单总结:介绍可编程管线第一个可以控制的地方。顶点着色器,它可以有四种方式的输入,一钟方式的输出,将数据传递给片元着色器。
图元装配
顶点着色器之后,管道中的下一个阶段是图元装配。图元是一种几何对象,可以使用OpenGL ES中适当的绘制命令来绘制。这些绘图命令指定一组顶点属性,这些属性描述图元的几何图形和图元类型。每个顶点都用一组顶点属性来描述。这些顶点属性包含顶点着色器用来计算位置的信息以及可以传递给片段着色器的其他信息,如其颜色和纹理坐标。
简单总结:就是将上一个阶段的顶点,组合成为一个完整的图形,比如三角形,直线。
在图元组装阶段,着色顶点被组装成可以绘制的单个几何图元,如三角形、直线或点精灵。对于每个图元,必须确定图元是否位于视平截头体(屏幕上可见的3D空间区域)内。如果图元没有完全位于视图平截头体内部,则可能需要将图元裁剪到视图平截头体上。如果图元完全在外部,则被丢弃。裁剪后,顶点位置转换为屏幕坐标。还可以执行剔除操作,根据图元是面向前还是面向后来丢弃图元。在裁剪和剔除之后,图元准备好被传递到管道的下一阶段,即光栅化阶段。
简单总结:图元会判断是不是在视锥体的里面,如果不在就需要进行一次裁剪,不在视锥体里面的就需要将其删除掉,还有需要执行剔除,根据设置的正向和反向来确定是不是需要剔除。
光栅化
图1-3所示的下一个阶段是光栅化阶段,在此阶段绘制适当的图元(点精灵、线或三角形)。光栅化是将图元转换成一组二维片段的过程,这些片段由片段着色器处理。这些二维片段代表可以在屏幕上绘制的像素。
简单总结:就是将图元使用一个二维数组来进行显示,每个数组的点就代表这里的像素值。
片段着色器
片段着色器为光栅化阶段的每一个片段执行
- 可变变量-由光栅化单元使用插值为每个片段生成的顶点着色器的输出。
- uniforms-片段着色器使用的恒定数据。
- 采样器——代表片段着色器使用的纹理的特定制服类型。
- 着色器程序—片段着色器程序源代码或可执行文件,描述将对片段执行的操作。
片段着色器可以丢弃片段,也可以生成一个称为gl_FragColor的颜色值。由光栅化阶段生成的颜色、深度、模板和屏幕坐标位置(xw,yw)成为OpenGL ES 2.0管道的每个片段操作阶段的输入。
对于图像显示的操作就在这里,这里可以对gl_color对应的就是每一个像素点。
Example 1-2 A Fragment Shader Example
1. precision mediump float;
2. varying vec4 v_color; // input vertex color from vertex shader
3. void
4. main(void)
5. {
6. gl_FragColor = v_color;
7.}
- 第1行设置默认精度限定符(手持设备的内存限制)
这将在第4章“着色器和程序”中详细解释第3行描述了片段着色器的输入。顶点着色器必须写入片段着色器读取的同一组可变变量。 - 第6-10行描述了片段着色器的主要功能。请注意,片段着色器中没有声明输出。这是因为唯一的输出变量是gl_FragColor,在本例中,它被设置为第9行中v_color给定的片段着色器的输入颜色。
每个片段进行操作
在片段着色器之后,下一个阶段是每片段操作。用(xw,yw)屏幕坐标光栅化产生的片段只能修改帧缓冲区中位置(xw,yw)处的像素。图1-5描述了OpenGL ES 2.0每片段操作阶段。
简单理解一下:就是一个二维数组,每个像素就代表一个二维数组的值,在处理的过程里面,每一个片段的操作只能处理对应x,y屏幕坐标的里面的像素。
- 每一个片段进行哪些操作
- 像素所有权测试:x,y中位置的像素是否输出当前上下文,就是要显示的 。
- 剪式裁剪:剪式矩阵内就显示 ,不在就不显示
- 模板测试和深度测试:对传入的值进行测试
- 混合:将存储在里面的值和当前的颜色值想结合
- 抖动:抖动可用于最大限度地减少因使用有限精度在帧缓冲区中存储颜色值而产生的伪像
测试结束要不就将值写入要不就直接丢弃,取决于掩码的值。还有一个可以从缓存区中读取数据的接口。
EGL
OpenGL ES命令需要一个渲染上下文和一个绘图表面。渲染上下文存储适当的OpenGL ES状态。绘图表面是图元将被绘制到的表面。绘图表面指定渲染所需的缓冲区类型,如颜色缓冲区、深度缓冲区和模具缓冲区。绘图面还指定了每个所需缓冲区的位深度。
(surfaceView和GLSurfaceView就会看到这个EGL.)
OpenGL ES API没有提到渲染上下文是如何创建的,或者渲染上下文是如何附加到本机窗口系统的。EGL是OpenGL ES等Khronos渲染APIs和原生窗口系统之间的一个接口。实现OpenGL ES时不需要提供EGL。开发人员应该参考平台供应商的文档来确定支持哪个接口。
在开始渲染之前,任何OpenGL ES应用程序都需要使用EGL执行以下操作:
- 查询设备上可用的显示并初始化它们。例如,一个翻盖手机可能有两个液晶面板,我们可以使用OpenGL ES渲染可以在其中一个或两个面板上显示的表面。
- 创建渲染表面。在EGL创建的表面可以分为屏幕表面和屏幕外表面。屏幕上的表面被附加到本地窗口系统,而屏幕外的表面是像素缓冲区,不被显示,但可以用作渲染表面。这些表面可用于渲染成纹理,并可在多个Khronos APIs之间共享。
- 创建渲染上下文。需要EGL来创建一个OpenGL ES渲染上下文。在实际开始渲染之前,需要将此上下文附加到适当的表面上。
EGL应用编程接口实现了刚才描述的特性和附加功能,如电源管理、支持一个进程中的多个渲染上下文、在一个进程中的渲染上下文之间共享对象(如纹理或顶点缓冲区),以及获取给定实现支持的EGL或OpenGL ES扩展函数的函数指针的机制。EGL规范的最新版本是EGL版本1.4。
刷新和完成
OpenGL ES 2.0 API继承了OpenGL客户端-服务器模型。应用程序或客户端发出命令,这些命令由OpenGL ES实现或服务器处理。在OpenGL中,客户机和服务器可以通过网络驻留在不同的机器上。OpenGL ES还允许客户端和服务器驻留在不同的机器上,但是因为OpenGL ES的目标是手持和嵌入式平台,所以客户端和服务器通常在同一台设备上。
在客户机-服务器模型中,客户机发出的命令不一定会立即发送到服务器。如果客户机和服务器在网络上,那么通过网络发送单独的命令将会非常低效。相反,命令可以在客户端缓冲,然后在稍后的时间点发送到服务器。因此,需要有一种机制,让客户机知道服务器何时完成了以前提交的命令的执行。考虑另一个例子,其中多个OpenGL ES上下文(每个当前到不同的线程)共享对象。为了在这些上下文之间正确同步,来自上下文A的命令在依赖于由上下文A修改的OpenGL ES状态的上下文B之前被发布到服务器是很重要的。glFlush命令用于刷新当前OpenGL ES上下文中的任何未决命令,并将它们发布到服务器。请注意,glFlush只向服务器发出命令,不等待它们完成。如果客户端要求完成命令,应该使用glFinish命令。但是,除非绝对必要,否则我们不建议使用glFinish。因为在服务器完全处理完上下文中所有排队的命令之前,glFinish不会返回,所以调用glFinish会强制客户端和服务器同步它们的操作,从而对性能产生不利影响。
总结:
两大3D渲染API,一个是DirectX和open gl,前一个运行在微软各个平台,后者可以在多个平台运行,open gles是面对手持设备上的,由于手持设备的各种局限,所以在opengles对opengl进行了一些冗余处理,但是也需要保持高度的兼容性,并且opengles可以设置数据类型。
目前主要的版本包括1.0和2.0,主要区别是固定管线和自定义管线,因为种种原因它是不可以向后兼容的(需要更小的存储,用户反馈),opengles是通过opengl衍生而来的,它主要可以控制片元着色器和着段找色器,片元着色器主要有属性、uniform、采样器、着色器程序、可变变量(varing),主要的操作有进行坐标变换的处理,光照计算。可变变量作为一种输出,可以传递给片段找色器,在栅格化阶段计算出颜色的插值。顶点找色器的数据一般会进入到图元装配阶段,图元装配的作用是将顶点变化为基本的图元,被绘制成点线三角形,点的位置还会进行一次判断,是否在视屏接头内部,不在的将会被抛弃,然后进入到下一个阶段栅格化阶段,栅格化就是将上一部分的数据进行一次处理,变为一个坐标点,也可以认为是像素点,并且也会计算插值。下一步就是片段着色器,它为光栅化后的每一个片段进行执行,它有可变变量,采样器,着色器程序,这里可以丢弃片段,也可以设置glColor,光栅化阶段生成的颜色、深度、魔板。屏幕坐标位置成为每个片段操作的输入。下来就是没片段进行执行,光栅化阶段的片段只可以修改缓冲区中的像素,每个片段都会执行以下操作:像素测试(是否属于我的标准是否被遮挡)、裁剪矩形、深度测试、混合操作、消除抖动。
EGL是显示表面和opengl联系的中间部分,显示表面是显示屏,opengl状态是绘制数据的状态
执行的一个基本顺序,加载顶点坐标,然后变化到本地内存区域(java 代码需要)、顶点找色器的处理、图元处理,栅格化、片段找色器、像素 测试、矩阵裁剪、深度测试。混合测试、消除抖动。
刷新和完成,刷新是执行完成 之后的执行的一种客户端的刷新操作,完成是执行的一种强制操作,即使没有操作完成也会执行的刷新操作。
状态机:本次设置,如果不进行修改下次操作仍然使用这个操作。