Shader 入门:GLSL ES(迭代、选择和跳转)
前言
在上一章节中我们说到了 GLSL ES 的【运算符和限定符】,那么本章节就来到了【迭代、选择和跳转】的内容。
上一篇:《Shader 入门:GLSL ES(运算符和限定符)》
写《Shader 入门:GLSL ES》系列文章主要目的为让没怎么接触过 GLSL ES 的读者快速入门这门语言。 同时我将默认读者有编程基础,不会对语言内容进行完全的讲解以节省篇幅。 *另外本系列文章中主要针对 GLSL ES 3.0 进行讲解
正文
迭代(Iteration)
循环语句(Loop Statement)
在 GLSL ES 中有以下 3 种循环语句:
for
首先执行初始化表达式,当条件表达式为 true 时执行循环体,之后再执行循环表达式,然后再次进行条件判断,循环往复,直到条件表达式为 false 时结束循环。
for (初始化表达式; 条件表达式; 循环表达式) {
// 循环体...
}
// 如下:
int a = 0;
for (int i = 0; i < 10; i++) {
a++;
}
// a = 10
while
只要条件表达式为 true 就执行循环体,直到条件表达式为 false 时结束循环。
while (条件表达式) {
// 循环体...
}
// 如下:
int a = 0;
while (a < 10) {
a++;
}
// a = 10
do-while
先执行一次循环体,之后只要条件表达式为 true 就继续执行循环体,直到条件表达式为 false 时结束循环。
do {
// 循环体...
} while (条件表达式)
// 如下:
int a = 0;
do {
a++;
} while (a < 0)
// a = 1;
?循环上限必须明确
需要注意的是,在 GLSL ES 循环语句的条件表达式中,循环的最大次数必须是明确的,如下面的栗子:
// 表达式使用常量
// int max = 20; // [×] 变量可被更改
const int max = 20; // [√] 常量不可被更改
for (int i = 0; i < max; i++) {
// ...
}
// 或者直接使用字面量
for (int j = 0; j < 20; j++) {
// ...
}
因为 GLSL ES 在编译时,编译器会对着色器代码中的 for 循环进行内联展开(Inline Expansion)以提高着色器的执行性能。
所以如果循环的次数不能确定的话就没有办法展开了呢~
选择(Selection)
选择语句(Selection Statement)
在 GLSL ES 中有以下三种选择语句:
if
当条件表达式为 true 时执行下方的语句块。
if (布尔表达式) {
// 语句...
}
// 如下:
int a = 0;
if (a == 0) {
a++;
}
// a = 1
if-else
当条件表达式为 true 时执行第一个语句块,为 false 时则执行 else 后面的语句块。
if (布尔表达式) {
// 语句...
} else {
// 语句...
}
// 如下:
int a = 0;
if (a == 1) {
a++;
} else {
a += 2;
}
// a = 2
switch(GLSL ES 3.0 新增)
switch 语句中的初始化表达式必须为整数,如果 case 标签的值与之相等,则执行标签后面的语句。
当没有匹配的 case 标签时,有 default 标签则执行 default 标签后面的语句,没有则跳过。
初始化表达式的类型必须与所有 case 标签的类型相等,可以使用的类型为
int
和uint
,且不会进行隐式类型转换(Implicit Type Conversion)。
switch (初始化表达式) {
case 常量表达式:
// 语句...
break;
// ...
default:
// 语句...
}
// 如下:
int a = 2;
switch (a) {
case 1:
a += 1;
break;
case 2:
a += 2;
break;
default:
a += 10;
}
// a = 4
⚡注意
过多的 if 或 if-else 语句会减慢着色器的执行速度,在着色器编写时需要注意这一点。
跳转(Jump)
跳转语句(Jump Statement)
在 GLSL ES 中有以下几种跳转语句:
continue
continue 只可用于循环中,执行该语句时会跳过最内层循环,并执行循环表达式(for 循环),然后执行下一次循环。
int a = 0;
for (int i = 0; i < 10; i++) {
if (i == 6) {
continue;
// 当 i 为 6 时不会执行后面的语句
}
a++;
}
// a = 9
break
break 可用于循环和 switch 语句中,执行该语句时将立即退出最内层循环,不再继续执行循环。
int a = 0;
for (int i = 0; i < 10; i++) {
if (i == 6) {
break;
// 当 i 为 6 时直接跳出循环
}
a++;
}
// a = 6
return
return 可以用在函数(Function)里的任何位置,执行该语句会直接跳出当前函数。如果 return 有表达式,则会返回表达式的值。
int plus(int a, int b) {
return a + b;
}
// int c = plus(1, 2);
// c = 3
discard
discard 只能在片元着色器(Fragment Shader)中使用,执行该语句将会直接跳出片元着色器,丢弃当前片元。
片元被丢弃之后就不会被渲染出来了,就好像是完全透明了一样~
void main() {
if (v_FragColor.a < 0.1) {
discard;
// 不透明度小于 0.1 时丢弃当前片元
// 不执行后面的语句
}
gl_FragColor = v_FragColor;
}
相关资料
OpenGL ES Registry(OpenGL ES 资料页)https://www.khronos.org/registry/OpenGL/index_es.php
OpenGL ES 3 Quick Reference Card(OpenGL ES 3 快速参考卡片)https://www.khronos.org/files/opengles3-quick-reference-card.pdf
GLSL ES Specification 3.00(GLSL ES 规范 3.0)https://www.khronos.org/registry/OpenGL/specs/es/3.0/GLSL_ES_Specification_3.00.pdf
OpenGL ES 3.0 Online Reference Pages(OpenGL ES 3.0 在线参考页)https://www.khronos.org/registry/OpenGL-Refpages/es3.0/
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Flutter中如何使用WillPopScope的示例代码
- Android实现音乐播放进度条传递信息的两种方式(在service和activity中)
- Flutter 中 Dart的Mixin示例详解
- Android Studio 实现九宫格功能
- Android user版通过adb_enable开启adb 调试 不提示对话框的流程分析
- Android实现圆线按钮进度效果
- Flutter 透明状态栏及字体颜色的设置方法
- Android实现带有进度条的按钮效果
- Android 自定义View实现多节点进度条功能
- android studio无法添加 bmob sdk依赖问题及解决方法
- Android自定义ToolBar并实现沉浸式的方法
- python初学者笔记—入门基础知识
- Android SurfaceView画板操作
- Android利用Andserver搭建服务器的详细教程
- 位运算处理进制转换问题