设为首页 加入收藏

TOP

OpenGL超级宝典学习笔记——GLSL语言基础
2015-02-25 22:42:47 来源: 作者: 【 】 浏览:36
Tags:OpenGL 超级 宝典 学习 笔记 GLSL 语言基础

GLSL的变量命名方式与C语言类似。变量的名称可以使用字母,数字以及下划线,但变量名不能以数字开头,还有变量名不能以gl_作为前缀,这个是GLSL保留的前缀,用于GLSL的内部变量。当然还有一些GLSL保留的名称是不能够作为变量的名称的。


?


除了布尔型,整型,浮点型基本类型外,GLSL还引入了一些在着色器中经常用到的类型作为基本类型。这些基本类型都可以作为结构体内部的类型。如下表:


结构体


?


结构体可以组合基本类型和数组来形成用户自定义的类型。在定义一个结构体的同时,你可以定义一个结构体实例。或者后面再定义。


你可以通过=为结构体赋值,或者使用 ==,!=来判断两个结构体是否相等。


mySurface = secondSurface;


mySurface == secondSurface;


只有结构体中的每个成分都相等,那么这两个结构体才是相等的。访问结构体的内部成员使用. 来访问。


vec3 color = mySurface.color + secondSurface.color;


结构体至少包含一个成员。固定大小的数组也可以被包含在结构体中。GLSL的结构体不支持嵌套定义。只有预先声明的结构体可以嵌套其中。


?


GLSL中只可以使用一维的数组。数组的类型可以是一切基本类型或者结构体。下面的几种数组声明是合法的:


指定显示大小的数组可以作为函数的参数或者使返回值,也可以作为结构体的成员.数组类型内建了一个length()函数,可以返回数组的长度。


lightPositions.length() //返回数组的大小 8


最后,你不能定义数组的数组。


?


变量的声明可以使用如下的修饰符。


?


内置变量可以与固定函数功能进行交互。在使用前不需要声明。顶点着色器可用的内置变量如下表:


片段着色器的内置变量如下表:


?


?


GLSL语言的操作符与C语言相似。如下表(操作符的优先级从高到低排列)


像 求地址的& 和 解引用的 * 操作符不再GLSL中出现,因为GLSL不能直接操作地址。类型转换操作也是不允许的。 位操作符(&,|,^,~, <<, >> ,&=, |=, ^=, <<=, >>=)是GLSL保留的操作符,将来可能会被使用。还有求模操作(%,%=)也是保留的。


?


数组的下标从0开始。合理的范围是[0, size - 1]。跟C语言一样。如果数组访问越界了,那行为是未定义的。如果着色器的编译器在编译时知道数组访问越界了,就会提示编译失败。


vec4 myColor, ambient, diffuse[6], specular[6];


myColor = ambient + diffuse[4] + specular[4];


?


构造函数可以用于初始化包含多个成员的变量,包括数组和结构体。构造函数也可以用在表达式中。调用方式如下:


vec3 myNormal = vec3(1.0, 1.0, 1.0);


greenTint = myColor + vec3(0.0, 1.0, 0.0);


ivec4 myColor = ivec4(255);


还可以使用混合标量和向量的方式来构造,只要你的元素足以填满该向量。


vec4 color = vec4(1.0, vec2(0.0, 1.0), 1.0);


vec3 v = vec3(1.0, 10.0, 1.0);


vec3 v1 = vec3(v);


vec2 fv = vec2(5.0, 6.0);


float f = float(fv); //用x值2.5构造,y值被舍弃


对于矩阵,OpenGL中矩阵是列主顺序的。如果只传了一个值,则会构造成对角矩阵,其余的元素为0.


mat3 m3 = mat3(1.0);


构造出来的矩阵式:


1.0 0.0 0.0


0.0 1.0 0.0


0.0 0.0 1.0


mat2 matrix1 = mat2(1.0, 0.0, 0.0, 1.0);


mat2 matrix2 = mat2(vec2(1.0, 0.0), vec2(0.0, 1.0));


mat2 matrix3 = mat2(1.0);?


mat2 matrix4 = mat2(mat4(2.0)); //会取 4x4矩阵左上角的2x2矩阵。


构造函数可以用于标量数据类型的转换。GLSL不支持隐式或显示的转换,只能通过构造函数来转。其中int转为float值是一样的。float转为int则小数部分被丢弃。int或float转为bool,0和0.0转为false,其余的值转为true. bool转为int或float,false值转为0和0.0,true转为1和1.0.


float f = 1.7;


int I = int(f); // I = 1


数组的初始化,可以在构造函数中传入值来初始化数组中对应的每一个值。


ivec2 position[3] = ivec2[3]((0,0), (1,1), (2,2));


ivec2 pos2[3] = ivec2[]((3,3), (2,1), (3,1));


构造函数也可以对结构体进行初始化。其中顺序和类型要一一对应。


?


向量中单独的成分可以通过{x,y,z,w},{r,g,b,a}或者{s,t,p,q}的记法来表示。这些不同的记法用于顶点,颜色,纹理坐标。在成分选择中,你不可以混合使用这些记法。其中{s,t,p,q}中的p替换了纹理的r坐标,因为与颜色r重复了。下面是用法举例:


较特殊的使用方式,你可以重复向量中的元素,或者颠倒其顺序。如:


在赋值是,也可以选择你想要的顺序,但是不能重复其中的成分。


我们也可以通过使用下标来访问向量或矩阵中的元素。如果越界那行为将是未定义的。


float myY = myVec[1];


在矩阵中,可以通过一维的下标来获得该列的向量(OpenGL的矩阵是列主顺序的)。二维的小标来获得向量中的元素。


?


?


与C和C++相似,GLSL语言也提供了for, while, do/while的循环方式。使用continue跳入下一次循环,break结束循环。


?


?


片段着色器中有一种特殊的控制流成为discard。使用discard会退出片段着色器,不执行后面的片段着色操作。片段也不会写入帧缓冲区。


if (color.a < 0.9)


?


在每个shader中必须有一个main函数。main函数中的void参数是可选的,但返回值是void时必须的。


GLSL中的函数,必须是在全局范围定义和声明的。不能在函数定义中声明或定义函数。函数必须有返回类型,参数是可选的。参数的修饰符(in, out, inout, const等)是可选的。


结构体和数组也可以作为函数的参数。如果是数组作为函数的参数,则必须制定其大小。在调用传参时,只传数组名就可以了。


GLSL的函数是支持重载的。函数可以同名但其参数类型或者参数个数不同即可。


GLSL中函数递归是不被允许的。其行为是未定义的。


GLSL中提供了许多内建的函数,来方便我们的使用。可以在官方手册中查找相关的函数http://www.opengl.org/sdk/docs/man/


GLSL指南 http://www.opengl.org/registry/doc/GLSLangSpec.Full.1.20.8.pdf


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇OpenGL超级宝典学习笔记——新的.. 下一篇OpenGL超级宝典学习笔记——顶点..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: