天天看點

【Three.js】七、three.js粒子、精靈、點雲一、粒子(Sprite)二、點雲(Points)

【Three.js】七、three.js粒子、精靈、點雲

  • 一、粒子(Sprite)
  • 二、點雲(Points)
粒子(也叫精靈),可用來建立非常細小的物體,可以用來模拟雨、雪、煙等其他有趣的效果。

一、粒子(Sprite)

  使用Three.Sprite()可以用來建立一個粒子,該構造函數接受一個材質參數。下面是一個利用Three.Sprite()建立的一個粒子矩陣。

let createSprites = function () {
        let texture = new THREE.TextureLoader().load(sprite);
        let spriteMaterial = new THREE.SpriteMaterial({map: texture, color: 0xff0000});
        for (let x = -5; x < 5; x++) {
            for (let y = -5; y < 5; y++) {
                let sprite = new THREE.Sprite(spriteMaterial);
                sprite.position.set(x*10, y*10, 0);
                scene.add(sprite);
            }
        }
    };
           
【Three.js】七、three.js粒子、精靈、點雲一、粒子(Sprite)二、點雲(Points)

  Three.Sprite()繼承自Object3D,是以其可以調用position、scale、rotation等方法。注意粒子不會投射任何陰影。

  上述例子建立了一百個粒子,并将這一百個粒子添加到了場景中,看起來并沒什麼不好,但如果要添加大量的粒子的話,顯然這種方式不太合适。下面介紹一種向場景中添加大量粒子的方法。

二、點雲(Points)

  建立Points與建立Mesh一樣,都需要一個Geometry和一個Material,繼承自Object3D。下面利用Points将上面例子實作:

let createSprites = function () {
        let texture = new THREE.TextureLoader().load(sprite);
        let pointsMaterial = new THREE.PointsMaterial({map: texture, color: 0xffffff, size: 10});
        let pointsGeometry = new THREE.Geometry();
        for (let x = -5; x < 5; x++) {
            for (let y = -5; y < 5; y++) {
                pointsGeometry.vertices.push(new THREE.Vector3(x*10, y*10, 0));
            }
        }
        let points = new THREE.Points(pointsGeometry, pointsMaterial);
        scene.add(points);
    };
           

将上面例子改為一個20*20*20的立體矩陣,效果依然流暢:

let createSprites = function () {
        let texture = new THREE.TextureLoader().load(sprite);
        let pointsMaterial = new THREE.PointsMaterial({map: texture, color: 0xffffff, size: 10});
        let pointsGeometry = new THREE.Geometry();
        for (let x = -10; x < 10; x++) {
            for (let y = -10; y < 10; y++) {
                for (let z = -10; z < 10; z++) {
                    pointsGeometry.vertices.push(new THREE.Vector3(x*5, y*5, z*5));
                }
            }
        }
        let points = new THREE.Points(pointsGeometry, pointsMaterial);
        scene.add(points);
    };
           
【Three.js】七、three.js粒子、精靈、點雲一、粒子(Sprite)二、點雲(Points)

  下面利用Points完成一個下雪場景:

import '../../stylus/index.styl'
import * as THREE from 'three'
import snow1 from '../../assets/images/snowflake1.png'
import snow2 from '../../assets/images/snowflake2.png'
import snow3 from '../../assets/images/snowflake3.png'
import snow4 from '../../assets/images/snowflake4.png'
import snow5 from '../../assets/images/snowflake5.png'
import {initTrackballControls, initThree, initStats} from "../../util/util";

function init(){
    let stats = initStats();
    let {scene, camera, renderer} = initThree();
    scene.fog = new THREE.FogExp2( 0x000000, 0.0008 );
    camera.position.set(0,0, 1000);
    camera.far = 20000;

    let geometry = new THREE.BufferGeometry();
    let textureLoader = new THREE.TextureLoader();
    let snowTexture1 = textureLoader.load(snow1);
    let snowTexture2 = textureLoader.load(snow2);
    let snowTexture3 = textureLoader.load(snow3);
    let snowTexture4 = textureLoader.load(snow4);
    let snowTexture5 = textureLoader.load(snow5);
    let parameters = [
        [[ 1.0, 0.2, 0.5 ], snowTexture2, 20 ],
        [[ 0.95, 0.1, 0.5 ], snowTexture3, 15 ],
        [[ 0.90, 0.05, 0.5 ], snowTexture1, 10 ],
        [[ 0.85, 0, 0.5 ], snowTexture5, 8 ],
        [[ 0.80, 0, 0.5 ], snowTexture4, 5 ]
    ];
    let vertices = [], materials = [];
    for(let i = 0; i < 10000; i++) {
        let x = Math.random() * 2000 - 1000;
        let y = Math.random() * 2000 - 1000;
        let z = Math.random() * 2000 - 1000;
        vertices.push(x, y, z);
    }
    geometry.addAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));

    for (let i = 0; i < parameters.length; i++) {
        let color = parameters[i][0];
        let sprite = parameters[i][1];
        let size = parameters[i][2];
        materials[i] = new THREE.PointsMaterial({
            color,
            map: sprite,
            size,
            blending: THREE.AdditiveBlending,
            depthTest: false,
            transparent: true
        });
        materials[i].color.setHSL(...color);
        let points = new THREE.Points(geometry, materials[i]);
        points.rotation.x = Math.random() * 6;
        points.rotation.y = Math.random() * 6;
        points.rotation.z = Math.random() * 6
        scene.add(points);
    }

    let trackball = initTrackballControls(camera, renderer);
    trackball.maxDistance = 1500;

    function render(){
        let time = Date.now() * 0.00005;
        stats.update();
        trackball.update();
        camera.position.x += 0.05;
        camera.position.y += 0.05;
        camera.lookAt(scene.position);
        for (let i = 0; i < scene.children.length; i++) {
            if (scene.children[i] instanceof THREE.Points) {
                scene.children[i].rotation.y = time * ( i < 4 ? i + 1 : - ( i + 1 ) );
            }
        }
        // 顔色随時間變化
        for ( let i = 0; i < materials.length; i ++ ) {
            let color = parameters[ i ][ 0 ];
            let h = ( 360 * ( color[ 0 ] + time ) % 360 ) / 360;
            materials[ i ].color.setHSL( h, color[ 1 ], color[ 2 ] );
        }
        requestAnimationFrame(render);
        renderer.render(scene, camera);
    }
    render();
}

init();
           
【Three.js】七、three.js粒子、精靈、點雲一、粒子(Sprite)二、點雲(Points)

完整示例(src/pages/three_sprite_demo1、src/pages/three_sprite_demo2):https://github.com/MAXLZ1/threejs_demo

繼續閱讀