渲染管线
渲染管线有时也被称为渲染流水线,一般是由显示芯片(GPU)内部处理图形信号的并行处理单元组成。这些并行处理单元两两之间是相互独立的,在不同型号的硬件上独立处理单元的数量也有很大的差异。一般越高端的硬件,其中独立处理单元的数量也就越多。
顶点着色器:顶点着色器是一个可编程的处理单元。(接收顶点缓存对象的顶点数据,单独处理每个顶点。)
功能:为执行顶点的变换、光照、材质的应用与计算等顶点的相关操作,其每顶点执行一次。
工作过程为:首先将原始的顶点几何信息及其他属性传递到顶点着色器中,经过自己开发的顶点着色器处理后产生纹理坐标、颜色、点位置等后继流程需要的各项顶点属性信息,然后将其传递给图元装配阶段。
(1) 顶点着色器的输入主要为待处理顶点相应的 attribute(属性) 变量、uniform(全局) 变量、采样器以及临时变量,输出主要为经过顶点着色器后生产的varying(易变) 变量及一些内建输出变量。
(2) attribute 变量指的是3D物体中每个顶点各自不同的信息所属的变量,一般顶点的位置、颜色、法向量等每个顶点各自不同的信息都是以attribute 变量的方式传入顶点着色器的。
片元着色器:片元着色器是用于处理片元值及其相关数据的可编程单元,其可以执行纹理的采样,颜色的汇总,计算雾颜色等操作,每片元执行一次。
功能:是通过重复执行(每片元一次),将3D物体中的图元光栅化后产生的每个片元的颜色属性计算出来送入后继阶段,如剪裁测试、深度测试及模板测试等。
细分着色器:接收来自顶点着色阶段的输出数据,并对收到的数据进一步处理。(用Patch描述一个物体的形状,在OpenGL管线内部生成新的几何体,并且模型的外观也会变得更加平顺,细分着色器会用到两个阶段来分别管理Patch数据,并生成最终状态)。
几何着色器:在管线内部会对所有的图元进行修改,改变几何图元的类型,或者放弃所有的几何体。如果启用,那么输入可能会来自顶点着色阶段完成的几何图元,也可能来自细分阶段的图元数据。
光栅化:将输入图元的数学描述转换为与屏幕位置对应的像素片元。
-数据类型概述
标量
向量
向量类型 | 说明 |
---|---|
vec2 | 包含了2个浮点数的向量 |
vec3 | 包含了3个浮点数的向量 |
vec4 | 包含了4个浮点数的向量 |
向量类型 | 说明 |
---|---|
ivec2 | 包含了2个整数的向量 |
ivec3 | 包含了3个整数的向量 |
ivec4 | 包含了4个整数的向量 |
向量类型 | 说明 |
---|---|
bvec2 | 包含了2个布尔数的向量 |
bvec2 | 包含了3个布尔数的向量 |
bvec2 | 包含了4个布尔数的向量 |
向量的运算
vec4 a; vec4 b;
a-b :A和B分量相减
加长取短
加长:vec2 a;
vec4 c=vec4( a,1000,2 );
取短 :vec4 rgba;
vec3 rgb=vec3( rgba.rgb);
矩阵
特点:先填充列,然后填充行。
矩阵类型 | 说明 |
---|---|
mat2 | 2 x 2 的浮点矩阵 |
mat3 | 3 x 3 的浮点矩阵 |
mat4 | 4 x 4 的浮点矩阵 |
- | - | - |
---|---|---|
1 | 4 | 7 |
2 | 5 | 8 |
3 | 6 | 9 |
mat3 m = mat(1,2,3,4,5,6,7,8,9);
mat3 m = mat(vec3(1,2,3), vec3(4,5,6), vec3(7,8,9));
采样器:采样器是着色器语言中不同于C语言的一种特殊的基本数据类型,其专门用来进行纹理采样的相关操作。一般情况下,一个采样器变量代表一幅或一套纹理贴图。
其具体情况如下表:
采样器类型 | 说明 |
---|---|
sampler2D | 用于访问二维纹理 |
sampler3D | 用于访问三维纹理 |
samplerCube | 用于访问立体贴图纹理 |
特点
1. 采样器变量不能再着色器中初始化。
2. 一般情况下采样器变量都用uniform限定符来修饰,从寄主语言(如java)接收传递进着色器的值。
3. sampler3D 并不是在所有的OpenGL ES 实现中都支持,因此,如要使用必须首先在着色器代码中进行设置,打开相应的扩展。
结构体
结构体:OpenGL ES 着色器还提供了类似于c语言中的用户自定义结构体,同样也是使用struce关键字进行声明,基本用法如下所示。
struct info{ //声明一个结构体info
vec3 color; //颜色成员
vec3 position; //位置成员
vec2 textureCoor; //纹理坐标成员
}
声明了info类型的结构体之后,就可以像使用内健数据类型一样使用 这 个用户自定义的数据类型了,如:
info CubeInfo; //声明了一个info类型的变量CubeInfo
对于结构体来说,其他的使用方法都与C语言基本类似。
数组
声明数组的方式:
vec3 position[20]; //声明了一个包含20个vec3的数组,索引从0开始。
在声明数组时,也可以不指定数组的大小,但是必须符合下列两种情况之一。
引用数组之前,要再次使用第一种声明方式来声明该数组,具体代码如下:
vec3 position[]; //声明了一个大小不定的vec3型数组。
vec3 pisition[]5; //再次声明该数组,并且指定大小。
提示:再次声明数组,指定大小之后,就不能再进行声明了。
代码中访问数组的下标都是编译时常量(如:字面常量),这时编译器会自动创建适当大小的数组,使得数组尺寸足够存储编译器看到的最大索引值对应的元素,代码如下:
vec3 position[]; //声明了一个大小不定的vec3型数组。
pisition[3] = vec3(3.0);//position需要为一个大小为4的数组
position[20] = vec3(6.0);//position需要为一个大小为21的数组
说明:上述代码的第2行需要尺寸为4的数组,代码的第3行需要尺寸为21的数组,若后面没有更大的下标出现,则编译器自动创建position为尺寸21的数组。这种由系统量体裁衣、自动分配的方法若恰当采用可以提高硬件的使用效率,降低对硬件资源的消耗。
类型修饰符
修饰符 | 说明 |
---|---|
in | 输入变量 |
out | 输出变量 |
inout | 输入输出变量 |
attribute | 一般用于每个顶点都各不相同的量,如顶点位置、颜色等(只能修饰顶点着色器的变量) |
uniform | 一般用于对同一组顶点组成的单个3D物体中所有顶点都相同的量,如当前的光源位置 {一致变量修饰符,(顶点和片元都可以用)} |
varying | 用于从顶点着色器传递到片元着色器的量(如果说要传递,变量名一致) |
const | 用于声明常量 |
OpenGL ES 中支持的绘制方式大致分3类,包括点、线段、三角形,每类中包含一种或多种具体的绘制方式,各种具体绘制方式的说明如下所列。
① GL_POINTS:点类下唯一的绘制方式,用来绘制点。
② GL_LINES:将着色器传入的顶点按顺序两个一组来绘制成线段。
③ GL_LINES_STRIP:按照顶点顺序连接顶点。(不封口)
④ GL_LINES_LOOP:按照顶点顺序连接顶点,并将第一个顶点和最后一个顶点相连。(封口)
⑤ GL_TRIANGLES:按照顶点顺序每3个点组成三角形进行绘制。
⑥ GL_TRIANGLE_STRIP:顶点按照顺序依次组织成三角形进行绘制, 最后实际形成的是一个三角形带。若有 N个顶点将绘制出n-2个三角形 (节省顶点空间)
⑦ GL_TRIANGLE_FAN:将第一个点作为中心点其他点作为边缘点,绘制一系列组成扇形的相邻三角形
⑧ glDrawArrays:按照传入渲染管线顶点本身的顺序及选用的绘制方式将顶点组织成图元进行绘制。称之 为顶点法( 特点:方便 ,但是出现了很多的重复顶点。 )
⑨ glDrawElements:绘制时不但要将顶点序列传入渲染管线,还需要将索引序列传入管线,绘制时跟据索引序列取出顶点值,并根据当前选用的绘制方式组织成图元。
区别:
用GL_TRIANGLES绘制方式(绘制一个正方形)
1.glDrawArrays需要6个顶点
2.glDrawElements需要四个顶点
四、纹理映射
纹理映射的原理
① 为顶点指定纹理坐标;
② 通过纹理坐标在纹理图上确定纹理区域;
③ 将选定的区域根据纹理坐标映射到图元上。
纹理的注意事项
① 纹理坐标用浮点数来表示,范围一般从0.0~1.0;
② 规定纹理的图片的宽高必须是2的n次方;
纹理拉伸和截取
两种拉伸方式的概述
无论是 S 轴还是 T 轴的纹理坐标都是在0.0~1.0中,这满足了大多数情况。但是在特定的情况下,也可以设置大于1的纹理坐标。当纹理坐标大于1以后,设置的拉伸方式就会起作用了。下面对两种拉伸方式进行单独介绍:
(1) 重复拉伸方式
如果设置的拉伸方式为重复,当顶点纹理坐标大于1时则实际起作用的纹理坐标为纹理坐标的小数部分。也就是说若纹理坐标为3.3,则起作用的纹理坐标为0.3,这种情况下会产生重复的效果。如下图所示:
//重复拉伸
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D
,GLES20.GL_TEXTURE_WRAP_S //设置S轴的拉伸方式为重复
,GLES20.GL_REPEAT);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D
,GLES20.GL_TEXTURE_WRAP_T //设置S轴的拉伸方式为重复
,GLES20.GL_REPEAT);
重复拉伸的方式在很多大场景地形的纹理贴图中很有作用,如将大块地面重复铺满草皮纹理、将大片水面重复铺满水波纹等。如果没有重复拉伸方式,则开发人员只能将大块面积切割为一块一块的小面积矩形,对每一块矩形单独设置0.0 ~ 1.0 内的纹理坐标。这样开发不但繁琐,而且大大增加了顶点的数量,程序运行的效率也会受到很大的影响。因此开发中要注意重复拉伸方式的灵活运用,可以使用重复拉伸方式时就不要去无畏地增加顶点数量了。
(2) 截取拉伸方式
截取拉伸方式中当纹理坐标的值大于1时都看作 1,因此会产生边缘被拉伸的效果。具体情况如下图所示。
从图中可以看出,需要纹理映射的矩形中4个顶点纹理坐标分别为(0,0)、( 4,0)、(0,4)、( 4,4),因此矩形中的各片元纹理坐标范围为S 轴方向 0 ~ 4,T 轴方向0 ~ 4.由于在此种拉伸方式下,大于1的纹理坐标都看作1,因此产生了纹理横向和纵向边缘被拉伸的效果。
//截取拉伸
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_S,//设置S轴的拉伸方式为截取
LES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_T,//设置T轴的拉伸方式为截取
LES20.GL_CLAMP_TO_EDGE);
所谓纹理采样就是:根据片元的纹理坐标到纹理图中提取对应位置颜色的过程。但是由于被渲染图元中的片元中的片元数量与其对应纹理区域中像素的数量并不一定相同,也就是说图元中的片元与纹理图中的像素并不总是–对应的。
例如,将较小的纹理图映射到较大的图元或将较大的纹理映射到较小的图元时这种情况就会产生。因此通过纹理坐标在纹理图中并不一定能找到与之完全对应的像素,这时候需要采用一些策略使得纹理采样可以顺利进行下去。通常采用的策略有最近点采样、线性采样两种。
最近点采样
线性纹理采样
MIN 与 MAG 采样
生成一个脚注1.
[TOC]