OpenGL ES 基础概念介绍

来源:互联网 发布:手机室内建模软件 编辑:程序博客网 时间:2024/06/05 05:45

OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。


首先,光栅化(Rasterize/rasteriztion)。
这个词儿Adobe官方翻译成栅格化或者像素化。没错,就是把矢量图形转化成像素点儿的过程。我们屏幕上显示的画面都是由像素组成,而三维物体都是点线面构成的。要让点线面,变成能在屏幕上显示的像素,就需要Rasterize这个过程。就是从矢量的点线面的描述,变成像素的描述。
如下图,这是一个放大了1200%的屏幕,前面是告诉计算机我有一个圆形,后面就是计算机把圆形转换成可以显示的像素点。这个过程就是Rasterize。

————————————————————————
渲染管线(Pipeline)
这个翻译尤其不接地气,兼职就是直译(pipe管子line线路)。Pipeline是输送管道的意思。其实是指三维渲染的过程中显卡执行的、从几何体到最终渲染图像的、数据传输处理计算的过程。
————————————————————————
着色器(Shader)
这个翻译的挺好。画画的时候我们经常有这么一个过程:先打线稿,再上色。着色器就是用来做这个工作的。
通常着色器分两种:
1顶点着色器(vertex shader)这个是告诉电脑如何打线稿的——如何处理顶点、法线等的数据的小程序。
2片面着色器(fragment shader)这个是告诉电脑如何上色的——如何处理光、阴影、遮挡、环境等等对物体表面的影响,最终生成一副图像的小程序。
采用了这两种着色器小程序 的 数据传输处理计算的渲染过程,称之为 可编程管线。


Opengl es 2.0实现了可编程的图形管线,比起1.x的固定管线要复杂和灵活很多,由两部分规范组成:Opengl es 2.0 API规范和Opengl es着色语言规范。下图是Opengl es 2.0渲染管线,阴影部分是opengl es 2.0的可编程阶段。

 

1. 顶点着色器(VertexShader)
顶点着色器对顶点实现了一种通用的可编程方法。
顶点着色器的输入数据由下面组成:
Attributes:使用顶点数组封装每个顶点的数据,一般用于每个顶点都各不相同的变量,如顶点位置、颜色等。
Uniforms:顶点着色器使用的常量数据,不能被着色器修改,一般用于对同一组顶点组成的单个3D物体中所有顶点都相同的变量,如当前光源的位置。
Samplers:这个是可选的,一种特殊的uniforms,表示顶点着色器使用的纹理。
Shader program:顶点着色器的源码或可执行文件,描述了将对顶点执行的操作。
顶点着色器的输出数据是varying变量,在图元光栅化阶段,这些varying值为每个生成的片元进行计算,并将结果作为片元着色器的输入数据。从分配给每个顶点的原始varying值来为每个片元生成一个varying值的机制叫做插值。
顶点着色器数据的输入和输出可以参考下图:
顶点着色器可用于传统的基于顶点的操作,例如:基于矩阵变换位置,进行光照计算来生成每个顶点的颜色,生成或者变换纹理坐标。
另外因为顶点着色器是由应用程序指定的,所以你可以用来进行任意自定义的顶点变换。

下面是一个用opengl es着色器语言编写的顶点着色器源码,这个顶点着色器使用一个position和跟它相关联的color数据作为输入数据,通过一个4×4矩阵变换位置,然后输出变换后的位置和颜色数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1. // uniforms used by the vertex shader
2. uniform mat4 u_mvpMatrix; // matrix to convert P from model
3. // space to normalized device space.
4.
5. // attributes input to the vertex shader
6. attribute vec4 a_position; // position value
7. attribute vec4 a_color; // input vertex color
8.
9. // varying variables – input to the fragment shader
10. varying vec4 v_color; // output vertex color
11.
12. void
13. main()
14. {
15. v_color = a_color;
16. gl_Position = u_mvpMatrix * a_position;
17. }

第2行代码定义了一个uniform变量u_mvpMatrix,mat4表示4×4浮点数矩阵,该变量存储了组合模型视图和投影矩阵。6和7行代码定义了顶点着色器的输入数据:Attributes,vec4表示包含了4个浮点数的向量,a_position是顶点位置属性,a_color是顶点颜色属性。第10行代码定义了varying类型的变量v_color,varying是用于从顶点着色器传递到片元着色器的变量,v_color是顶点着色器的输出数据,存储了每个顶点的颜色。12-17行的main函数是顶点着色器和片元着色器的入口,第15行读取了顶点着色器输入属性中a_color的值,并把它赋值给输出数据v_color,第16行的gl_Position 是内置的varying变量,不需要声明,顶点着色器必须把变换后的位置赋值给它。

2.图元装配(Primitive Assembly)
顶点着色器之后,渲染流水线的下一个阶段是图元装配,图元是一个能用opengl es绘图命令绘制的几何体,绘图命令指定了一组顶点属性,描述了图元的几何形状和图元类型。顶点着色器使用这些顶点属性计算顶点的位置、颜色以及纹理坐标,这样才能传到片元着色器。在图元装配阶段,这些着色器处理过的顶点被组装到一个个独立的几何图元中,例如三角形、线、点精灵。对于每个图元,必须确定它是否位于视椎体内(3维空间显示在屏幕上的可见区域),如果图元部分在视椎体中,需要进行裁剪,如果图元全部在视椎体外,则直接丢弃图元。裁剪之后,顶点位置转换成了屏幕坐标。背面剔除操作也会执行,它根据图元是正面还是背面,如果是背面则丢弃该图元。经过裁剪和背面剔除操作后,就进入渲染流水线的下一个阶段:光栅化。

3. 光栅化(Rasterization)
光栅化阶段把图元转换成片元集合,之后会提交给片元着色器处理,这些片元集合表示可以被绘制到屏幕的像素。如下图所示:

 

4. 片元着色器(FragmentShader)
片元着色器对片元实现了一种通用的可编程方法,它对光栅化阶段产生的每个片元进行操作,需要的输入数据如下:
Varying variables:顶点着色器输出的varying变量经过光栅化插值计算后产生的作用于每个片元的值。
Uniforms:片元着色器使用的常量数据
Samplers:一种特殊的uniforms,表示片元着色器使用的纹理。
Shader program:片元着色器的源码或可执行文件,描述了将对片元执行的操作。
片元着色器也可以丢弃片元或者为片元生成一个颜色值,保存到内置变量gl_FragColor。光栅化阶段产生的颜色、深度、模板和屏幕坐标(Xw, Yw)成为流水线中pre-fragment阶段(FragmentShader之后)的输入。如下图:

下面是一个简单的片元着色器源码,可以跟上面的顶点着色器源码结合绘制一个高洛德着色的三角形。

1
2
3
4
5
6
7
8
9
10
1. precision mediump float;
2.
3. varying vec4 v_color; // input vertex color from vertex shader
4.
5.
6. void
7. main(void)
8. {
9. gl_FragColor = v_color;
10.}

第1行代码设置默认的精度修饰符,有highp、mediump、lowp,这个后面再详细解释。第3行代码定义了片元着色器的输入数据,顶点着色器必须赋值给片元着色器一组一样的varying变量。注意:gl_FragColor是片元着色器唯一的输出,第9行代码把输入数据v_color赋值给gl_FragColor。

5. 逐个片元操作阶段(Per-Fragment Operations)
片元着色器之后就是逐个片元操作阶段,包括一系列的测试阶段。一个光栅化阶段产生的具有屏幕坐标(Xw, Yw)的片元,只能修改framebuffer(帧缓冲)中位置在(Xw, Yw)的像素。下图是Opengl es 2.0逐片元操作的过程:

Pixel ownership test:像素所有权测试决定framebuffer中某一个(Xw, Yw)位置的像素是否属于当前Opengl ES的context,比如:如果一个Opengl ES帧缓冲窗口被其他窗口遮住了,窗口系统将决定被遮住的像素不属于当前Opengl ES的context,因此也就不会被显示。
Scissor test:裁剪测试决定位置为(Xw, Yw)的片元是否位于裁剪矩形内,如果不在,则被丢弃。
Stencil and depth tests:模板和深度测试传入片元的模板和深度值,决定是否丢弃片元。
Blending:将新产生的片元颜色值和framebuffer中某个(Xw, Yw)位置存储的颜色值进行混合。
Dithering:抖动可以用来最大限度的减少使用有限精度存储颜色值到framebuffer的工件。
逐片元操作之后,片元要么被丢弃,要么一个片元的颜色,深度或者模板值被写入到framebuffer的(Xw, Yw)位置,不过是否真的会写入还得依赖于write masks启用与否。write masks能更好的控制颜色、深度和模板值写入到合适的缓冲区。例如:颜色缓冲区中的write mask可以被设置成没有红色值写入到颜色缓冲区。另外,Opengl ES 2.0提供从framebuffer中获取像素的接口,不过需要记住的是像素只能从颜色缓冲区读回,深度和模板值不能读回。

注意:Opengl ES 2.0 的Per-Fragment Operations已经不再支持Alpha test 和 LogicOp了,这两个步骤在 OpenGL 2.0 和 OpenGL ES 1.x中是存在的。Alpha test 阶段不再需要的原因是片元着色器可以丢弃片元,所以可以在片元着色器中执行Alpha test。 LogicOp因为很少使用,所以不再支持了。


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩吃多了吐了怎么办 6岁儿童越来越瘦怎么办 7岁儿童不吃饭怎么办 天热宝宝不好好吃饭怎么办 天热宝宝不爱吃饭怎么办 天热宝宝不想吃饭怎么办 夏天天热宝宝不爱吃饭怎么办 3岁宝宝吃饭不香怎么办 胃ca吃饭反胃没食欲怎么办 12岁儿童脸色发黄怎么办 胃饿 但是没食欲不想吃饭怎么办 牙缝大经常塞西怎么办 吃肉老是塞牙缝怎么办 宝宝光喝奶粉不吃饭怎么办 九个月宝宝缺维c怎么办 九个月宝宝缺维d怎么办 9个月大宝宝缺锌怎么办 三周岁宝宝不爱吃饭怎么办 一周岁宝宝不爱吃饭怎么办 两岁半宝宝不自己吃饭怎么办 3岁宝宝不会吃饭怎么办 节食减肥胃疼怎么办呢 减肥不吃饭胃疼怎么办 过度节食伤了胃怎么办 3岁宝宝啥也不吃怎么办 1岁多宝宝不吃饭怎么办 胃口吃辣的难受怎么办 空腹吃辣椒胃疼怎么办 吃东西辣的胃口疼怎么办 吃辣的东西胃烧怎么办 吃母乳的宝宝不爱喝水怎么办 三个月宝宝不肯吃奶粉怎么办 三个月宝宝不肯喝奶粉怎么办 三个月的宝宝不肯喝奶粉怎么办 三个月的宝宝不肯吃奶粉怎么办 饿了还是没食欲怎么办 3岁半幼儿便秘怎么办 小孩字写得难看怎么办 小孩的字写的丑怎么办 小孩字写的太差怎么办 小孩很多字不会写怎么办