学习three.js四个月了,最近终于利用shader粒子做出了我心心念念的蝌蚪状飞线,这个网上也是查不到什么资料的,2Dcanvas的可以查得到,3D的都藏着掖着很难找的到相关案例,最近我通过腾讯一个小姐姐发布几个three.js 案例受到了一点启发,终于花了一个晚上做了出来,也是第一次在three.js中使用shader。

下面是效果图:

先说说思路,第一步是制作一个蝌蚪状的粒子束,其实很简单就是让粒子一个一个从小到大排列就好,这部分主要利用shader处理,代码如下:

const vs:string = `

attribute float size; // 顶点尺寸

attribute vec4 colors; //顶点颜色

varying float opacity; // 控制透明度

varying vec3 vexColor; // 顶点颜色

void main(){

vexColor.x = colors.r;

vexColor.y = colors.g;

vexColor.z = colors.b;

//w分量为透明度

opacity = colors.w;

vec4 mvPosition = modelViewMatrix * vec4(position,1.0); //?这里模型矩阵,坐标向量,和投影矩阵都是three给你注入的好像。

gl_PointSize = size;

gl_Position = projectionMatrix * mvPosition;

}

`;

然后就是配置数据源,数据源可以利用three.js 给的curve3组件中的getPoints取得,代码如下

this.spline = new THREE.CatmullRomCurve3(vecs);

this.pointNum = num;

this.distance = this.spline.getLength();

//初始化粒子

this.points = this.spline.getPoints(num);

const colorsLen = this.points.length * 4;

const sizeLen = this.points.length;

const colors:Float32Array = new Float32Array(colorsLen);

const sizes:Float32Array = new Float32Array(sizeLen);

this.geometry = new THREE.BufferGeometry().setFromPoints(this.points);

for(let i=0,z=0;i<colorsLen;i+=4,z++){

//color

colors[i] = color.r;

colors[i+1] = color.g;

colors[i+2] = color.b;

// opacity

colors[i+3] = (i+3)/sizeLen;

// size从小到大

sizes[z] =size*(z/sizeLen);

};

this.geometry.addAttribute('colors',new THREE.BufferAttribute(colors,4));

this.geometry.addAttribute('size',new THREE.BufferAttribute(sizes,1));

第二部分就是如何让粒子运动起来,这里我借助了tween.js,整体思路就是取一段固定的粒子数目+加上Curve3的getPointAt取点函数,不断的取出固定数目并不断前移的坐标,直接修改bufferGeometry的position数据即可。

下面贴出完整代码:

import * as THREE from "three";

import TWEEN from "@tweenjs/tween.js";

const fs:string = `

uniform sampler2D texture;

varying float opacity;

varying vec3 vexColor;

void main(){

gl_FragColor = vec4(vexColor,opacity);

gl_FragColor = gl_FragColor * texture2D(texture,gl_PointCoord);

}

`;

const vs:string = `

attribute float size;

attribute vec4 colors;

varying float opacity;

varying vec3 vexColor;

void main(){

vexColor.x = colors.r;

vexColor.y = colors.g;

vexColor.z = colors.b;

//w分量为透明度

opacity = colors.w;

vec4 mvPosition = modelViewMatrix * vec4(position,1.0);

gl_PointSize = size;

gl_Position = projectionMatrix * mvPosition;

}

`;

/**

* 粒子飞线

*/

export default class PointsFlyLine{

//粒子位置

geometry: THREE.BufferGeometry;

//曲线

spline: THREE.CatmullRomCurve3;

//粒子系统

particleSystem: THREE.Points;

//粒子数目

pointNum:number;

//粒子间的总距离

distance: number;

points: THREE.Vector3[];

tween: any;

/**

* 创建粒子系统

* @param points 粒子

* @param size 粒子大小

* @param num 粒子数目

* @param color 粒子颜色

*/

constructor({ vecs, num, size, color }: { vecs: THREE.Vector3[]; num: number; size: number; color: THREE.Color; }){

this.spline = new THREE.CatmullRomCurve3(vecs);

this.pointNum = num;

this.distance = this.spline.getLength();

//初始化粒子

this.points = this.spline.getPoints(num);

const colorsLen = this.points.length * 4;

const sizeLen = this.points.length;

const colors:Float32Array = new Float32Array(colorsLen);

const sizes:Float32Array = new Float32Array(sizeLen);

this.geometry = new THREE.BufferGeometry().setFromPoints(this.points);

for(let i=0,z=0;i<colorsLen;i+=4,z++){

//color

colors[i] = color.r;

colors[i+1] = color.g;

colors[i+2] = color.b;

// opacity

colors[i+3] = (i+3)/sizeLen;

// size从小到大

sizes[z] =size*(z/sizeLen);

};

this.geometry.addAttribute('colors',new THREE.BufferAttribute(colors,4));

this.geometry.addAttribute('size',new THREE.BufferAttribute(sizes,1));

const uniforms:object = {

texture: {

value: new THREE.CanvasTexture(this.createSpriteCanvas(size)),

}

};

const shaderMaterial:THREE.ShaderMaterial = new THREE.ShaderMaterial({

uniforms,

vertexShader:vs,

fragmentShader:fs,

transparent:true,

depthTest:false

});

this.particleSystem = new THREE.Points(this.geometry,shaderMaterial);

}

//飞线开始

start(){

const max = this.distance*10;

const end:number = this.pointNum;

const m = {start:0,end};

this.tween = this.tweenAnimate(m,{start:max-end,end:max},2000,null,()=>{

let pointArr:number[] = [];

let s = Math.round(m.start),e = Math.floor(m.end);

for (let i = s; i <= e && i<=max; i++) {

pointArr = pointArr.concat(this.spline.getPointAt(i/max).toArray());

}

this.geometry.attributes.position = new THREE.BufferAttribute(new Float32Array(pointArr),3);

});

this.tween.repeat(Infinity).start();

}

stop(){

this.tween.stop();

}

tweenAnimate(current:object, target:object, interval:number, animation?:TWEEN.Easing, onUpdate?:Function, complete?:Function) {

var animate = animation ? animation : TWEEN.Easing.Linear.None;

let tween = new TWEEN.Tween(current).to(target, interval).easing(animate);

onUpdate && tween.onUpdate(() => onUpdate());

complete && tween.onComplete(() => complete());

return tween;

}

//创建圆形精灵贴图

createSpriteCanvas(size:number){

const canvas = document.createElement('canvas');

canvas.width = canvas.height = size;

const context = canvas.getContext('2d');

if(context!=null){

context.fillStyle='rgba(255,255,255,.0)';

context.beginPath();

context.arc(size/2,size/2,size/2,0,Math.PI*2);

context.fillStyle = 'white';

context.fill();

context.closePath();

}

return canvas;

}

}

three.js+shader 制作粒子飞线,小蝌蚪那种。相关推荐

  1. 数据可视轻松制作多点飞线图

    今天为大家讲解一下,在数据可视化软件平台中,地图-多点飞线图的使用. 数据可视化,一个可以帮助您展示数据,统计数据,分析数据,通过可视化界面,多种统计图并行的方式,完成数据交互展示. 首先,我们创建一 ...

  2. shader实现飞线效果(three.js练习)

    一.先看看效果 二.实现方法: 1.飞线的相关配置数据准备 // 飞线效果的相关配置数据 const flyData = [{start: { //起始点位置x: 0,y: 0,z: 0},end: ...

  3. d3.js-V3制作简单的飞线图

    d3.js制作简单的飞线图 简介 期末的一个小作业,放上来分享一下.若有不懂的地方欢迎在评论区提问~ 最终效果图: 使用工具 d3.js (V3版本) 步骤简介 准备好数据. 绘制一个中国地图. 绘制 ...

  4. web端的shader Threejs飞线

    目标 之前想用粒子来实现一下飞线的效果,看到很多大佬的代码发现使用粒子会是一个不错的选择,因为粒子的渲染比较省性能,之前看到有人使用圆形的粒子 后来发现其实普通的正方形的粒子就行,因为在线的粗度比较小 ...

  5. THREE.JS 绘制飞线 攻击线 迁移线 拓扑图动画线条等

    THREE.JS 绘制飞线 攻击线 迁移线 拓扑图动画线条等 在THREE中如何绘制飞线:使用的是Points+Shader封装的一个飞线方法:可以用于攻击线路,指向效果等:显卡GT730 6000根 ...

  6. echart制作出中国地图飞线图

    先上图片 参考内容:https://www.makeapie.com/editor.html?c=xm7FhEqj6w&v=2 这里直接展示代码,相关的图标,背景,大部分在代码中都做了注释(背 ...

  7. [Python] 利用 Python 制作“飞花令”小工具

    转载请注明:陈熹 chenx6542@foxmail.com (简书号:半为花间酒) 若公众号内转载请联系公众号:早起Python 介绍:飞花令是古时候人bai们经常玩一种"行酒令" ...

  8. AMap + echarts、google map + d3.js分别实现数据可视化中的飞线图(迁徙图)

    首先肯定是给出demo啦: 演示demo 直接到左侧选择框中选择View taxi flow里面随便选个日期 总体介绍 最近由于工作室项目需要做一个数据可视化平台,这个平台最终是交由国外人使用的.而国 ...

  9. shader飞线改进版

    项目github地址:https://github.com/ecojust/flyline 前面写过一个飞线(基于THREE.Line进行的颜色变化),只是简单地将可视区片元颜色的alpha通道值设为 ...

最新文章

  1. 反射型 DDoS 攻击的原理和防范措施
  2. springcloud(一)-初识
  3. Tcpdump源码分析系列7:main函数
  4. 微机原理换行代码_微机原理实验保留最长行输入字符的程序
  5. 分布式事务slides
  6. 无锡金秋购物节 淘菜菜提供社区消费全景式服务
  7. 原来 JS 也支持跟 Lua 语意一样的内嵌函数的闭包概念
  8. Linux下添加eigen头文件,移植Eigen库到SylixOS下及使用方法
  9. 大数据核心技术是什么?
  10. 将[c语言中文网](http://c.biancheng.net/view/1380.html)的“”23 种设计模式“的网页转成pdf
  11. BMapGL实现地图轨迹运动(地图视角不变)
  12. 音视频 | 音视频学习-01
  13. CSMA/CD技术详解
  14. CnOpenData·IFR工业机器人数据
  15. SCCB与IIC的异同及FPGA实现的注意事项
  16. 魔兽地图编辑器触发器笔记
  17. 《Oracle内核技术解密》读书笔记(三)
  18. Python是“真火”还是“虚火”?
  19. 电子标签亮灯拣选解决方案
  20. 视频号怎么打造私域流量,视频号+公众号+朋友圈+社群:国仁楠哥

热门文章

  1. 牛客网 SQL大厂面试真题篇 SQL4 每个创作者每月的涨粉率及截止当前的总粉丝量
  2. 年薪百万程序员的成功基础
  3. java使用openOffice 实现word转pdf
  4. 华为C8813D详细刷机、ROOT权限、解锁、刷机教程
  5. python量化策略源码_Python量化交易进阶讲堂-创建自定义量化回测框架
  6. 迅为瑞芯微RK3399开发板Debian9多媒体测试之Gstreamer测试
  7. C#软件开发实例.私人订制自己的屏幕截图工具(一)功能概览
  8. 西安建筑科技大学的计算机专业怎么样,西安建筑科技大学-XAUAT
  9. 开发版linux随身wifi密码,linux下使用随身wifi–ubuntu下使用随身wifi
  10. android cardview透明,CardView上的透明背景 – Android