文章目录

  • 前言
  • 分支和循环
    • 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)规范 ——下篇相关推荐

  1. OpenGL ES着色器语言之语句和结构体(官方文档第六章)内建变量(官方文档第七、八章)...

    OpenGL ES着色器语言之语句和结构体(官方文档第六章) OpenGL ES着色器语言的程序块基本构成如下: 语句和声明 函数定义 选择(if-else) 迭代(for, while, do-wh ...

  2. OpenGL ES着色器语言之变量和数据类型

    所有变量和函数在使用前必须声明.变量和函数名是标识符. 没有默认类型,所有变量和函数声明必须包含一个声明类型以及可选的修饰符.变量在声明的时候首先要标明类型,后边可以跟多个变量,之间用逗号隔开.很多情 ...

  3. OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章)

    OpenGL ES着色器语言之变量和数据类型(二)(官方文档第四章) 4.5精度和精度修饰符 4.5.1范围和精度 用于存储和展示浮点数.整数变量的范围和精度依赖于数值的源(varying,unifo ...

  4. OpenGLES2.0着色器语言glsl

    OpenGLES2.0中是强制使用可编程的渲染管线的,使用的是glsl着色器语言,因为着色器语言是使用的GPU,即图形处理单元,而不是CPU,这样可以使CPU从繁重的几何计算和像素的处理中解脱出来了. ...

  5. OpenGL着色器语言GLSL语法总结

    GLSL语法与C语言类似. 1.变量类型 基础类型:bool,int,uint,float,double与C语言的类型类似. 向量类型:vecN,bvecN,ivecN,uvecN,dvecN,N表示 ...

  6. 图片处理之着色器语言 GLSL (opengl-shader-language) 内建函数

    内建函数基本上可以分为一下三类: (1)它们使用一些简便的方式提供必要的硬件功能,如材质贴图.这些函数单独通过着色器是无法模拟出来的. (2)它们展示了一些可以常简单的写入的繁琐操作(clamp, m ...

  7. OpenGL学习——着色器

    基于上一个 你好,三角形 的代码绘制修改点击蓝色字体查看 着色器 给三角形换色 三角形变换颜色 五彩三角形 给三角形换色 如果我们打算从一个着色器向另一个着色器发送数据,我们必须在发送方着色器中声明一 ...

  8. GLSL三种基本类型(着色器语言三种变量)

    着色器语言和C语言一样,通过一个表示特定数据类型的关键词声明一个变量,比如int num;通过int关键字声明一个整数型变量num,不过着色器语言还提供了三个关键字attribute.uniform和 ...

  9. OpenGL编译着色器

    1.读入着色器的代码 一般着色器的代码可以写在raw下创建glsl文件. gls是openGL的着色语言. 1.1.顶点着色器 定义的每个单一的顶点,顶点着色器都会调用一次,当他被调用的时候,会在a_ ...

最新文章

  1. EngineRoot是在哪里定义的?
  2. 排序算法学习——冒泡排序
  3. 使用观察者模式在 Silverlight 中切换用户控件
  4. 聚类(part1)--聚类概述
  5. Python高级特性:迭代器和生成器
  6. Dart语言精简入门介绍
  7. 对vector中的数据排序
  8. Oracle中insert into select和select into的区别
  9. VS恢复调试时出现的确认对话框
  10. 测试用例设计技术之一等价类法
  11. 交叉编译 -sh: ./xxx: not found 的问题
  12. python整数转换成英文表示
  13. 用Spotlight实时监控Windows Server 08
  14. Linux常用命令——nethogs命令
  15. HorNet+YOLOv5改进方案
  16. django2.1.7从0开始搭建一个个人博客网站第5天
  17. java 断网处理_如何处理浏览器的断网情况?
  18. TP-link WR703N v1.17固件不拆机绕过RSA验证强刷openwrt
  19. 随机抽人名小程序_这些好用的微信小程序,你知道多少?
  20. Python使用ffmpeg合成视频、音频

热门文章

  1. Logitech Options改变设备顺序
  2. Jmeter 录制脚本碰到的代理服务器拒绝连接
  3. ps与pstree小结
  4. 如果让你做技术负责人,你会怎么设计后端架构?
  5. python3安装requests库
  6. 改变eclipse的主题,使用IDEA的黑色主题
  7. 从油漆罐到协作型BPM
  8. 5月8号粉笔資料分析2
  9. Java网络编程(二) 连续发送数据
  10. 发那科机器人GI分配_发那科机器人的正确操作方法及步骤