ThreeJS实现波纹粒子效果

  今天我们来用ThreeJS的库实现一个波纹粒子效果,我们用到的ThreeJS的库有CanvasRenderer.js,OrbitControls.js,Projector.js,stats.min.js和three.js。这些库都是不可或缺的,我们先来看看实现的效果,如下图所示。

  我们再来看看项目结构是怎么样的,项目结构如下图所示。

我们的效果全部写在了index.html里,现在我们直接贴出index.html的代码,同学们可以直接拿来运行,代码如下。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>演示页面</title>
    <script src="three.js"></script>
    <script src="Projector.js"></script>
    <script src="CanvasRenderer.js"></script>
    <script src="stats.min.js"></script>
    <script src="OrbitControls.js"></script>
</head>
<body>
</body>
<script>
    var SEPARATION = 200,
        AMOUNTX = 60,
        AMOUNTY = 60;
    var container, stats;
    var camera, scene, renderer, controls;
    var particles, particle, count = 0;
    var windowHalfX = window.innerWidth / 2;
    var windowHalfY = window.innerHeight / 2;
    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();

    function init() {
        container = document.createElement('div');
        document.body.appendChild(container);
        camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
        scene = new THREE.Scene();

        /**
         * 设置光源
         * */
        //点光源
        var point = new THREE.PointLight(0xffffff);//白光
        point.position.set(1200, 1200, 1200);//点光源位置
        scene.add(point);//点光源添加进场景
        //环境光
        var ambient = new THREE.AmbientLight(0x999999);//白光
        scene.add(ambient);//环境光添加进场景

        //模型
        var cubeGeometry = new THREE.CubeGeometry(1000, 1000, 1000);
        var cubeMaterial = new THREE.MeshLambertMaterial({
            color:0xffff00
            //side:THREE.DoubleSide
        });//材质对象
        var cubeMesh = new THREE.Mesh(cubeGeometry, cubeMaterial);//网格模型对象
        cubeMesh.translateY(500);
        scene.add(cubeMesh);//正方体网格模型添加到场景中

        //粒子
        particles = new Array();
        var PI2 = Math.PI * 2;
        var material = new THREE.SpriteCanvasMaterial({
            color: 0xffffff,
            program: function(context) {
                context.beginPath();
                context.arc(0, 0, 0.5, 0, PI2, true);
                context.fill();
            }
        });

        var i = 0;
        for (var ix = 0; ix < AMOUNTX; ix++) {
            for (var iy = 0; iy < AMOUNTY; iy++) {
                particle = particles[i++] = new THREE.Sprite(material);
                particle.position.x = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2);
                particle.position.z = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2);
                scene.add(particle);
            }
        }

        /**
         * 创建渲染器对象
         * */
        renderer = new THREE.CanvasRenderer();
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        container.appendChild(renderer.domElement);

        window.addEventListener('resize', onWindowResize, false);

        //交互控制器
        /**
         * 鼠标键盘事件监听器
         * */
        controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true;
        controls.dampingFactor = 0.1;
        controls.screenSpacePanning = true;
        controls.minDistance = 0;
        controls.maxDistance = 5000;
        controls.maxPolarAngle = 2*Math.PI;

        /**
         * 模型拾取
         * */
        mouse.x = -10000;
        mouse.y = -10000;

        function onMouseMove( event ) {
            // calculate mouse position in normalized device coordinates
            // (-1 to +1) for both components
            mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
            mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
        }


        window.addEventListener( 'mousemove', onMouseMove, false );
    }

    function pickUp() {
        // update the picking ray with the camera and mouse position
        raycaster.setFromCamera( mouse, camera );
        // calculate objects intersecting the picking ray
        var intersects = raycaster.intersectObjects( scene.children );
        for ( var i = 0; i < intersects.length; i++ ) {
            intersects[ i ].object.material.color.set( 0xff00ff );
        }
        if(intersects.length === 0){
            scene.children[2].material.color.set( 0xffff00 );
            for(var i=3; i<scene.children.length; i++){
                scene.children[i].material.color.set( 0xffffff );
            }
        }
        renderer.render( scene, camera );
    }


    function onWindowResize() {
        windowHalfX = window.innerWidth / 2;
        windowHalfY = window.innerHeight / 2;
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }

    var rad = 0;
    function render() {
        camera.position.set(2600, 500, 2600);
        camera.up = new THREE.Vector3(0, 1, 0);
        camera.lookAt(new THREE.Vector3(0, 500, 0));

        var i = 0;
        for (var ix = 0; ix < AMOUNTX; ix++) {
            for (var iy = 0; iy < AMOUNTY; iy++) {
                particle = particles[i++];
                particle.position.y = (Math.sin((ix + count) * 0.2) * 500) +
                    (Math.sin((iy + count) * 0.2) * 500);
                particle.scale.y = (Math.sin((ix + count) * 0.3) + 1) * 3 +
                    (Math.sin((iy + count) * 0.3) + 1) * 3;
                particle.scale.x = (Math.sin((ix + count) * 0.3) + 1) * 3 +
                    (Math.sin((iy + count) * 0.3) + 1) * 3;
            }
            scene.children[2].translateY(Math.cos(ix + count/2)*5);
        }
        //模型旋转
        scene.children[2].rotateY(Math.PI/180);
        camera.position.x = 2600*Math.cos(Math.PI/180*rad);
        camera.position.z = -2600*Math.sin(Math.PI/180*rad);
        //点光源位置
        scene.children[0].position.x = 1200*Math.cos(Math.PI/180*rad+Math.PI*0.1);
        scene.children[0].position.z = -1200*Math.sin(Math.PI/180*rad+Math.PI*0.1);
        
        controls.update();
        renderer.render(scene, camera);
        count += 0.1;
        rad += 0.2;
    }

    function animate() {
        requestAnimationFrame(animate);
        render();
        pickUp();
    }

    init();
    animate();
</script>
</html>

  我们分析一下段代码,首先我们看到requestAnimationFrame,这是主循环,我们在init()初始化函数中往scene场景中添加了particle粒子,这些粒子是在XoZ平面上均匀网格散布的。然后我们主循环每次render()都改变粒子的Y坐标,修改的规则是通过sin函数进行Y轴向扰动。每次重绘我们都修改Y坐标,就实现了粒子的波动特效。
  代码很简单,希望能帮助大家做出一套粒子波动的背景特效。鲫鱼非常愿意和大家讨论学习WebGL和ThreeJS的技术,欢迎大家留言,谢谢。本文系原创,如需引用请注明出处:https://www.cnblogs.com/ccentry/p/10125686.html                       

转载于:https://www.cnblogs.com/ccentry/p/10125686.html

要在Vue中使用Three.js实现波纹效果,可以按照以下步骤进行: 1. 首先,安装Three.js库。可以使用npm或yarn安装: ```bash npm install three # 或者 yarn add three ``` 2. 在Vue组件中引入Three.js库: ```javascript import * as THREE from 'three' ``` 3. 创建一个Three.js场景和相机,并将它们添加到Vue组件中: ```javascript mounted() { // 创建场景 this.scene = new THREE.Scene() // 创建相机 this.camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ) this.camera.position.z = 5 // 添加相机到场景中 this.scene.add(this.camera) } ``` 4. 创建一个平面几何体(PlaneGeometry)和一个材质(MeshBasicMaterial),并将它们合并成一个网格(Mesh): ```javascript mounted() { // ... // 创建平面几何体和材质 const geometry = new THREE.PlaneGeometry(10, 10, 32, 32) const material = new THREE.MeshBasicMaterial({ color: 0x0088ff, wireframe: true }) // 创建网格 this.mesh = new THREE.Mesh(geometry, material) // 添加网格到场景中 this.scene.add(this.mesh) } ``` 5. 在Vue组件的update方法中更新网格的顶点位置,以创建波纹效果: ```javascript update() { // 更新网格的顶点位置 const time = Date.now() * 0.001 const vertices = this.mesh.geometry.vertices for (let i = 0; i < vertices.length; i++) { const vertex = vertices[i] vertex.z = Math.sin(vertex.x * 0.5 + time) * 0.5 } this.mesh.geometry.verticesNeedUpdate = true } ``` 6. 在Vue组件的mounted方法中启动渲染循环: ```javascript mounted() { // ... // 启动渲染循环 this.renderer = new THREE.WebGLRenderer() this.renderer.setSize(window.innerWidth, window.innerHeight) this.$refs.container.appendChild(this.renderer.domElement) this.animate() }, methods: { animate() { requestAnimationFrame(this.animate) this.update() this.renderer.render(this.scene, this.camera) } } ``` 这样,就可以在Vue中使用Three.js实现波纹效果了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值