three.js 着色器材质之变量(二)
上一篇郭先生在例子中用到了着色器变量中的uniform和varying。这节继续结合例子将一下attribute变量,在使用过程中也发现由于three.js的版本迭代,之前的一些属性和参数已经发生了改变,ShaderMaterial也不需要传递attributes属性值,查看源码我们可以看到如果传递了attributes参数,会给出下面这样的错误。
if ( parameters.attributes !== undefined ) {
console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );
}
因为我们现在想传递attributes时,几何体需要设置对应的缓冲类型,然后将使用setAttribute方法(老版本使用addAttribute方法)将属性添加到BufferGeometry的attributes中,然后我们在顶点着色器中定义使用即可。
先看看今天要完成的效果,灵感还是在iview主页上看到的。在线案例请点击波浪效果。
捕获.PNG
1. 制作几何体
之前的版本有这样一个方法THREE.BufferGeometryUtils.mergeBufferGeometries,它可以将几何体组合起来,并保留几何体的中心坐标,但是现在已经找不到了。建议使用merge方法。
let geometry = new THREE.Geometry();
for(let i=0; i<39; i++) { //39行
for(let j=0; j<39; j++) { //39列
let sphere = new THREE.SphereGeometry(2, 15, 10);
sphere.translate(i * 50 - 950, 0, j * 50 - 950); //这里我们使用Geometry的translate方法将间隔调成50
geometry.merge(sphere);//结合几何体
}
}
let bufferGeometry = new THREE.BufferGeometry().fromGeometry(geometry); //最后将几何体替换成对应的缓冲类型
2. 设置attributes属性
因为现在所有的球已经失去了中心坐标,如果不增加一些属性,我们很难在顶点着色器中操作这些点(因为不知道哪个点对应哪个球),因此这个时候我们就需要使用attributes属性。这里我们设置一个叫做centers的attribute属性,每一个球上面的点都对应同一个centers。
total = bufferGeometry.attributes.position.count; //几何体点的个数
every = total / 39 /39; //每个球体点的个数
centers = new Float32Array(total * 3);//初始化类型数组,并设置长度
//将中心点保存到centers中
for(let i=0; i<39; i++) {
for(let j=0; j<39; j++) {
for(let k=0; k<every; k++) {
centers[(i*39*every + j*every + k) * 3] = i * 50 - 950;
centers[(i*39*every + j*every + k) * 3 + 1] = 0;
centers[(i*39*every + j*every + k) * 3 + 2] = j * 50 - 950;
}
}
}
bufferGeometry.setAttribute('centers', new THREE.BufferAttribute(centers, 3));//为bufferGeometry设置属性
3. 设置着色器材质
这里重点就是顶点着色器,要做出水波的效果其实是两个方向正弦效果的叠加,所以设置一个centery,它是中心点的y坐标,它会随时间高低变化。有一个centery其实波浪效果就实现了,接来下还需要动态的改变球的大小。center向量是每个球中心点静止时的坐标,target是球中心点到球上一点的向量(也是球的法向量),newPosition是position沿法向量变换的点,我们回过头看一下centery,它值的范围是-80,80,因此(centery + 80.0) / 80.0的范围是0, 2,我们在centery最高是,让球最大,newPosition = center + target * 2。最后设置gl_Position,newPosition控制缩放,centery控制小球上下浮动。
无标题.png
uniforms = {
time: {
type: 'f',
value: 0
}
}
var material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: `
attribute vec3 centers;
uniform float time;
void main() {
float centery = sin(centers.x / 100.0 + time) * 40.0 + sin(centers.z / 100.0 + time) * 40.0;
vec3 center = vec3(centers.x, 0, centers.z);
vec3 target = position - center;
vec3 newPosition = center + target * ((centery + 80.0) / 80.0);
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition.x, newPosition.y + centery, newPosition.z, 1.0 );
}
`,
fragmentShader: `
void main() {
gl_FragColor = vec4(0.0,0.5,0.8,1.0);
}
`
});
好了,到此为止,我们结合案例说了着色器变量uniform,varying和attribute,感觉还好的话就点咋赞吧!
转载请注明地址:郭先生的博客
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=m2qvjhkwisxl
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 线程通讯wait¬ify
- 最新深度学习框架——OneFlow:新分布式训练(附源代码)
- 多线程相关概念
- MySQL安装教程
- MapReduce之自定义OutputFormat
- 在TensorFlow中使用模型剪枝将机器学习模型变得更小
- 干货 | 滴滴 数据分析原来是这样做的!
- 数据链路层之PPP协议
- matplotlib基础绘图命令之boxplot
- MapReduce之GroupingComparator分组(辅助排序、二次排序)
- MySQL优化--概述以及索引优化分析
- MySQL优化--查询分析工具以及各种锁
- MySQL优化--MVCC
- Linux入门--基础命令
- Linux入门--权限管理、任务调度、磁盘管理