threejs(webgl)-shader入门教程(1)
1.shader基本使用
2.shader粒子
shader是什么?
shader是一个用GLSL编写的小程序,也就是着色器语言,我们可以通过shader来编写顶点着色器和片元着色器,在WEBGL编程一书中 25-26页有详细说明
shader在Three.js中如何使用?
threejs提供了关于shader的材质 RawShaderMaterial 和 ShaderMaterial 两种编写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)相关推荐
- Shader入门教程
学习Unity有一段时间了,都说Unity想要进阶得学会Shader编程,因此花了一阵子来学习Shader编程.学了之后才发现,Shader并没有我原先想的那么复杂,掌握它的原理和语法后,我们也能用s ...
- Shader入门教程(一)
学习Unity有一段时间了,都说Unity想要进阶得学会Shader编程,因此花了一阵子来学习Shader编程.学了之后才发现,Shader并没有我原先想的那么复杂,掌握它的原理和语法后,我们也能用s ...
- 我见过的,最易上手的Shader入门教程(图文)
自从接触了shader之后我便深深得爱上了它,因为它独特的编程思考方式冲击着我这十几年的惯性认知. 在向各位大佬学习的过程中,每学到一个新的技巧,我都不禁感叹:"实在是妙!" 本文 ...
- unity Shader Lab(cg hlsl glsl)着色器入门教程 以及 vs2019 支持unity shader语法(更新中2019.9.5)
前言: 如果你对cg glsl hlsl 顶点着色器 片段着色器 表面着色器 固定渲染管线 等等有所疑惑,或是想学会unity的渲染,看这一篇就足够了.另外我博客的shader分类中还有很多shade ...
- Android基础入门教程——8.3.13 Paint API之—— Shader(图像渲染)
Android基础入门教程--8.3.13 Paint API之-- Shader(图像渲染) 标签(空格分隔): Android基础入门教程 本节引言: 最近一段时间因为工作上的事以及面试等等,耽误 ...
- 【 Threejs 】- Shader 着色器实例渲染教程
着色器在threejs中是一个难点,话不多说,先来看看着色器是什么? 如果您已经有使用计算机绘图的经验,您就会知道在这个过程中您先画一个圆,然后画一个矩形.一条线.一些三角形,直到您组成您想要的图像. ...
- Three.js零基础入门教程(2023版本)
1. threejs文件包下载和目录简介 在正式学习Three.js之前,先做一些必要的准备工作,具体说就是下载threejs官方文件包,threejs官方文件包提供了很多有用的学习资源. Three ...
- webgl坐标转换_WebGL教程
前言 通过WebGL做了很多项目,感觉有必要录制一套视频教程,所以在这里写一个录制大纲,大家也可以通过章节目录了解下WebGL的基本内容. 视频教程发布地址 Threejs引擎 Threejs是web ...
- threejs可视化快速入门指北(附3D资源导航)
前言 当你开始思考你应该如何学习WebGL和Three.js的时候,相信你至少对相关的关键词了解过了,希望通过WebGL或Three.js实现你想要的Web3D功能,也许你也会去思考通过WebGL或T ...
最新文章
- Microsoft月度中文速递
- iframe显示错误页面
- 【二分】【暴力】蛋糕(gmoj 3918)
- [转]Java 对象锁-synchronized()与线程的状态与生命周期
- cookie、session和token
- WDS和DHCP配置说明
- windows程序设计一 最简单的windows程序
- Linux安全加固手册
- 视频应用在区块链上的应用
- springboot大学生就业规划系统毕业设计-附源码191451
- 简单的python爬取淘宝数据
- 软件分类和软件测试工作流程
- 一个女留学生在美国的七年(转载)
- 队列基本操作模拟打印机任务管理
- 能代替苹果pencil的手写笔有吗?比较好用的ipad手写笔推荐
- Matlab的一些术语
- 区块链研究生专业_“区块链大数据赋能低碳发展”高端研讨活动 在增城低碳总部举行...
- metashape(photosan)集群设置
- 几个好玩有趣的Python入门实例
- angular中forRootforChild的作用