three.js 流动线shader实现方式(伪)

    技术2022-07-13  70

     原文来至,在原文的基础上,优化了一些逻辑

    https://blog.csdn.net/weixin_43842660/article/details/97940152

     

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="../js/three.min.js"></script> <script src="../js/OrbitControls.js"></script> <script src="../js/Init.js"></script> <style> #box{ position: absolute; top: 0; left: 0; right: 0; bottom: 0; } </style> </head> <body> <div class="ys-absolute-container" id="box" style="overflow: hidden"></div> <script> let el=document.getElementById('box') let app=new THREE.inithree(el,{ axes:true, }) let scene=app.scene let renderer=app.renderer let camera=app.camera let controls=app.controls camera.position.set(50, 50, 50) camera.lookAt(new THREE.Vector3(0, 0, 0)) function addGroundPlane() { // create the ground plane var planeGeometry = new THREE.PlaneGeometry(60, 20, 120, 120); var planeMaterial = new THREE.MeshPhongMaterial({ color: 0xffffff }); var plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.receiveShadow = true; // rotate and position the plane plane.rotation.x = -0.5 * Math.PI; plane.position.x = 15; plane.position.y = 0; plane.position.z = 0; scene.add(plane); return plane; } addGroundPlane() var ambientLight = new THREE.AmbientLight(0xffffff,0.9); scene.add(ambientLight); // 参数依次为color、强度、距离、角度,penumbra,decay var spotLight = new THREE.SpotLight(0x00ff00); spotLight.position.set(30,25,-10) scene.add(spotLight); // const spotLightHelper = new THREE.SpotLightHelper( spotLight ) // scene.add( spotLightHelper ) var amount = 1000; var radius = 200; var positions = new Float32Array(amount * 3); var colors = new Float32Array(amount * 3); var sizes = new Float32Array(amount); var vertex = new THREE.Vector3(); var color = new THREE.Color(0xffffff); for (var i = 0; i < amount; i++) { vertex.x = (Math.random() * 2 - 1) * radius; vertex.y = (Math.random() * 2 - 1) * radius; vertex.z = (Math.random() * 2 - 1) * radius; vertex.toArray(positions, i * 3); if (vertex.x < 0) { color.setHSL(0.5 + 0.1 * (i / amount), 0.7, 0.5); } else { color.setHSL(0.0 + 0.1 * (i / amount), 0.9, 0.5); } color.toArray(colors, i * 3); sizes[i] = 2; //线粗细 } var curve = new THREE.CatmullRomCurve3(); function Point(pos) { this.vector = new THREE.Vector3(pos.x, pos.y, pos.z); } var points = [ new Point({ x: -100, y: 0, z: 0 }), new Point({ x: -50, y: 50, z: 0 }), new Point({ x: 100.199427036501952, y: 0, z: 0 }), ] points.forEach(function (point) { curve.points.push(point.vector); }); var geometry = new THREE.Geometry(); geometry.vertices = curve.getPoints(amount - 1); var pointArr = []; var colorArr = []; var objArr = geometry.vertices; for (var i = 0; i < objArr.length; i++) { pointArr.push(objArr[i].x); pointArr.push(objArr[i].y); pointArr.push(objArr[i].z); colorArr.push(0); colorArr.push(0); colorArr.push(1); } pointArr = new Float32Array(pointArr); var geometry = new THREE.BufferGeometry(); geometry.addAttribute('position', new THREE.BufferAttribute(pointArr, 3)); geometry.addAttribute('customColor', new THREE.BufferAttribute(colors, 3)); geometry.addAttribute('size', new THREE.BufferAttribute(sizes, 1)); let v=` attribute float size; //顶点大小,由geometry的属性传入 attribute vec3 customColor; //顶点自定义颜色,由geometry的属性传入 varying vec3 vColor; //插值颜色 void main() { vColor = customColor; //插值颜色,由geometry的属性传入 gl_PointSize = 5.0*size ; //gl_Position的计算总是固定为 投影矩阵*模型视图矩阵*位置向量 gl_Position = projectionMatrix*modelViewMatrix * vec4( position, 1.0 ); }` //原文顶点着色器后三句为,个人没发现size的区别,就简化了 // vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); // // gl_PointSize = size * ( 300.0 / -mvPosition.z ); // // gl_Position = projectionMatrix * mvPosition; let f=` uniform vec3 color; //顶点颜色 ,由shader构造材质时引入 uniform sampler2D pointTexture; //顶点纹理采样器 varying vec3 vColor; //顶点插值颜色 void main() { //原文 gl_FragColor = vec4( color * vColor, 1.0 ) * texture2D( pointTexture, gl_PointCoord ); //改为一下方式更好看,也易于初学者理解一些 gl_FragColor = vec4( color * vColor, 1.0 ) ; } ` var material = new THREE.ShaderMaterial({ uniforms: { color: { value: new THREE.Color(0xf0ffff) }, pointTexture: { value: new THREE.TextureLoader().load("../images/red_line.png") } }, vertexShader: v, fragmentShader: f, // blending: THREE.AdditiveBlending, depthTest: false, depthWrite: false, transparent: true }); sphere = new THREE.Points(geometry, material); scene.add(sphere); let arr,delArray,newArray function animate() { controls.update() //实际上该种方式就是一堆点构线,将点数组的前三个一直取出,在拼接到最后,造成流动的效果 //实际上并不是线,放大之后就可以看得很清楚 arr = sphere.geometry.attributes.position.array.toString().split(","); delArray = arr.splice(0, 9); newArray = arr.concat(delArray); sphere.geometry.attributes.position.array = new Float32Array(newArray); sphere.geometry.attributes.position.needsUpdate = true; renderer.render(scene, camera) requestAnimationFrame(animate) } animate() </script> </body> </html>

     

    Processed: 0.017, SQL: 10