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

光影编程师:Threejs Shader 基础全攻略

介绍

Shader 是一种运行在 GPU 上的小程序,用于实现一些图形效果。在 Three.js 中,我们可以使用 GLSL ES 语言来编写 Shader,并将其应用到材质上,从而实现各种图形效果。

可以做什么

  • 实现各种图形效果,如光照、阴影、反射、折射等。

  • 实现自定义的材质,如金属、塑料、玻璃等。

  • 实现粒子效果,如烟雾、火焰、水波等。

  • 实现动态纹理,如动态纹理、动态贴图等。

GLSL ES

GLSL ES 是一种用于编写 Shader 的编程语言,它是一种基于 C 语言的编程语言,具有 C 语言的大部分语法和特性。在 GLSL ES 中,我们可以使用一些特殊的语法和函数来实现各种图形效果。

基础语法

  • 变量声明:在 GLSL ES 中,我们可以使用 floatintbool 等数据类型来声明变量,例如:
float x = 1.0;
int y = 2;
bool z = true;
  • 函数声明:在 GLSL ES 中,我们可以使用 voidfloatint 等数据类型来声明函数,例如:
void myFunction(float a, int b) {// 函数体
}
float myFunction2(int a) {// 函数体return 1.0;
}
  • 循环和条件语句:在 GLSL ES 中,我们可以使用 forwhileif 等循环和条件语句,例如:
for (int i = 0; i < 10; i++) {// 循环体
}
if (x > 0.5) {// 条件体
}

向量

GLSL ES 中,向量可以标时多种数据,也能进行多种数学运算。

例如,我们可以使用 vec3 来表示颜色,其中 vec3 是一个包含三个浮点数的向量,分别表示红、绿、蓝三个颜色通道的值。例如:

vec3 color = vec3(1.0, 0.0, 0.0); // 红色

我们也可以使用 vec3 来表示位置、方向、法线等,例如:

vec3 position = vec3(0.0, 0.0, 0.0); // 位置
vec3 direction = vec3(0.0, 0.0, 1.0); // 方向
vec3 normal = vec3(0.0, 1.0, 0.0); // 法线

常用关键字:

  • vec2: 二维向量,分量是浮点数。

  • vec3: 三维向量,分量是浮点数。

  • vec4: 四维向量,分量是浮点数。

  • ivec2: 二维向量,分量是整数。

  • ivec3: 三维向量,分量是整数。

  • ivec4: 四维向量,分量是整数。

  • bvec2: 二维向量,分量是布尔值。

  • bvec3: 三维向量,分量是布尔值。

  • bvec4: 四维向量,分量是布尔值。

  • mat2: 二维矩阵,包含两个二维向量。

  • mat3: 三维矩阵,包含三个三维向量。

  • mat4: 四维矩阵,包含四个四维向量。

着色器材质

Three.js 中,我们可以使用 ShaderMaterial 来创建一个着色器材质,并将其应用到几何体上,从而实现各种图形效果。

使用 ShaderMaterial

之前介绍了很多材质,例如:创建一个平面,使用基础网格材质 MeshBasicMaterial

const geometry = new THREE.PlaneGeometry(1, 1);
const material = new THREE.MeshBasicMaterial({color: 0xff0000,
});
const mesh = new THREE.Mesh(geometry, material);

现在,我们使用 ShaderMaterial 来创建一个材质,并应用到平面上。

const geometry = new THREE.PlaneGeometry(100, 50);
const material = new THREE.ShaderMaterial({vertexShader: "...", // 顶点着色器fragmentShader: "...", // 片元着色器
});
const mesh = new THREE.Mesh(geometry, material);

设置顶点着色器

ShaderMaterial 顶点着色器属性 vertexShader,是一个字符串,表示顶点着色器的代码。

const material = new THREE.ShaderMaterial({vertexShader: "", // 顶点着色器
});

设置顶点着色器主函数

根据 GLSL ES 的语法,顶点着色器需要有一个主函数 main(),函数无返回值,前面加上 void 关键字。

const material = new THREE.ShaderMaterial({vertexShader: `void main() {// 顶点着色器代码}`,
});

内置变量

GLSL ES 中,我们可以使用 attributeuniformvarying 等关键字来声明变量,这些变量可以在顶点着色器和片元着色器之间传递。

  • gl_Position

gl_Position 是顶点着色器的一个内置变量,表示顶点的位置。在 GLSL ES 中,顶点着色器需要输出一个 vec4 类型的变量 gl_Position,表示顶点的位置。

const material = new THREE.ShaderMaterial({vertexShader: `//注意在主函数外面声明,默认提供,不用自己写attribute vec3 position; void main() {gl_Position = vec4(position, 1.0);}`,
});

attribute: 顶点属性,只能在顶点着色器中使用,用于传递几何体的顶点数据,例如顶点的位置、法线、颜色等。

使用 ShaderMaterial 的时候,Threejs 会在内部把内置变量 position 与几何体的顶点位置数据 geometry.attributes.position 进行绑定,这就意味着,在顶点着色器代码中访问 position 变量,就相当于访问几何体的顶点位置数据。

  • modelMatrix

modelMatrix 是顶点着色器的一个内置变量,表示模型的模型矩阵。在 GLSL ES 中,顶点着色器可以访问 mesh.matrixWorld 变量,用于计算顶点的位置。

const material = new THREE.ShaderMaterial({vertexShader: `uniform mat4 modelMatrix;void main() {gl_Position = modelMatrix * vec4(position, 1.0);}`,
});

使用 ShaderMaterial 的时候,Threejs 会自动获取模型世界矩阵 mesh.matrixWorld 的值,赋值给变量 modelMatrix。这意味着,模型矩阵 modelMatrix 包含了模型自身的位置、缩放、姿态角度信息。

uniform: 全局变量,可以在顶点着色器和片元着色器中使用,用于传递全局数据,例如光源位置、颜色等。

const material = new THREE.ShaderMaterial({vertexShader: `uniform float opacity;//uniform声明透明度变量opacityvoid main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}`,
});

uniform 变量传值,在 Three.js 中,我们可以在创建 ShaderMaterial 的时候,通过 uniforms 属性来传递。

const material = new THREE.ShaderMaterial({vertexShader: `uniform float opacity;void main() {gl_Position = vec4(position, 1.0);}`,fragmentShader: `void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, opacity);}`,uniforms: {opacity: { value: 1.0 }, // 传递透明度变量opacity的值},
});
  • viewMatrix

viewMatrix 是顶点着色器的一个内置变量,表示视图矩阵。在 GLSL ES 中,顶点着色器可以访问 camera.matrixWorldInverse 变量,用于计算顶点的位置。

const material = new THREE.ShaderMaterial({vertexShader: `uniform mat4 viewMatrix;void main() {gl_Position = viewMatrix * modelMatrix * vec4(position, 1.0);}`,
});
  • projectionMatrix

projectionMatrix 是顶点着色器的一个内置变量,表示投影矩阵。在 GLSL ES 中,顶点着色器可以访问 camera.projectionMatrix 变量,用于计算顶点的位置。

const material = new THREE.ShaderMaterial({vertexShader: `uniform mat4 projectionMatrix;void main() {gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);}`,
});

设置片元着色器

ShaderMaterial 片元着色器属性 fragmentShader,是一个字符串,表示片元着色器的代码。

const material = new THREE.ShaderMaterial({fragmentShader: "", // 片元着色器
});
  • gl_FragColor

gl_FragColor 是片元着色器的一个内置变量,表示片元的颜色。在 GLSL ES 中,片元着色器需要输出一个 vec4 类型的变量 gl_FragColor,表示片元的颜色。

const material = new THREE.ShaderMaterial({fragmentShader: `void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色}`,
});

效果

//创建平面
const geometry = new THREE.PlaneGeometry(1, 1);
const material = new THREE.ShaderMaterial({vertexShader: `void main() {// 投影矩阵 * 视图矩阵 * 模型矩阵 * 顶点位置,如果不乘模型矩阵,则不会有模型变换gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);}`,fragmentShader: `void main() {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}`,
});
const plane = new THREE.Mesh(geometry, material);
scene.add(plane);

modelViewMatrix :视图矩阵 * 模型矩阵

gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);

注意: 每个语句后面要加分号,否则会报错。

在这里插入图片描述

Threejs基础系列课程差不多临近结尾了,大家还有什么想学的可以留言。接下来会准备一些项目实战教程,大家可以学到Threejs的应用,在做案例的过程中对之前的基础知识做补充,敬请期待吧!!!

书洞笔记

相关文章:

  • 【嵌入式系统设计师(软考中级)】第二章:嵌入式系统硬件基础知识(3)
  • 18.应用聚合、指标显示、应用状态,从Heimdall说起(二)
  • JavaScript 实现继承及 Class 本质详解
  • 上篇:深入剖析 BLE 底层物理层与链路层(约5000字)
  • 链表-两两交换链表中的结点
  • Halcon 的基础用法
  • C语言基础(day0424)
  • AI打开潘多拉魔盒?当深度伪造成为虚假信息的核动力引擎
  • 仓库体系结构风格-笔记
  • Unity 资源合理性检测
  • 数据完整性的守护者:哈希算法原理与实现探析
  • Python中random库的应用
  • ​Janus Pro
  • C++跨平台开发要点
  • 面试题:Java程序CPU 100%问题排查指南
  • Mermaid 绘图指南(二)- 使用 Typora 与 Mermaid 绘制专业图表
  • Qt 使用 MySQL 数据库的基本方法
  • redis集群的三种部署方式
  • 《ATPL地面培训教材13:飞行原理》——第1章:概述与定义
  • unity Animation学习,精准控制模型动画播放
  • 五矿地产:今年要确保债务“不爆雷”、交付“不烂尾”
  • 咖啡与乳腺健康之间,究竟有着怎样的复杂关系?
  • 神舟二十号载人飞船成功飞天,上海航天有何贡献?
  • 生于1982年,孙晋出任共青团广西壮族自治区委员会书记
  • 王毅同伊朗外长阿拉格齐会谈
  • 职工疗休养如何告别千篇一律?安徽含山给出新解法