1.shader基本使用
2.shader粒子

shader是什么?

shader是一个用GLSL编写的小程序,也就是着色器语言,我们可以通过shader来编写顶点着色器和片元着色器,在WEBGL编程一书中 25-26页有详细说明

shader在Three.js中如何使用?

threejs提供了关于shader的材质 RawShaderMaterialShaderMaterial 两种编写shader的材质。
RawShaderMaterial:不内置uniforms和attributes
ShaderMaterial:内置一些需要的参数,后期的使用都为此材质
这里的教程使用的教程为ShaderMaterial

ShaderMaterial

如果使用ShaderMaterial?
首先的了解ShaderMaterial时我们需要的参数。

attributes

顶点数据,我们使用的geometry和加载的模型中就已经创建好顶点数据了
这是使用PlaneGeometry生成的一段数据,一般的geometry数据有三个属性

position(vec3) 为模型的点位,没有这个属性,物体就无法显示出来
normal(vec3) 法线数据 用于光照计算 法线贴图等
uv(vec2) 贴图的点位

uniforms

通过材质传递给shader的值,可以动态的去修改shader的参数 这些值需要满足在shader中的基础类型(最底下),可以通过传递参数来对物体进行不同的操作。例如修改颜色,透明度,计算的参数等。
在接受当前参数时,一定要确定好当前参数的基本类型。传递的浮点数接受一定是浮点数

vertexShader

在顶点着色器中运行的代码, 顶点着色器在片元着色器前运行,可以自行搜索下webgl的渲染流程。

fragmentShader

在片元着色器中运行的代码

第一个Demo(修改颜色)

我们输出一个最简单的Demo,修改颜色

const geometry = new THREE.PlaneGeometry(100, 100);const shader = new THREE.ShaderMaterial({uniforms: {},vertexShader: `void main() {// 顶点着色器计算后的Positiongl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`,fragmentShader: `void main() {// 输出到页面中。当前物体的每一个材质为红色,输出的颜色为rgba的归一化,gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}`
});const plane = new THREE.Mesh(geometry, shader);scene.add(plane);

修改输出
我们在uniforms传递一个参数,然后通过着色器去接收这个参数。

// uniforms
uniforms: {uColor: {value: new THREE.Color('#FFFF00') // 传递一个黄色}
}// fragmentShader
fragmentShader: `uniform vec3 uColor;void main() {// // 输出到页面中。当前物体的每一个材质为红色,输出的颜色为rgba的归一化,gl_FragColor = vec4(uColor, 1.0);}`

最终我们得到了一个黄色的面

然后我们可以通过直接修改材质中uniforms.uColor.value的参数,就可以直接修改面的颜色

// 动态的修改颜色
setInterval(() => {const color = `rgb(${radom()}, ${radom()}, ${radom()})`;shader.uniforms.uColor.value.setStyle(color);
}, 200)

这样我们就编写了一个最简单的可以修改物体颜色的shader材质

第二个Demo

通过接受顶点数据,来输出对应的颜色。通过varying变量,可以把顶点的数据着色器传递到片元着色器之中

申明一个三维向量接受position传递给片元,然后我们判断y轴小于0的为uColor的颜色,否则为uColor1的颜色

const geometry = new THREE.PlaneGeometry(100, 100);const shader = new THREE.ShaderMaterial({uniforms: {uColor: {value: new THREE.Color('#FFFF00'),},uColor1: {value: new THREE.Color('#FFFFFF'),}},vertexShader: `varying vec3 vPosition; // + 新增void main() {// 顶点着色器计算后的PositionvPosition = position; // + 新增gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`,fragmentShader: `uniform vec3 uColor;uniform vec3 uColor1; // + 新增varying vec3 vPosition; // + 新增void main() { if (vPosition.y < 0.0) { // + 新增gl_FragColor = vec4(uColor, 1.0);} else { // + 新增gl_FragColor = vec4(uColor1, 1.0); // + 新增} // + 新增}`
});const plane = new THREE.Mesh(geometry, shader);scene.add(plane);

最后我们得到了一个上下不一样颜色的图形

也可以在片元着色器中画一个圆


const geometry = new THREE.PlaneGeometry(100, 100);const shader = new THREE.ShaderMaterial({uniforms: {uColor: {value: new THREE.Color('#FFFF00'),},uColor1: {value: new THREE.Color('#FFFFFF'),},uRadius: {value: 0}},vertexShader: `varying vec3 vPosition;void main() {// 顶点着色器计算后的PositionvPosition = position;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`,fragmentShader: `uniform float uRadius; // 设置一个半径范围uniform vec3 uColor;uniform vec3 uColor1;varying vec3 vPosition;void main() { // 中心点vec3 vCenter = vec3(.0, .0, .0);// 计算顶点离中心点的距离float len = distance(vCenter, vPosition);// 设置在半径范围内的颜色为uColor 反之 为 uColorif (len < uRadius) {gl_FragColor = vec4(uColor1, 1.0);} else {gl_FragColor = vec4(uColor, 1.0);}}`
});const plane = new THREE.Mesh(geometry, shader);scene.add(plane);let radius = 1;
setInterval(() => {const color = `rgb(${radom()}, ${radom()}, ${radom()})`;shader.uniforms.uColor.value.setStyle(color);shader.uniforms.uRadius.value = radius % 50;radius++;
}, 50)

就得到了以下的图形

把图片纹理传递到当前DEMO中

顶点着色器:varying把图片的uv传递给片元。使用纹理必须有对应的uv


const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('/textures/texture.jpg')const geometry = new THREE.PlaneGeometry(100, 100);const shader = new THREE.ShaderMaterial({uniforms: {uColor: {value: new THREE.Color('#FFFF00'),},uRadius: {value: 0},uTexture: {value: texture}},vertexShader: `varying vec3 vPosition;varying vec2 vUV; // void main() {// 顶点着色器计算后的PositionvPosition = position;// 把uv数据传递给片元vUV = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`,fragmentShader: `uniform float uRadius; // 设置一个半径范围uniform vec3 uColor; // 颜色1varying vec3 vPosition; // 顶点数据varying vec2 vUV; // uvuniform sampler2D uTexture; // 材质void main() { // 材质和uv计算为当前位置颜色vec4 mapColor = texture2D(uTexture, vUV);vec3 vCenter = vec3(.0, .0, .0);float len = distance(vCenter, vPosition);if (len < uRadius) {gl_FragColor = mapColor;} else {gl_FragColor = vec4(uColor, 1.0);}}`
});const plane = new THREE.Mesh(geometry, shader);scene.add(plane);let radius = 1;
setInterval(() => {const color = `rgb(${radom()}, ${radom()}, ${radom()})`;shader.uniforms.uColor.value.setStyle(color);shader.uniforms.uRadius.value = radius % 50;radius++;
}, 50)

总结

在着色器中,操控顶点数据和片元输出的颜色,就能做出更多的效果。
更深入的待续。


代码地址
觉得可以的话请给一个小星星或者一个赞
QQ群:1082834010


基本类型:

类型 说明
void 空类型,即不返回任何值
bool 布尔类型 true,false
int 带符号的整数 signed integer
float 带符号的浮点数 floating scalar
vec2, vec3, vec4 n维浮点数向量 n-component floating point vector
bvec2, bvec3, bvec4 n维布尔向量 Boolean vector
ivec2, ivec3, ivec4 n维整数向量 signed integer vector
mat2, mat3, mat4 2x2, 3x3, 4x4 浮点数矩阵 float matrix
sampler2D 2D纹理 a 2D texture
samplerCube 盒纹理 cube mapped texture

threejs(webgl)-shader入门教程(1)相关推荐

  1. Shader入门教程

    学习Unity有一段时间了,都说Unity想要进阶得学会Shader编程,因此花了一阵子来学习Shader编程.学了之后才发现,Shader并没有我原先想的那么复杂,掌握它的原理和语法后,我们也能用s ...

  2. Shader入门教程(一)

    学习Unity有一段时间了,都说Unity想要进阶得学会Shader编程,因此花了一阵子来学习Shader编程.学了之后才发现,Shader并没有我原先想的那么复杂,掌握它的原理和语法后,我们也能用s ...

  3. 我见过的,最易上手的Shader入门教程(图文)

    自从接触了shader之后我便深深得爱上了它,因为它独特的编程思考方式冲击着我这十几年的惯性认知. 在向各位大佬学习的过程中,每学到一个新的技巧,我都不禁感叹:"实在是妙!" 本文 ...

  4. unity Shader Lab(cg hlsl glsl)着色器入门教程 以及 vs2019 支持unity shader语法(更新中2019.9.5)

    前言: 如果你对cg glsl hlsl 顶点着色器 片段着色器 表面着色器 固定渲染管线 等等有所疑惑,或是想学会unity的渲染,看这一篇就足够了.另外我博客的shader分类中还有很多shade ...

  5. Android基础入门教程——8.3.13 Paint API之—— Shader(图像渲染)

    Android基础入门教程--8.3.13 Paint API之-- Shader(图像渲染) 标签(空格分隔): Android基础入门教程 本节引言: 最近一段时间因为工作上的事以及面试等等,耽误 ...

  6. 【 Threejs 】- Shader 着色器实例渲染教程

    着色器在threejs中是一个难点,话不多说,先来看看着色器是什么? 如果您已经有使用计算机绘图的经验,您就会知道在这个过程中您先画一个圆,然后画一个矩形.一条线.一些三角形,直到您组成您想要的图像. ...

  7. Three.js零基础入门教程(2023版本)

    1. threejs文件包下载和目录简介 在正式学习Three.js之前,先做一些必要的准备工作,具体说就是下载threejs官方文件包,threejs官方文件包提供了很多有用的学习资源. Three ...

  8. webgl坐标转换_WebGL教程

    前言 通过WebGL做了很多项目,感觉有必要录制一套视频教程,所以在这里写一个录制大纲,大家也可以通过章节目录了解下WebGL的基本内容. 视频教程发布地址 Threejs引擎 Threejs是web ...

  9. threejs可视化快速入门指北(附3D资源导航)

    前言 当你开始思考你应该如何学习WebGL和Three.js的时候,相信你至少对相关的关键词了解过了,希望通过WebGL或Three.js实现你想要的Web3D功能,也许你也会去思考通过WebGL或T ...

最新文章

  1. Microsoft月度中文速递
  2. iframe显示错误页面
  3. 【二分】【暴力】蛋糕(gmoj 3918)
  4. [转]Java 对象锁-synchronized()与线程的状态与生命周期
  5. cookie、session和token
  6. WDS和DHCP配置说明
  7. windows程序设计一 最简单的windows程序
  8. Linux安全加固手册
  9. 视频应用在区块链上的应用
  10. springboot大学生就业规划系统毕业设计-附源码191451
  11. 简单的python爬取淘宝数据
  12. 软件分类和软件测试工作流程
  13. 一个女留学生在美国的七年(转载)
  14. 队列基本操作模拟打印机任务管理
  15. 能代替苹果pencil的手写笔有吗?比较好用的ipad手写笔推荐
  16. Matlab的一些术语
  17. 区块链研究生专业_“区块链大数据赋能低碳发展”高端研讨活动 在增城低碳总部举行...
  18. metashape(photosan)集群设置
  19. 几个好玩有趣的Python入门实例
  20. angular中forRootforChild的作用

热门文章

  1. fprintf()函数的运用
  2. java闭锁_Java闭锁_CountDownLatch
  3. 《指数基金投资指南》读书笔记---行业指数基金
  4. 前端后端数据交换乱码问题
  5. 【大数据】SQL的作业题(仅适合初学者)
  6. 为没有后缀名的文件设置默认打开方式——Notepad++
  7. YC++编译器最新版主要功能及特点简介, 请广大的编程爱好者试用,并且希望能提出更多宝贵意见,使此软件更加完善。谢谢!
  8. Redis地理算法GEO解析和应用
  9. Mysql--instr函数的介绍及使用
  10. stegsolve 的安装使用