WebGL-Shader入门(4.着色器语言GLSL ES函数定义与流程控制)
Posted 点燃火柴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WebGL-Shader入门(4.着色器语言GLSL ES函数定义与流程控制)相关的知识,希望对你有一定的参考价值。
1. 函数定义
1.1 函数结构
GLSL ES 的函数定义与C语言接近,基本构成包括返回类型、函数名、参数和函数体,具体结构如下
返回类型 函数名 (type0 arg0, type1 arg1, ...,typen argn) {
函数计算
return 返回值;
}
函数如果没有返回值,函数中就不需要return语句,这时函数的返回值类型必须是 void,如果函数的返回值是结构体类型,需要注意结构体的成员中不能有数组
接下来看一个将RGBA颜色值转化为亮度值的函数
float getBrightness (in vec3 color) {
return 0.231 * color.r + 0.752 * color.g + 0.032 * color.b
}
//调用
attribute vec3 a_Color;
void main(){
...
float brightness = getBrightness (a_Color);//将计算结果赋值给brightness
...
}
注意,如果调用是传入的参数类型与声明函数是指定的参数类型不一致,就会报错
1.2 规范声明
与C语言一样,如果函数定义在其调用之后,那么必须在进行调用前先声明该函数的规范,规范声明预先告诉WebGL系统函数的参数、参数类型、返回值等信息,具体请参数如下代码
float luma(vec3);//规范声明
void main(){
...
float brightness = luma(a_Color);//将计算结果赋值给brightness
...
}
float luma(in vec3 color) {
return 0.231 * color.r + 0.752 * color.g + 0.032 * color.b
}
2 流程控制
着色器中的流程控制与C和javascript语言中的流程控制几乎无异,主要是通过if语句和for语句等控制流程
2.1 if语句
if语句有三种控制流程的语句模型,分别是 if 模型、 if…else… 模型 和 if…else if…else 模型
if 模型
if(x>10){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);//红色
}
if…else… 模型
if(distance < 0.4){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);//红色
}else {
gl_FragColor = vec4(0.0,0.0,1.0,1.0);//蓝色
}
if…else if…else 模型
if(distance > 0.1){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);//红色
}else if (distance < 0.2) {
gl_FragColor = vec4(0.0,0.0,1.0,1.0);//蓝色
}else if (distance < 0.4) {
gl_FragColor = vec4(0.0,1.0,0.0,1.0);//绿色
}else {
gl_FragColor = vec4(0.0,0.0,0.0,1.0);//黑色
}
GLSL ES中没有switch语句,在程序中避免过多的使用if语句,否则会影响效率
2.2 for语句
大多数循环程序都是通过for语句实现的,GLSL ES 语言也一样,for 语句的格式如下
for (初始化表达式;条件表达式;循环步进表达式){
重复执行的语句;
}
GLSL ES 语言的for循环的循环变量有一些特殊的限制,具体如下
- 一个for循环中只允许有一个循环变量,且只能是int类型或float类型
- 循环步进表达式必须是以下的形式中的一种,i++,i–,i+=常量表达式,i-=常量表达式
- 条件表达式必须是循环变量与整形常量的比较
- 循环体内,循环变量不可以被赋值
来一个最简单的for循环示例,对5以内的整数求和
for(int i = 0; i < 5; i++){
sum += i;
}
2.3 continue、break语句
通常情况下,我们会在for语句中使用continue语句来跳过本次循环,使用break语句终止循环
for (var i = 0; i < 30; i++) {
...
if(i==15){
continue;//跳过循环体余下的部分,直接进入下次循环
}
//当i==15时,这部分代码不会执行
...
}
for (var i = 0; i < 20; i++) {
...
if(i==18){
break;//直接终止循环执行,跳出for循环
}
...
}
2.4 discard语句
与其他语言不一样的是,GLSL ES语言 提供了discard语句。discard语句只能在片元着色器中使用,表示放弃当前片元直接处理下一个片元,作用与continue类似。请参照以下代码
//片元着色器
var FSHADER_SOURCE = '' +
'#ifdef GL_ES\\n' +
' precision mediump float;\\n' + // 设置float类型默认精度
'#endif\\n' +
'varying vec4 v_Color;\\n' + //声明varying变量v_Color,用来接收顶点着色器传送的片元颜色信息
'void main(){\\n' +
' float d = distance(gl_PointCoord, vec2(0.5, 0.5));\\n' + //计算像素距离中心点的距离
' if(d < 0.5) {\\n' + //距离大于0.5放弃片元,小于0.5保留片元
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\\n' +
' } else { discard; }\\n' + //跳过当前片元直接处理下一个片元
'}\\n'
以上是关于WebGL-Shader入门(4.着色器语言GLSL ES函数定义与流程控制)的主要内容,如果未能解决你的问题,请参考以下文章
WebGL-Shader入门(2.着色器语言GLSL ES矢量和矩阵的访问与运算)
WebGL-Shader入门(3.着色器语言的限定词-参数限定词/存储限定词/精度限定词)
WebGL-Shader入门(6.着色器语言GLSL ES 预处理指令和宏定义)
WebGL-Shader入门(5.着色器语言GLSL ES 内置变量和内置函数)