在之前使用threejs实现了点云的效果,后来想了一下还可以通过着色器修改一块板子上每个点的位置实现一些特殊的效果,比如让一个板子炸开~之前点云中点的运动轨迹都是自己计算出来的,后来发现tweenjs这个工具很好用,于是就应用到了这个项目中。
介绍项目之前,先理一理实现炸裂效果的思路
1.创建一个PlaneBufferGeometry对象方便对顶点进行处理,创建一个ShaderMaterial用于对着色器进行修改。
2.获取板子的顶点数并存入一个数组A,将每个顶点变换完成后的位置存入数组B。
3.在A与B之间使用tweenjs进行变换。
4.在着色器中根据A数组存放点的位置,对每个点的位置进行不断变换。
初始化模型,着色器纹理,创建两个存放顶点位置的数组,添加attribute变量。
//初始化板子 geometry = new THREE.PlaneBufferGeometry( 100, 100, 1000 ); //板子顶点个数 var vertices = geometry.attributes.position.count; offset = new Float32Array( vertices * 3 ); //偏移量逐渐增加 final_pos = new Float32Array(vertices * 3); //最终位置 for ( var i = 0; i < vertices; i ++ ) { final_pos[i*3] = Math.random()*100; final_pos[i*3+1] = Math.random()*100; final_pos[i*3+2] = Math.random()*100; } var material = new THREE.ShaderMaterial( { uniforms: { texture: { value: new THREE.TextureLoader().load( "bg1.jpg" )} }, vertexShader: document.getElementById( 'vertexShader' ).textContent, fragmentShader: document.getElementById( 'fragmentShader' ).textContent, } ); geometry.addAttribute( 'offset', new THREE.BufferAttribute( offset, 3 ) ); var plane = new THREE.Mesh( geometry, material ); scene.add( plane );使用tweenjs在两个数组之间非线性变换。
var tween = new TWEEN.Tween(offset); tween.to(final_pos , 5000).easing(TWEEN.Easing.Exponential.InOut).start();最后是片元着色器与顶点着色器~比较简单,前面也提过了。
<script type="vs" id="vertexShader"> attribute vec3 offset; varying vec2 vUv; void main() { vUv = uv; vec3 po = position; po.z = position.z+offset.z; po.y = position.y+offset.y; po.x = position.x+offset.x; gl_Position = projectionMatrix * modelViewMatrix * vec4( po, 1.0 ); } </script> <!-- fragment shader a.k.a. pixel shader --> <script type="fs" id="fragmentShader"> varying vec2 vUv; uniform sampler2D texture;//纹理内容数据 void main(){ gl_FragColor = texture2D(texture, vUv); } </script>最后:由于这里画的是GL_TRIANGLES,所以点与点之间会形成三角形片,下次试一试对点云使用间补动画,看看会不会有更好的效果~
在学习tweenjs时我发现阅读源码加打印调试,有的时候远比到处找文档要有用得多,我之前想着threejs的每个mesh在最后会有GL绘制的代码,结果仔细一看绘制的GL代码全都在render里面,过几天有时间还是要多拜读threejs的源码。
效果如下图:
Github:https://github.com/StringKun/ThreeJS-TweenJS-BurstingEffect