转载自:http://www.cppblog.com/init/archive/2011/11/20/160579.aspx
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就可以自动的把这两个数值连接起来