depth testing(深度测试)的功能,启动它,OpenGL就可以跟踪在z轴上的像素。这样它只会在那个像素前方没有东西时,才会绘画这个像素。
///
限定符:
attribute表示修饰顶点属性的变量,这种类型的变量只能出现在vertex shader中,且为只读性性。
uniform表示修饰图元,帧的变量,这种类型的变量无论在vertex shader还是fragment shader中都是只读属性,不可写。
varying表示是可读可写的变量,在vertex shader只能写,在fragment shader中只能读,用于vertex shader与fragment shader传数据,并插值。
const是常量限定符,与c/c++中类似
GLSL语法跟C语言非常相似:
1.数据类型:
GLSL包含下面几种简单的数据类型
float
bool :false or ture
int
向量:
vec {2,3,4} 长度为2, 3, 4的float向量
bvec {2,3,4} 长度为2, 3, 4的bool向量
ivec {2,3,4} 长度为2, 3, 4的int向量
矩阵:
mat2 2*2的浮点矩阵
mat3 3*3的浮点矩阵
mat4 4*4的浮点矩阵
以上三种矩阵可以简写为mat2 mat3 mat4
矩阵的行和列并没有规定相等,因为可以使用mat2*3 mat 4*2等方法来声明行数和列数
一种特殊的数据类型:取样器--用于纹理采样
sampler1D 访问一个一维纹理
sampler2D 访问一个二维纹理
sampler3D 访问一个三维纹理
samplerCube 访问一个立方体纹理
sampler1DShadow 访问一个带对比的一维深度纹理
sampler2DShadow 访问一个带对比的二维深度纹理
GLSL提供了类似C语言的用户定义结构:
struct dirlight{
vec3 direction;
vec3 color;
};
变量限定符:
限定符赋给变量特殊的含义:
const-- 用于声明非可写的编译时常量变量
attribute-- 用于经常更改的信息,只可以再顶点着色器中使用
uniform-- 用于不经常更改的信息,用于顶点着色器和片元着色器
varying-- 用于慈宁宫顶点着色器传递到片元着色器的插值信息
控制流:
GLSL的控制流 与C++非常类似,可以使用for while以及do-while实现循环,也可以使用if和if-else进行选择,不过if语句中的变量声明,只是在最近的硬件中才提供
函数:
GLSL也提供了一些特殊的实现:
continue
break
discard --只可用于片元着色器,当控制流遇到这个关键字时,正在处理的片元就会被标记为将要丢弃
函数
main() 可以返回除了数组外的任何类型
对于函数的参数 可以使用下面几种限定符
in -- 复制进函数但不在返回时复制,在函数内部仍然是可写的
out--只在返回时复制,是可读的
inout 复制进函数并在返回时复制
如果没有指定限定符,默认情况下为in
函数可以通过参数类型重载,但是不能仅仅通过返回类型重载,同样,因为不会执行参数类型自动提升,所以调用函数时参数类型必须完全匹配
函数不能被递归调用
GLSL Vertex shader内置的输入变量,注意这些变量都是不可更改的
attribute vec4 gl_Color; 顶点数据字段的Diffuse颜色
attribute vec4 gl_SecondaryColor; 顶点数据字段的Specular颜色
attribute vec4 gl_Normal; 顶点法线
attribute vec4 gl_Vertex; 顶点位置
attribute vec4 gl_MultiTexCoord0; 8组贴图坐标
attribute vec4 gl_MultiTexCoord1;
attribute vec4 gl_MultiTexCoord2;
attribute vec4 gl_MultiTexCoord3;
attribute vec4 gl_MultiTexCoord4;
attribute vec4 gl_MultiTexCoord5;
attribute vec4 gl_MultiTexCoord6;
attribute vec4 gl_MultiTexCoord7;
attribute vec4 gl_MultiTexCoord0;
attribute vec4 gl_MultiTexCoord1;
attribute vec4 gl_FogCoord; 使用雾效果的参考数值
在编写shader时,可以把这些输入数据所代表的功能重新定义,名称只是用来让传入数据时有个规则可循而已,C++调用glVertexPointer所指到的vetex buffer数据,在GLSL中可以通过gl_Vertex变量来获得。
Vertex Shader的输出数据时使用的内置变量:
vec4 gl_posotion; 用来设置顶点转换到屏幕坐标的位置,Vertex Shader一定要去更新这个数值
float gl_pointSize; 是启动PointSprite功能时,用来设置矩形大小的数值
vec4 gl_ClipVertex; 如果启用了Clip Plane功能,gl_ClipVertex可以放入用来与Clip Plane平面做测试用的位置
下面的输出数据在Vertex Shader中用来输出数据,在Fragment Sahder也可以使用这些变量,但是是用来读取数据:
araying Vec4 gl_FrontColor; 对正面做不同的光照计算 ,这两组颜色分主要颜色和次要颜色 代表的是固管的Diffuse值
varying vec4 gl_BackColor; 背面
varying vec4 gl_FrontSecondDaryColor; 固管的Specular值
varying vec4 gl_BackSecondaryColor;
varying vec4 gl_TexCoord[gl_MaxTextureCoords]; glTextCoord[0]是指第0个贴图坐标
varying vec4 gl_FogFragCoord;
Fragment Sahder除了可以从上面几个所列出的变量获得内插结果外,还可以从另外两个内置变量得到一些无法从Vertex Shader获得的数值
vec4 gl_FragCoord; gl_FragCoorg.xy代表像素在Framebuffer画面的位置,gl_FragCoord.z代表这个店在做Z Buffer测试时所用的Z值
bool gl_FrontFacing; 可用来查询目前正在画的像素是来自三角形的正面还是来自他的背面
Fragment Shader的内置输出变量:
vec4 gl_FragColor; 代表画面所要填入的颜色
vec4 gl_FragData[gl_MaxDrawBuffers]; 用来填入画面的颜色,用在启用多个FrameBuffer时,调用gl_FragData填入画面颜色
vec4 gl_FragDepth; 用来指定Z Buffer测试时所使用的Z值,这样就可以不通过顶点内插得到的Z值
对于Vertex Shader来说,除了可通过内置变量来内插数值给Fragment Shader之外,也可以不通过内置变量,只要在Vertex Shader和Fragment Shader中声明相同名称的全局变量,GLSL就可以自动的把这两个数值连接起来
///
在OpenGL ES2.0 的世界,在场景中渲染任何一种几何图形,你都需要创建两个称之为“着色器”的小程序。
着色器由一个类似C的语言编写- GLSL这个世界有两种着色器(Shader):
- Vertex shaders – 在你的场景中,每个顶点都需要调用的程序,称为“顶点着色器”。假如你在渲染一个简单的场景:一个长方形,每个角只有一个顶点。于是vertex shader 会被调用四次。它负责执行:诸如灯光、几何变换等等的计算。得出最终的顶点位置后,为下面的片段着色器提供必须的数据。
- Fragment shaders – 在你的场景中,大概每个像素都会调用的程序,称为“片段着色器”。在一个简单的场景,也是刚刚说到的长方形。这个长方形所覆盖到的每一个像素,都会调用一次fragment shader。片段着色器的责任是计算灯光,以及更重要的是计算出每个像素的最终颜色。
下面我们通过简单的例子来说明。
代码:
attribute vec4 Position; // 1
attribute vec4 SourceColor; // 2
varying vec4 DestinationColor; // 3
void main(void) { // 4
DestinationColor = SourceColor; // 5
gl_Position = Position; // 6
}
解析:
- “attribute”声明了这个shader会接受一个传入变量,这个变量名为“Position”。在后面的代码中,你会用它来传入顶点的位置数据。这个变量的类型是 “vec4”,表示这是一个由4部分组成的矢量。
- 与上面同理,这里是传入顶点的颜色变量。
- 这个变量没有“attribute”的关键字。表明它是一个传出变量,它就是会传入片段着色器的参数。“varying”关键字表示,依据顶点的颜色,平滑计算出顶点之间每个像素的颜色。文字比较难懂,我们一图胜千言:图中的一个像素,它位于红色和绿色的顶点之间,准确地说,这是一个距离上面顶点55/100,距离下面顶点45/100的点。所以通过过渡,能确定这个像素的颜色.设置目标颜色 = 传入变量:SourceColor
- 设置目标颜色 = 传入变量:SourceColor
- gl_Position 是一个内建的传出变量。这是一个在 vertex shader中必须设置的变量。这里我们直接把 gl_Position = Position; 没有做任何逻辑运算。
一个简单的vertex shader 就是这样了,接下来我们再创建一个简单的fragment shader。
代码:
下面解析:varying lowp vec4 DestinationColor; // 1 void main(void) { // 2 gl_FragColor = DestinationColor; // 3 }
- 这是从vertex shader中传入的变量,这里和vertex shader定义的一致。而额外加了一个关键字: lowp。在fragment shader中,必须给出一个计算的精度。出于性能考虑,总使用最低精度是一个好习惯。这里就是设置成最低的精度。如果你需要,也可以设置成medp或者highp.
- 正如你在vertex shader中必须设置gl_Position, 在fragment shader中必须设置gl_FragColor.这里也是直接从 vertex shader中取值,先不做任何改变。