three.js 着色器材质之变量(三)
这篇郭先生在练习一下着色器变量,在度娘上面或者官网上经常看到类似水波一样的效果,这篇就试着做一个这样的效果,顺便巩固一下顶点着色器和片元着色器,毕竟多多练习才能更好地掌握。效果如下图,在线案例请点击博客原文。
这里用到了用到了顶点着色器和片元着色器。
1. 设置几何体
设置一个几何体,对于波浪效果,我们制作一个球几何体(当然也可以设置其他的,可能有意想不到的效果哦!)。
var sphere = new THREE.SphereBufferGeometry(10, 120, 80);
2. 设置attribute属性
这里我们使用一个叫做noise的attribute属性来搞定它,同时我们在设置一个类型化数组boolArray来辅助它。
count = sphere.attributes.position.count;//顶点的数量 verticesArray = new Float32Array(count);//存放每一个点的噪声值 boolArray = new Float32Array(count);//辅助类型数组 for(var v = 0; v < count; v++) { verticesArray[v] = Math.random() * 2 + 10;//随机数[10,12) if(Math.random() >= 0.5) {//在创造一个随机数,如果大于如果大于0.5,boolArray设置成10.5,boolArray设置成1。如果小于0.5,boolArray设置成-1 boolArray[v] = 1; } else { boolArray[v] = -1; } } var bufferAttribute = new THREE.BufferAttribute(verticesArray, 1); sphere.setAttribute('noise', bufferAttribute);
3. 设置着色器材质
var material = new THREE.ShaderMaterial({ vertexShader: ` attribute float noise;//着色器中定义noise属性 varying vec3 vNormal;//定义两个varying属性,用于将顶点着色器中的属性传到片元着色器中 varying vec3 vPosition; void main() { vNormal = normal; vPosition = position; vec3 newPosition = position + normal * noise;//这里比较重要,顶点坐标加上球面法向量乘以噪声,得到新的顶点坐标,新的坐标是和normal方向相同的。 gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 ); } `, fragmentShader: ` varying vec3 vPosition; varying vec3 vNormal; void main() { vec3 nml = (vNormal + 1.0) / 2.0;//这个使用了顶点坐标的法向量 vec3 cy = vec3((sin(vPosition.y * 3.0) + 1.0) / 2.0);//这个使用了顶点坐标 gl_FragColor=vec4(cy * nml, 1.0);//将两种效果结合起来(上面两种颜色你们不妨可以单个试一试哦) } ` });
4. 设置动态效果
上一篇我们使用了uniform传递了一个time值,这次我们另辟蹊径,在render方法中改变attribute属性。
for(var v = 0; v < count; v++) { if(verticesArray[v] < 10) {//如果噪声小于10,就将对应的boolArray变成1,然后累加 boolArray[v] = 1; verticesArray[v] += 0.05; } else if(verticesArray[v] > 12) {//如果噪声大于12,就将对应的boolArray变成-1,然后累减 boolArray[v] = -1; verticesArray[v] -= 0.05; } else if(boolArray[v] == 1) {//如果boolArray等于1,就继续累加 verticesArray[v] += 0.05; } else {//如果boolArray等于-1,就继续累减 verticesArray[v] -= 0.05; } } var bufferAttribute = new THREE.BufferAttribute(verticesArray, 1); //更新noise属性值 mesh.geometry.setAttribute('noise', bufferAttribute);
这样就做成了案例上面的效果,是不是很有意思,我们可以做各种效果,说不上有心仪的效果。
转载请注明地址:郭先生的博客