Three.js 粒子系統動畫與發光材質——利用HTML5畫布繪製

用Three.js作了個字體的粒子系統動畫,可設置speedX=speedY=speedZ=1000的參數改變更畫效果,截圖以下:javascript

clipboard.png

預覽地址:https://joeoeoe.github.io/Jon...
此文重講思路,爲方便解釋,部分代碼有作修改,此外由於部分代碼太長,因此作的是截取,完整代碼請看github
gitHub地址:https://github.com/Joeoeoe/Jo...
(有興趣的同窗能夠本身試試調參數嘗試出不一樣的動畫,滑稽臉.jpg)html

Three的三大基本組件:相機,渲染器,場景在這就不必說了吧,百度有不少資料
接下來咱們分幾個步驟來說解如何作出這個粒子動畫java

目錄:

1.思路敘述
2.建立文字幾何體並獲取點集
3.用HTML5畫布編寫發光粒子貼圖
4.建立粒子系統
5.如何完成粒子動畫
6.結束git

一.思路敘述

1.建立文字幾何體,獲取點的集合,做爲粒子動畫的終點(因此文字幾何體不用送入場景中!咱們只是要個位置而已
2.選取一個起始點,建立粒子系統(粒子貼圖也包含在這部分)
3.編寫粒子動畫,使粒子系統動起來github

二.建立字體

先看函數架構json

let fontLoader = new THREE.FontLoader();
fontLoader.loag('字體包路徑',onLoad函數,onProgress函數,onError函數)

這裏注意字體包的選擇,不一樣字體包的幾何體Verctor的數量是不同的,這裏我選擇optimer_bold.typeface.json的字體包,你們能夠在three.js的集合包中找到各類各樣的字體包
待字體包加載完後,咱們便調用onLoad函數,建立字體
(先截取onLoad函數的一部分,餘下的主要代碼均寫在onLoad函數中)canvas

fontLoader.load('../../../package/font/optimer_bold.typeface.json',
        function (font) {
            let fontOptions ={
                font:font,
                size:1000,
                height:20,
                fontWeight:'bold',
                curveSegments: 12,  //number of points on the curves
                bevelEnabled:true,
                bevelThickness:2,
                bevelSize:8,
                bevelSegments:5
            };
            geometry = new THREE.TextGeometry("Jonithan" ,fontOptions);
            geo_ver = getGeoVer(geometry);
            .....

注意在onLoad函數中傳入參數font,而後配置字體樣式fontOptions,接着生成字體幾何體geometry,而後就獲取點集
這樣咱們就得到了終點位置api

三.編寫發光粒子貼圖

首先創造canvas,而且調用createRadialGradient方法,用於繪製漸變色,繪製漸變色的原理是設定好一組同心圓,用addColorStop方法在不一樣位置設定顏色,以下代碼所示架構

function createLightMateria() {
let canvasDom = document.createElement('canvas');
canvasDom.width = 16;
canvasDom.height = 16;
let ctx = canvasDom.getContext('2d');
//根據參數肯定兩個圓的座標,繪製放射性漸變的方法,一個圓在裏面,一個圓在外面
let gradient = ctx.createRadialGradient(
    canvasDom.width/2,
    canvasDom.height/2,
    0,
    canvasDom.width/2,
    canvasDom.height/2,
    canvasDom.width/2);
gradient.addColorStop(0,'rgba(255,255,255,1)');
gradient.addColorStop(0.005,'rgba(139,69,19,1)');
gradient.addColorStop(0.4,'rgba(139,69,19,1)');
gradient.addColorStop(1,'rgba(0,0,0,1)');

顏色繪製好後咱們把顏色配置給ctx,並繪製貼圖,等會用於與粒子map
代碼以下dom

//設置ctx爲漸變色
ctx.fillStyle = gradient;
//繪圖
ctx.fillRect(0,0,canvasDom.width,canvasDom.height);

//貼圖使用
let texture = new THREE.Texture(canvasDom);
texture.needsUpdate = true;//使用貼圖時進行更新
return texture;
}

這樣,咱們等會就直接拿return的texture做爲貼圖

四.建立起始點粒子系統

接下來咱們就能夠創造粒子系統了,先說一下咱們要用到的三個api
new Three.Geometry()
new Three.PointsMaterial()
new Three.Points()
思路:建立一個原點Geometry,遍歷向Geometry.vertices推入起始點,再調用new Three.Points()傳入Geometry和粒子配置生成粒子系統

首先作好粒子配置:

pointsMaterial = new THREE.PointsMaterial({
    color:0xffffff,
    size:80,
    transparent:true,//使材質透明
    blending:THREE.AdditiveBlending,
    depthTest:false,//深度測試關閉,不消去場景的不可見面
    map:createLightMateria()//剛剛建立的粒子貼圖就在這裏用上
})

接着建立Geomotry和粒子系統

let[x,y,z] =[0,0,0];
let originGeo = new THREE.Geometry();
for (let i = 0; i <originParticleNum; i++){//循環建立Geo
    originGeo.vertices.push(new THREE.Vector3(x,y,z));
}
let originParticleField = new THREE.Points(originGeo,pointsMaterial);
return originParticleField;

這樣子就得到原點粒子系統了

五.如何完成粒子動畫

先看看Three.js中的動畫是如何完成的

function animate() {
    threeConf.stats.begin();
    threeConf.renderer.clear();
    threeConf.renderer.render(threeConf.scene,threeConf.camera);
    threeConf.control.update();
    particleAnimate();//粒子動畫函數
    threeConf.stats.end();
    requestAnimationFrame(animate);
  }

即經過不停地調用animate函數,進行渲染,這個animate函數中的particleAnimate()函數就是咱們的粒子動畫,particleAnimate函數中就改變點的位置

接下來咱們就來編寫particleAnimate函數,先貼完整代碼再講過程

function particleAnimate () {
    for(let i = 0; i < pointsNum; i++){
        let originP = originVer[i],
            destiP =  destiVer[i];
        let distance = Math.abs(originP.x - destiP.x) + Math.abs(originP.y - destiP.y) + Math.abs(originP.z - destiP.z);
        if (distance > 1){
            //利用距離與座標差的餘弦值
            originP.x += ((destiP.x - originP.x)/distance) * speedX * (1 - Math.random());
            originP.y += ((destiP.y - originP.y)/distance) * speedY * (1 - Math.random());
            originP.z += ((destiP.z - originP.z)/distance) * speedZ * (1 - Math.random());
        }
    }
    originParticlae.geometry.verticesNeedUpdate=true;
}

先搞清楚給部分變量:
pointsNum:粒子數,
originVer:起始點集合,
destiVer:目標位置點集合(就是來自於TextGeometry),
speedX,speedY,speedZ分別表示點在各軸上每次移動的速度
originParticlae:起始點粒子系統
接下來說過程:

1.獲取起始點與目標點的大體距離

let distance = Math.abs(originP.x - destiP.x) + Math.abs(originP.y - destiP.y) + Math.abs(originP.z - destiP.z);

2.距離大於1時進行移動,這裏利用餘弦值進行距離的自增運算

if (distance > 1){
            //利用距離與座標差的餘弦值
    originP.x += ((destiP.x - originP.x)/distance) * speedX * (1 - Math.random());
    originP.y += ((destiP.y - originP.y)/distance) * speedY * (1 - Math.random());
    originP.z += ((destiP.z - originP.z)/distance) * speedZ * (1 - Math.random());
        }

3.最後設置更新粒子系統點爲true

originParticlae.geometry.verticesNeedUpdate=true;

六.結束

最後進行代碼的整合
以上即是全部的重點思路,根據這個思路,寫好代碼,就能夠作出粒子動畫了!

相關文章
相關標籤/搜索