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

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

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>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章