当前位置: 首页 > news >正文

WebGL系列教程八(GLSL着色器基础语法)

目录

  • 1 前言
  • 2 基本原则
  • 3 基本数据类型
  • 4 顶点着色器和片元着色器
    • 4.1 声明
    • 4.2 初始化项目
    • 4.3 赋值
  • 5 结构体
    • 5.1 声明
    • 5.2 赋值
  • 6 函数
    • 6.1 基本结构
    • 6.2 自定义函数
    • 6.3 常用内置函数
  • 7 精度
  • 8 其他
  • 9 总结

1 前言

  通过前七讲,我们已经见过了WebGL中的部分基础语法,这一讲我们来完善一下WebGL中的语法。GLSLOpenGL Shading Language的首字母缩写,表示的含义就是着色器语言。而我们在第一讲中就已经说过,WebGL中使用的是GLSLES版本,ESEmbedded Systems,意为嵌入式系统。因为最初GLSL ES是给嵌入式设备准备的,轻量级的三维图形渲染语言。为了方便,下文统称为GLSL

2 基本原则

  1.GLSL是大小写敏感的。
  2.GLSL每个语句结束时必须在结尾加上分号。
  3.变量名由a-z、A-Z、0-9和下划线组成。
  4.变量名不能gl_、webgl_、_webgl_开头。
  5.变量名不能和关键字冲突,即不能叫做attribute、uniform等。
  6.GLSL是强类型语言,声明时不能以var开头,必须以对应的类型开头。

3 基本数据类型

int i = 8;//整型
float m = 8.0;//浮点型
bool b = false;//布尔型
vec2 v2 = vec2(1.0,2.0);//浮点型二维向量
vec3 v2 = vec3(1.0,2.0,3.0);//浮点型三维向量
vec4 v = vec4(1.0,2.0,3.0,4.0);//浮点型四维向量
//访问时用xyzw、stpq、rgba、【0123】都可以访问
//v.x 和 v.s 以及 v.r , v[0] 表达的是同一个分量。
//v.y 和 v.t 以及 v.g , v[1] 表达的是同一个分量。
//v.z 和 v.p 以及 v.b , v[2] 表达的是同一个分量。
//v.w 和 v.q 以及 v.a , v[3] 表达的是同一个分量。
vec4(v.rgb, 1)vec4(v.r, v.g, v.b, 1)//等价
vec4(1)vec4(1, 1, 1, 1)//等价
vec4 s = sin(v);和vec4 s = vec4(sin(v.x), sin(v.y), sin(v.z), sin(v.w));//等价
ivec2 iv2 = ivec2(1,2);//整型二维向量
ivec3 iv3 = ivec3(1,2,3);//整型三维向量
ivec4 iv4 = ivec4(1,2,3,4);//整型四维向量
bvec2 bv2 = bvec2(false,true);//布尔型二维向量
bvec3 bv3 = bvec3(false,true,false);//布尔型三维向量
bvec4 bv4 = bvec4(false,true,false,true);//布尔型四维向量
mat2 = mat2(1.0,1.0                         //【1.0,2.02.0,2.0);//2*2的矩阵,列主序,即相当于  1.0,2.0】,mat3,mat4同理
mat3 = mat3(1.0,1.0,1.02.0,2.0,2.0,3.0,3.0,3.0);//3*3的矩阵
mat4 = mat4(1.0,1.0,1.0,1.0,2.0,2.0,2.0,2.0,3.0,3.0,3.0,3.0,4.0,4.0,4.0,4.0);/4*4的矩阵

4 顶点着色器和片元着色器

4.1 声明

//顶点着色器
<script id="vertex-shader" type="x-shader/x-vertex">//声明属性attribute vec4 a_Position;attribute vec4 a_Color;//声明全局变量,一旦赋值,就不可更改了uniform mat4 uRotateMatrix;//声明要传递到片元着色的变量varying vec4 v_Color;void main(){gl_Position =  uRotateMatrix * a_Position;v_Color = a_Color;v_TexCoord = a_TexCoord;}
</script>
//片元着色器
<script id="fragment-shader" type="x-shader/x-fragment">precision highp float;//声明要接收的量varying vec4 v_Color;void main(){gl_FragColor = v_Color;}
</script>

4.2 初始化项目

const canvas = document.getElementById("canvas");
const gl = canvas.getContext("webgl");
//创建着色器对象
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
//获取着色器对象的源
let vertexSource = document.getElementById("vertex-shader").innerText;
let fragmentSource = document.getElementById("fragment-shader").innerText;
//绑定着色器的源
gl.shaderSource(vertexShader,vertexSource);
gl.shaderSource(fragmentShader,fragmentSource);
//编译着色器
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
console.log(gl.getShaderInfoLog(vertexShader));
//创建并关联项目
let program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

4.3 赋值

//获取attribute变量
let a_Position = gl.getAttribLocation(program,'a_Position');
//赋值,有多种赋值方法,使用缓冲区见之前博文
gl.vertexAttrib1f (a_Position, v);                 // float
gl.vertexAttrib1fv(a_Position, [v]);               // float 或 float array
gl.vertexAttrib2f (a_Position,  v0, v1);            // vec2
gl.vertexAttrib2fv(a_Position,  [v0, v1]);          // vec2 或 vec2 array
gl.vertexAttrib3f (a_Position,  v0, v1, v2);        // vec3
gl.vertexAttrib3fv(a_Position,  [v0, v1, v2]);      // vec3 或 vec3 array
gl.vertexAttrib4f (a_Position,  v0, v1, v2, v4);    // vec4
gl.vertexAttrib4fv(a_Position,  [v0, v1, v2, v4]);  // vec4 或 vec4 array
//获取attribute变量
let uRotateMatrix= gl.getUniformLocation(program,'uRotateMatrix');
//赋值,有多种赋值方法
gl.uniform1f (uRotateMatrix, v);                 // float
gl.uniform1fv(uRotateMatrix, [v]);               // float 或 float array
gl.uniform2f (uRotateMatrix,  v0, v1);            // vec2
gl.uniform2fv(uRotateMatrix,  [v0, v1]);          // vec2 或 vec2 array
gl.uniform3f (uRotateMatrix,  v0, v1, v2);        // vec3
gl.uniform3fv(uRotateMatrix,  [v0, v1, v2]);      // vec3 或 vec3 array
gl.uniform4f (uRotateMatrix,  v0, v1, v2, v4);    // vec4
gl.uniform4fv(uRotateMatrix,  [v0, v1, v2, v4]);  // vec4 或 vec4 array
//赋值矩阵
gl.uniformMatrix2fv(mat2UniformLoc, false, [  4x element array ])  // mat2 或 mat2 array
gl.uniformMatrix3fv(mat3UniformLoc, false, [  9x element array ])  // mat3 或 mat3 array
gl.uniformMatrix4fv(mat4UniformLoc, false, [ 16x element array ])  // mat4 或 mat4 array
//赋值整型变量
gl.uniform1i (intUniformLoc,   v);                 // int
gl.uniform1iv(intUniformLoc, [v]);                 // int 或 int array
gl.uniform2i (ivec2UniformLoc, v0, v1);            // ivec2
gl.uniform2iv(ivec2UniformLoc, [v0, v1]);          // ivec2 或 ivec2 array
gl.uniform3i (ivec3UniformLoc, v0, v1, v2);        // ivec3
gl.uniform3iv(ivec3UniformLoc, [v0, v1, v2]);      // ivec3 or ivec3 array
gl.uniform4i (ivec4UniformLoc, v0, v1, v2, v4);    // ivec4
gl.uniform4iv(ivec4UniformLoc, [v0, v1, v2, v4]);  // ivec4 或 ivec4 array
//赋值纹理
gl.uniform1i (sampler2DUniformLoc,   v);           // sampler2D (textures)
gl.uniform1iv(sampler2DUniformLoc, [v]);           // sampler2D 或 sampler2D array
//赋值立方体纹理 
gl.uniform1i (samplerCubeUniformLoc,   v);         // samplerCube (textures)
gl.uniform1iv(samplerCubeUniformLoc, [v]);         // samplerCube 或 samplerCube array

5 结构体

5.1 声明

struct Material {vec3 ambient;vec3 diffuse;vec3 specular;float shininess;
};struct Light {vec3 position;vec3 color;float intensity;
};struct Scene {Material material;Light light;
};
uniform Scene uScene;void main() {vec3 ambient = uScene.material.ambient * uScene.light.color;
}

5.2 赋值

// 设置 Material
gl.uniform3f(gl.getUniformLocation(program, 'uScene.material.ambient'), 1.0, 0.5, 0.31);
gl.uniform3f(gl.getUniformLocation(program, 'uScene.material.diffuse'), 1.0, 0.5, 0.31);
gl.uniform3f(gl.getUniformLocation(program, 'uScene.material.specular'), 0.5, 0.5, 0.5);
gl.uniform1f(gl.getUniformLocation(program, 'uScene.material.shininess'), 32.0);// 设置 Light
gl.uniform3f(gl.getUniformLocation(program, 'uScene.light.position'), 10.0, 10.0, 10.0);
gl.uniform3f(gl.getUniformLocation(program, 'uScene.light.color'), 1.0, 1.0, 1.0);
gl.uniform1f(gl.getUniformLocation(program, 'uScene.light.intensity'), 1.0);

6 函数

6.1 基本结构

返回类型 函数名(参数列表) {// 函数体return 返回值; // 如果返回类型不是 void
}
例如:add 是函数名,接受两个 float 类型的参数 a 和 b,并返回它们的和。
float add(float a, float b) {return a + b;
}

6.2 自定义函数

// 自定义函数:计算镜面反射
vec3 calculateSpecular(vec3 normal, vec3 viewDir, vec3 lightDir, float shininess) {vec3 reflectDir = reflect(-lightDir, normal);float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);return spec * vec3(1.0); // 假设镜面反射颜色为白色
}void main() {vec3 normal = normalize(vNormal);vec3 lightDir = normalize(uLightPos - vFragPos);vec3 viewDir = normalize(uViewPos - vFragPos);// 使用自定义函数计算镜面反射vec3 specular = calculateSpecular(normal, viewDir, lightDir, 32.0);fragColor = vec4(specular, 1.0);
}

6.3 常用内置函数

sin(x):返回 x 的正弦值,x 为弧度。
cos(x):返回 x 的余弦值。
tan(x):返回 x 的正切值。
asin(x):返回 x 的反正弦值,结果为弧度。
acos(x):返回 x 的反余弦值。
atan(x):返回 x 的反正切值。
atan(y, x):返回从 (x, y) 到原点的角度,结果为弧度
exp(x):返回 e^x。
log(x):返回 ln(x),即自然对数。
log2(x):返回以 2 为底的对数。
pow(x, y):返回 x 的 y 次幂。
sqrt(x):返回 x 的平方根。
inversesqrt(x):返回 1 / sqrt(x)abs(x):返回 x 的绝对值。
sign(x):返回 x 的符号,-1.0(负数),0.0(零),1.0(正数)。
floor(x):返回不大于 x 的最大整数。
ceil(x):返回不小于 x 的最小整数。
round(x):返回四舍五入后的整数。
mod(x, y):返回 x 除以 y 的余数。
min(x, y):返回 x 和 y 中较小的值。
max(x, y):返回 x 和 y 中较大的值。
clamp(x, minVal, maxVal):将 x 限制在 minVal 和 maxVal 之间。
mix(x, y, a):线性插值,返回 (1 - a) * x + a * y。
step(edge, x):阶跃函数,如果 x < edge 返回 0.0,否则返回 1.0smoothstep(edge0, edge1, x):平滑的阶跃函数,x 在 edge0 和 edge1 之间时进行平滑过渡。
dot(x, y):计算向量 x 和 y 的点积。
cross(x, y):计算向量 x 和 y 的叉积(仅适用于 vec3)。
normalize(x):将向量 x 归一化。
length(x):返回向量 x 的长度。
distance(x, y):返回向量 x 和 y 之间的距离。
reflect(I, N):计算入射向量 I 关于法线 N 的反射向量。
refract(I, N, eta):计算入射向量 I 关于法线 N 的折射向量,eta 为折射率比。
transpose(x):返回矩阵 x 的转置。
inverse(x):返回矩阵 x 的逆矩阵。
matrixCompMult(x, y):按元素相乘两个矩阵 x 和 y。
faceforward(N, I, Nref):根据视角调整法线方向,确保法线朝向观察者。
texture(sampler, coord):根据纹理坐标 coord 从 sampler 采样纹理。
textureLod(sampler, coord, lod):带有指定层次细节级别的纹理采样。
textureProj(sampler, coord):投影纹理采样。
textureGrad(sampler, coord, dPdx, dPdy):带有梯度信息的纹理采样。
min(x, y):返回 x 和 y 中较小的值。
max(x, y):返回 x 和 y 中较大的值。
clamp(x, minVal, maxVal):将 x 限制在 minVal 和 maxVal 之间。
step(edge, x):阶跃函数。
smoothstep(edge0, edge1, x):平滑的阶跃函数。

7 精度

在这里插入图片描述

8 其他

  其他的如if判断,for循环等于C语言、JavaScript一样,这里不再赘述。

9 总结

  本篇中我们介绍了GLSL的基础语法,略显枯燥乏味,但对我们能够是否熟练掌握WebGL有很大的帮助,希望读者仔细体会,回见~

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 采用qt做一个命令行终端
  • 面向对象程序设计之继承(C++)
  • ai 回答HFS是什么 HTTP的文件服务器是什么
  • Leetcode3282. 到达数组末尾的最大得分
  • new/delete和malloc/free到底有什么区别
  • VUE + NODE 历史版本安装
  • AWTK fscript 中的 value 扩展函数
  • synchronized的详解、锁的升级过程和优缺点比较
  • Maven 解析:打造高效、可靠的软件工程
  • JavaSE:9、数组
  • 3. 进阶指南:自定义 Prompt 提升大模型解题能力
  • 记录word转xml文件踩坑
  • 机器学习特征构建与特征筛选
  • Vue3实现打印功能
  • LeetCode[中等] 3. 无重复字符的最长子串
  • 分享一款快速APP功能测试工具
  • 【知识碎片】第三方登录弹窗效果
  • C# 免费离线人脸识别 2.0 Demo
  • C++类中的特殊成员函数
  • gf框架之分页模块(五) - 自定义分页
  • Java 网络编程(2):UDP 的使用
  • Promise初体验
  • Redis在Web项目中的应用与实践
  • Vue ES6 Jade Scss Webpack Gulp
  • Vue UI框架库开发介绍
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 第十八天-企业应用架构模式-基本模式
  • 电商搜索引擎的架构设计和性能优化
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 区块链分支循环
  • 如何解决微信端直接跳WAP端
  • 微信小程序实战练习(仿五洲到家微信版)
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • 选择阿里云数据库HBase版十大理由
  • # 透过事物看本质的能力怎么培养?
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (31)对象的克隆
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY)讲解
  • (定时器/计数器)中断系统(详解与使用)
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (蓝桥杯每日一题)love
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .NET COER+CONSUL微服务项目在CENTOS环境下的部署实践
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)...
  • .net6Api后台+uniapp导出Excel
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项