OpenGL ES着色器语言(GLSL ES)规范 ——下篇
文章目录
- 前言
- 分支和循环
- if、if-else
- for
- continue、break、discard
- 着色器内置变量
- 函数
- 函数定义
- 规范声明
- webgl内置函数
- 存储限定字
- const
- attribute
- uniform
- varying
- 精度限定字
- 预处理指令
- 总结
前言
本篇接上文继续对着色器语言规范进行讲解,本文的内容包括:分支和循环、着色器内置变量、函数、存储限定字、精度限定字、预处理指令等,接OpenGL ES着色器语言(GLSL ES)规范 ——上篇。
分支和循环
GLSL ES也支持分支循环相关的方法,用法与javascript几乎一致,为数不多的区别是GLSL ES中没有switch关键字,多了discard关键字
if、if-else
if、if-else过多时会影响着色器执行速度,应合理使用。
// 顶点着色器const vertex = `attribute vec4 aPosition;varying vec4 vCoordvoid main() {vCoord = aPosition;gl_Position = aPosition;gl_PointSize = 10.0;}`// 片元着色器const fragment = `precision highp float;varying vec4 vCoordvoid main(){if (vCoord.x > 0.5) {gl_FragColor = vec4(1.0,1.0,1.0,1.0);} else {gl_FragColor = vec4(0.0,0.0,0.0,1.0);} }`
for
`void main() {for (int i = 0; i < 3; i++) {sum += i}}`
continue、break、discard
- continue表示终止当前循环并跳到下一个循环
- break表示终止当前循环并跳出整个循环
- discard只能出现在片元着色器中,表示终止处理当前片元跳到下一个片元
着色器内置变量
webgl中内置了一些变量可以直接在着色器中使用:
webgl中的变量 | 类型 | 含义 |
---|---|---|
gl_PointSize | float | 绘制点时,正方形的边长 |
gl_Position | vec4 | 顶点裁剪坐标值 |
gl_FragColor | vec4 | 片元颜色值 |
gl_FragCoord | vec2 | 片元在屏幕上的像素坐标 |
gl_PointCoord | vec2 | 点渲染模式对应点像素坐标 |
函数
函数定义
函数的定义与C语言的样式很类似,注意除非定义函数时声明了void,否则函数必须有返回值,而且GLSL ES中的函数不允许递归调用(闭包)。
// 旋转函数
vec2 rotate(vec2 uv, float rotation, vec2 mid) {return vec2(cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x, cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y);
}// 使用该函数
vec2 rotateUv = rotate(vUv,3.14*0.25,vec2(0.5,0.5));
float rbga = 1.0-rotateUv.y;
gl_FragColor =vec4(rbga,rbga,rbga,1);
规范声明
如果函数在其定义前就先被使用也是可以的,这时候要提前对函数进行规范声明
//旋转函数声明
vec2 rotate(vec2, float, vec2) // 旋转函数使用
vec2 rotateUv = rotate(vUv,3.14*0.25,vec2(0.5,0.5));
float rbga = 1.0-rotateUv.y;
gl_FragColor =vec4(rbga,rbga,rbga,1);// 旋转函数定义
vec2 rotate(vec2 uv, float rotation, vec2 mid) {return vec2(cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x, cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y);
}
webgl内置函数
webgl内部将一些常用的函数开放了出来,函数的返回类型取决于参数类型。
- 角度函数
名称 | 类型 | 含义 |
---|---|---|
radians() | float / vec | 角度转弧度 |
degrees() | float / vec | 弧度转角度 |
- 三角函数
名称 | 类型 | 含义 |
---|---|---|
sin() | float / vec | 弧度的正弦值 |
cos() | float / vec | 弧度的余弦值 |
tan() | float / vec | 弧度的正切值 |
asin() | float / vec | 反正弦值 |
acos() | float / vec | 反余弦值 |
atan() | float / vec | 反正切值 |
- 指数函数
名称 | 类型 | 含义 |
---|---|---|
pow(a,n) | float / vec | a的n次方 |
exp(n) | float / vec | 自然底数e的n次方 |
log(n) | float / vec | 以e为底n的对数 |
exp2(n) | float / vec | 2的n次方 |
log2(n) | float / vec | 以2为底的n的对数 |
sqrt(n) | float / vec | 对n开平方 |
inversesqrt(n) | float / vec | 对n开平方并取倒数 |
- 通用函数
名称 | 类型 | 含义 |
---|---|---|
abs(x) | float / vec | x的绝对值 |
sign(x) | float / vec | x的绝对值,正数返回1.0,负数返回-1.0,否则返回0.0 |
floor(x) | float / vec | 向下取整 |
ceil(x) | float / vec | 向上取整 |
fract(x) | float / vec | 获取小数部分 |
mod(x,y) | float / vec | 返回x/y的模 |
max(x,y) | float / vec | 返回x和y中的较大值 |
clamp(x,minVal,maxVal) | float / vec | 将一个值限制在一个上限和下限之间,min(max(x, minVal), maxVal) |
mix(x,y,r) | float / vec | 线性内插,mix(x,y,r) = (1-r)*x +yr |
step(edge,a) | float / vec | 阶梯函数,a<edge返回0.0,否则返回1.0 |
smoothstep(edge1,edge2,a) | float / vec | 艾米内内插步进,a<edge1返回0.0,a>edge2返回1.0,edge2>a>edge1返回艾米内插值结果 |
- 几何函数
名称 | 类型 | 含义 |
---|---|---|
length(v) | float | 矢量v的长度 |
distance(p0,p1) | float | 返回p0和p1之间的距离 |
dot(x,y) | float | 返回x和y之间的内积/点乘 |
cross(x,y) | vec | 返回x和y之间的外积/叉乘 |
normalize(x) | float/vec | 向量归一化为单位向量 |
faceforward(N,I,Nref) | float/vec | 法向量反向 |
reflect(I,N) | float/vec | 根据入射向量I和表面法向量N(单位向量)计算反射向量 |
refract(I,N,eta) | float/vec | 根据入射向量I和表面法向量N(单位向量),折射率eta计算折射向量 |
- 矩阵函数
名称 | 类型 | 含义 |
---|---|---|
matrixCompMult(mat1, mat2) | mat2/mat3/mat4 | 矩阵对应位置上的元素相乘,返回新的矩阵 |
- 矢量函数
名称 | 类型 | 含义 |
---|---|---|
lessThan(vec1, vec2) | bvec2/bvec3/bvec4 | 逐分量比较vec1 < vec2 是否成立 |
lessThanEqual(vec1, vec2) | bvec2/bvec3/bvec4 | 逐分量比较vec1 <= vec2 是否成立 |
greaterThan(vec1, vec2) | bvec2/bvec3/bvec4 | 逐分量比较vec1 > vec2 是否成立 |
greaterThanEqual(vec1, vec2) | bvec2/bvec3/bvec4 | 逐分量比较vec1 >= vec2 是否成立 |
equal(vec1, vec2) | bvec2/bvec3/bvec4 | 逐分量比较vec1 = vec2 是否成立 |
notEqual(vec1, vec2) | bvec2/bvec3/bvec4 | 逐分量比较vec1 != vec2 是否成立 |
any(vec) | bool | vec任意分量为true,返回true |
all(vec) | bool | vec全部分量为true,返回true |
not(vec) | bool | 逐分量取补 |
- 纹理查询函数
sampler2D: 使用纹理坐标coord,从当前绑定到sampIer的二维纹理中读取相应的纹素。对于投影版本(带有Poj的),纹理坐标将从cood的最后一个分量中解析出来,而vec4类型的 coord的第3个分量将被忽略。参数bias只可在片元着色器中使用,它表示在sampIer是 MIPMAP纹理时,加在当前 lod上的值。如下:
名称 | 类型 |
---|---|
texture2D(sampler2D sampler,vec2 coord) | vec4 |
texture2D(sampler2D sampler,vec2 coord,float bias) | vec4 |
texture2DProj(sampler2D sampler, vec3 coord) | vec4 |
texture2DProj(sampler2D sampler,vec3 coord, float bias) | vec4 |
texture2DProj(sampler2D sampler,vec4 coord) | vec4 |
texture2DProj(sampler2D sampler,vec4 coord, float bias) | vec4 |
texture2DLod(sampler2D sampler,vec2 coord, float lod) | vec4 |
vec4 texture2DProj(sampler2D sampler,vec4 coord, float bias) | vec4 |
texture2DProjLod(sampler2D sampler,vec3 coord, float lod) | vec4 |
texture2DProjLod(sampler2D sampler,vec4 coord, float lod) | vec4 |
samplerCube: 使用纹理坐标coord,从绑定到sampler的立方体纹理中读取响应纹素。coord的方向可用来指定立方体纹理的表面。如下:
名称 | 类型 |
---|---|
textureCube(samplerCube sampler, vec3 coord) | vec4 |
textureCube(samplerCube sampler, vec3 coord, float bias) | vec4 |
textureCubeLod(samplerCube sampler,vec3 coord, float lod) | vec4 |
存储限定字
在GLSL ES中,会经常使用attribute、uniform、varying来传递变量
const
首先来讲一下const变量,const代表一个不能改变的值,使用const时,需要同时对变量进行声明和初始化
const float PI 3.14;
const vec4 red (1.0, 0.0, 0.0, 1.0);
attribute
attribute变量只能在顶点着色器中使用,它是一个全局变量,被用来表示接收顶点信息。
attribute vec3 position; // 存储坐标信息
attribute vec2 uv; // 贴图坐标
attribute vec4 a_Color // 颜色
uniform
uniform变量既可以在顶点着色器中使用,也可以在片元着色器中使用,它也是一个全局变量,可以是除了数组与结构体的任何类型,在顶点着色器和片元着色器定义了同名uniform变量时会被二者共享,即会被所有顶点和片元共用,它可以被用来存储变换矩阵,时间纹理这种影响所有顶点的信息。
uniform mat4 modelMatrix; // 模型转换矩阵
uniform mat4 viewMatrix; // 视图矩阵
uniform mat4 projectionMatrix; // 投影矩阵
uniform float uTime; // 时间
varying
varying它也是一个全局变量,与uniform和attribute不同的是:他不是将javascript中的信息传给着色器,使用时必须同时在顶点着色器和片元着色器中定义同名同类型的varying变量,它的作用是把顶点着色器的数据传递给片元着色器,举例:
在顶点着色器,使用varying定义一个变量v_uv,它是二维向量类型,用它获取每个点的uv坐标
varying vec2 v_uv;
void main() {v_uv = uv;···
}
在片元着色器中接收来自顶点着色器中的uv信息,并把它作为rbga中的前俩个值
varying vec2 v_uv;
void main() {gl_FragColor = vec4(v_uv, 0.0, 1.0);
}
精度限定字
在GLSL中需要指定精度以提高运行效率,减少内存损耗,顶点着色器默认指定高精度,片元着色器需手动指定。可以在开头指定以下三个之一。
precision lowp float;
precision mediump float;
precision highp float;
预处理指令
GLSL ES支持预处理指令。预处理指令用来在真正编译之前对代码进行预处理,都以井号(#)开始。GLSL ES提供了三种预处理指令。
- #if
#if 条件表达式
If 条件表达式为真,执行这里
#endif
- #ifdef
#ifdef 某宏
如果定义了某宏,执行这里
#endif
- #ifndef
#ifdef 某宏
如果没有定义某宏,执行这里
#endif
宏的定义使用关键字 #define,解除宏定义使用 #undef
举例:
#define PI 3.1415926#ifdef PIprecision highp float#endif
总结
分支和循环
- if、if-else
- for
- continue、break、discard
着色器内置变量
函数
- 函数定义
- 规范声明
- webgl内置函数
存储限定字
- const
- attribute
- uniform
- varying
精度限定字
预处理指令
OpenGL ES着色器语言(GLSL ES)规范 ——下篇相关推荐
- OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)...
OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...
- OpenGL ES着色器语言之变量和数据类型
所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符.变量在声明的时候首先要标明类型,后边可以跟多个变量,之间用逗号隔开.很多情 ...
- OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)
OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...
- OpenGLES2.0着色器语言glsl
OpenGLES2.0中是强制使用可编程的渲染管线的,使用的是glsl着色器语言,因为着色器语言是使用的GPU,即图形处理单元,而不是CPU,这样可以使CPU从繁重的几何计算和像素的处理中解脱出来了. ...
- OpenGL着色器语言GLSL语法总结
GLSL语法与C语言类似. 1.变量类型 基础类型:bool,int,uint,float,double与C语言的类型类似. 向量类型:vecN,bvecN,ivecN,uvecN,dvecN,N表示 ...
- 图片处理之着色器语言 GLSL (opengl-shader-language) 内建函数
内建函数基本上可以分为一下三类: (1)它们使用一些简便的方式提供必要的硬件功能,如材质贴图.这些函数单独通过着色器是无法模拟出来的. (2)它们展示了一些可以常简单的写入的繁琐操作(clamp, m ...
- OpenGL学习——着色器
基于上一个 你好,三角形 的代码绘制修改点击蓝色字体查看 着色器 给三角形换色 三角形变换颜色 五彩三角形 给三角形换色 如果我们打算从一个着色器向另一个着色器发送数据,我们必须在发送方着色器中声明一 ...
- GLSL三种基本类型(着色器语言三种变量)
着色器语言和C语言一样,通过一个表示特定数据类型的关键词声明一个变量,比如int num;通过int关键字声明一个整数型变量num,不过着色器语言还提供了三个关键字attribute.uniform和 ...
- OpenGL编译着色器
1.读入着色器的代码 一般着色器的代码可以写在raw下创建glsl文件. gls是openGL的着色语言. 1.1.顶点着色器 定义的每个单一的顶点,顶点着色器都会调用一次,当他被调用的时候,会在a_ ...
最新文章
- EngineRoot是在哪里定义的?
- 排序算法学习——冒泡排序
- 使用观察者模式在 Silverlight 中切换用户控件
- 聚类(part1)--聚类概述
- Python高级特性:迭代器和生成器
- Dart语言精简入门介绍
- 对vector中的数据排序
- Oracle中insert into select和select into的区别
- VS恢复调试时出现的确认对话框
- 测试用例设计技术之一等价类法
- 交叉编译 -sh: ./xxx: not found 的问题
- python整数转换成英文表示
- 用Spotlight实时监控Windows Server 08
- Linux常用命令——nethogs命令
- HorNet+YOLOv5改进方案
- django2.1.7从0开始搭建一个个人博客网站第5天
- java 断网处理_如何处理浏览器的断网情况?
- TP-link WR703N v1.17固件不拆机绕过RSA验证强刷openwrt
- 随机抽人名小程序_这些好用的微信小程序,你知道多少?
- Python使用ffmpeg合成视频、音频