学习threejs,使用canvas样式化粒子

在这里插入图片描述

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录

  • 一、🍀前言
    • 1.1 ☘️THREE.PointCloud简介
      • 1.11 ☘️THREE.PointCloudMaterial材质
  • 二、🍀使用canvas样式化粒子
    • 1. ☘️实现思路
    • 2. ☘️代码样例


一、🍀前言

本文详细介绍如何基于threejs在三维场景中使用canvas样式化粒子,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.PointCloud简介

当我们大量使用粒子时,会很快遇到性能问题,导致页面卡顿,这是因为每添加一个粒子就是一个模型,因为每个粒子对象分别由THREE.js进行管理,所以,three.js提供了另一种方式来处理大量粒子,那就是使用THREE.PointCloud。通过THREE.PointCloud,three.js不再需要管理大量的单个粒子对象,而只需管理THREE.PointCloud实例即可。
创建方法:
var cloud = new THREE.PointCloud(geom, material);
geom:THREE.Geometry对象,用于创建粒子对象
material:THREE.PointCloudMaterial 粒子云材质

1.11 ☘️THREE.PointCloudMaterial材质

概念
设置所有粒子的大小,颜色,顶点颜色,透明度,是否根据相机距离的远近改变大小等属性。
var material = new THREE.PointCloudMaterial({size: 4, vertexColors: true, color: 0xffffff});
属性
color: PointCloud中所有的粒子的颜色都相同,除非设置了vertexColors且该几何体的colors属性不为空,才会使用colors颜色,否则都使用该属性。
map:在粒子上应用某种材质。
size:粒子的大小。
sizeAnnutation:false,无论相机的位置,所有的粒子大小一致;true,离相机近的粒子更大一些,离相机越远越小。
vetexColors:true,且该几何体的colors属性有值,则该粒子会舍弃第一个属性–color,而应用该几何体的colors属性的颜色。
opacity:粒子透明度。
transparent:是否透明。
blending:渲染粒子时的融合模式。
fog:是否受场景的雾化影响。

二、🍀使用canvas样式化粒子

1. ☘️实现思路

  • 1、初始化renderer渲染器
  • 2、初始化Scene三维场景
  • 3、初始化camera相机,定义相机位置 camera.position.set
  • 4、初始化THREE.AmbientLight环境光源,scene场景加入环境光源,初始化THREE.DirectionalLight平行光源,设置平行光源位置,scene添加平行光源。
  • 5、加载几何模型:添加THREE.AxesHelper坐标辅助工具,scene场景中加入坐标辅助工具。
  • 6、加入controls控制,加入gui控制,定义gui的redraw重绘方法,方法中生成15000个随机粒子,使用THREE.PointCloudMaterial点云材质,该材质使用canvas生成的小章鱼图案作为纹理。加入stats监控器,监控帧数信息。

2. ☘️代码样例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>learn30(使用canvas样式化粒子)</title>
    <script src="lib/threejs/91/three.js"></script>
    <script src="https://johnson2heng.github.io/three.js-demo/lib/js/controls/OrbitControls.js"></script>
    <script src="https://johnson2heng.github.io/three.js-demo/lib/js/libs/stats.min.js"></script>
    <script src="lib/threejs/127/three.js-master/examples/js/libs/dat.gui.min.js"></script>
</head>
<style>
    html, body {
        margin: 0;
        height: 100%;
    }

    canvas {
        display: block;
    }
</style>
<body onload="draw()">
</body>
<script>
  var renderer
  var initRender = () => {
    renderer = new THREE.WebGLRenderer({antialias: true})
    renderer.setClearColor(new THREE.Color(0xffffff))
    renderer.setSize(window.innerWidth, window.innerHeight)
    document.body.appendChild(renderer.domElement)
  }
  var scene
  var initScene = () => {
    scene = new THREE.Scene()
  }
  var camera
  var initCamera = () => {
    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000)
    camera.position.set(20, 0, 100)
  }
  var light
  var initLight = () => {
    scene.add(new THREE.AmbientLight(0x404040))

    light = new THREE.DirectionalLight(0xffffff)
    light.position.set(1, 1, 1)
    scene.add(light)
  }

  var initModel = () => {
    var helper = new THREE.AxesHelper(500)
    scene.add(helper)
  }

  var randomColor = () => {
    var arrHex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"],
      strHex = "0x",
      index
    for (var i = 0; i < 6; i++) {
      index = Math.round(Math.random() * 15)
      strHex += arrHex[index]
    }
    return strHex
  }

  var stats
  var initStats = () => {
    stats = new Stats()
    document.body.appendChild(stats.dom)
  }

  var controls
  var initControls = () => {
    controls = new THREE.OrbitControls(camera, renderer.domElement)
    controls.enableDamping = true
    controls.autoRotate = false
  }
  var getTexture = () => {
    var canvas = document.createElement('canvas')
    canvas.width = 32
    canvas.height = 32
    var ctx = canvas.getContext('2d')
    // 绘制身
    ctx.translate(-81, -84)
    ctx.fillStyle = "orange"
    ctx.beginPath()
    ctx.moveTo(83, 116)
    ctx.lineTo(83, 102)
    ctx.bezierCurveTo(83, 94, 89, 88, 97, 88)
    ctx.bezierCurveTo(105, 88, 111, 94, 111, 102)
    ctx.lineTo(111, 116)
    ctx.lineTo(106.333, 111.333)
    ctx.lineTo(101.666, 116)
    ctx.lineTo(97, 111.333)
    ctx.lineTo(92.333, 116)
    ctx.lineTo(87.666, 111.333)
    ctx.lineTo(83, 116)
    ctx.fill()
    // 绘制眼睛
    ctx.fillStyle = "white"
    ctx.beginPath()
    ctx.moveTo(91, 96)
    ctx.bezierCurveTo(88, 96, 87, 99, 87, 101)
    ctx.bezierCurveTo(87, 103, 88, 106, 91, 106)
    ctx.bezierCurveTo(94, 106, 95, 103, 95, 101)
    ctx.bezierCurveTo(95, 99, 94, 96, 91, 96)
    ctx.moveTo(103, 96)
    ctx.bezierCurveTo(100, 96, 99, 99, 99, 101)
    ctx.bezierCurveTo(99, 103, 100, 106, 103, 106)
    ctx.bezierCurveTo(106, 106, 107, 103, 107, 101)
    ctx.bezierCurveTo(107, 99, 106, 96, 103, 96)
    ctx.fill()

    // 绘制眼球
    ctx.fillStyle = "blue"
    ctx.beginPath()
    ctx.arc(101, 102, 2, 0, Math.PI * 2, true)
    ctx.fill()
    ctx.beginPath()
    ctx.arc(89, 102, 2, 0, Math.PI * 2, true)
    ctx.fill()

    var texture = new THREE.Texture(canvas)
    texture.needsUpdate = true
    return texture
  }
  var cloud, gui
  var initGui = () => {
    gui = {
      "size": 4,
      "transparent": true,
      "opacity": 0.6,
      "vertexColors": true,
      "color": 0xffffff,
      "sizeAttenuation": true,
      "rotateSystem": true,
      redraw: function () {
        if (cloud) {
          scene.remove(cloud)
        }
        createParticles(gui.size, gui.transparent, gui.opacity, gui.vertexColors, gui.sizeAttenuation, gui.color)
        //设置是否自动旋转
        controls.autoRotate = gui.rotateSystem
      }
    }
    var datGui = new dat.GUI()
    //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值)gui.add(controls, 'size', 0, 10).onChange(controls.redraw);
    datGui.add(gui, 'transparent').onChange(gui.redraw)
    datGui.add(gui, 'opacity', 0, 1).onChange(gui.redraw)
    datGui.add(gui, 'vertexColors').onChange(gui.redraw)
    datGui.addColor(gui, 'color').onChange(gui.redraw)
    datGui.add(gui, 'sizeAttenuation').onChange(gui.redraw)
    datGui.add(gui, 'rotateSystem').onChange(gui.redraw)

    gui.redraw()
  }

  var createParticles = (size, transparent, opacity, vertexColors, sizeAttenuation, color) => {
    var geom = new THREE.Geometry()
    var material = new THREE.PointCloudMaterial({
      size: size,
      transparent: transparent,
      opacity: opacity,
      vertexColors: vertexColors,
      sizeAttenuation: sizeAttenuation,
      color: color,
      map: getTexture(),
      depthTest: false  //设置解决透明度有问题的情况
    })

    var range = 500
    for (var i = 0; i < 15000; i++) {
      var particle = new THREE.Vector3(range * Math.random() - range / 2, range * Math.random() - range / 2, range * Math.random() - range / 2)
      geom.vertices.push(particle)
      var color = new THREE.Color(+randomColor())
      //.setHSL ( h, s, l ) h — 色调值在0.0和1.0之间 s — 饱和值在0.0和1.0之间 l — 亮度值在0.0和1.0之间。 使用HSL设置颜色。
      //随机当前每个粒子的亮度
      // color.setHSL(color.getHSL().h, color.getHSL().s, Math.random() * color.getHSL().l);
      geom.colors.push(color)
    }
    // var cloud = new THREE.PointCloud(geom, material)
    cloud = new THREE.PointCloud(geom, material)
    scene.add(cloud)
  }
  var render = () => {
    renderer.render(scene, camera)
  }
  var onWindowResize = () => {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    render()
    renderer.setSize(window.innerWidth, window.innerHeight)
  }
  var animate = () => {
    render()
    stats.update()
    controls.update()
    requestAnimationFrame(animate)
  }
  var draw = () => {
    initRender()
    initScene()
    initCamera()
    initLight()
    initModel()
    initStats()
    initControls()
    initGui()

    animate()

    window.onresize = onWindowResize
  }
</script>
</html>

效果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/900352.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3+ts+vite自动导入vue的依赖

Vue3tsvite自动导入vue的依赖 unplugin-auto-import 主要依赖 npm i -D unplugin-auto-import// vite.config.ts import AutoImport from unplugin-auto-import/viteexport default defineConfig({plugins: [AutoImport({ imports: ["vue", "vue-router"…

团体标准审查结果一般会有哪几种情况?

1. 通过&#xff1a; • 标准质量高&#xff1a;标准的内容符合国家法律法规和相关标准的要求&#xff0c;技术指标科学、合理、先进&#xff0c;具有较强的适用性和可操作性 • 材料完整规范&#xff1a;送审材料齐全&#xff0c;标准的格式、文本编写等符合规定&#xff0c;为…

深入拆解TomcatJetty——Tomcat生命周期与多层容器

深入拆解Tomcat&Jetty&#xff08;三&#xff09; 专栏地址&#xff1a;https://time.geekbang.org/column/intro/100027701 1 Tomcat组件生命周期 Tomcat如何如何实现一键式启停 Tomcat 架构图和请求处理流程如图所示&#xff1a; 对组件之间的关系进行分析&#xff0c;…

deploylinux的ubuntu系统无法成功安装使用MySQL❓

&#x1f3c6;本文收录于《全栈Bug调优(实战版)》专栏&#xff0c;主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&am…

如何编辑加密的PDF文件?

PDF文件打开之后&#xff0c;发现编辑功能都是灰色的&#xff0c;无法使用&#xff0c;无法编辑PDF文件&#xff0c;遇到这种情况&#xff0c;是因为PDF文件设置了限制编辑导致的。一般情况下&#xff0c;我们只需要输入PDF密码&#xff0c;将限制编辑取消就可以正常编辑文件了…

由于导出的数据名字中带有/,导致Matlab打不开,怎么办?

&#x1f3c6;本文收录于《全栈Bug调优(实战版)》专栏&#xff0c;主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&am…

Spring Boot集成PageHelper分页插件详解---补充

这里写目录标题 内容补充 内容 ⭐最新版!SpringBoot正确集成PageHelper姿势&#xff0c;不再被误导&#xff01; Spring Boot集成PageHelper分页插件详解 原本看了这两篇文章&#xff0c;觉得写的其实挺好的。但是发现两篇文章里面&#xff0c;对于方法的使用&#xff0c;都…

昆虫种类识别数据集昆虫物种分类数据集YOLO格式VOC格式 目标检测 机器视觉数据集

一、数据集概述 数据集名称&#xff1a;10类昆虫图像数据集 数据集包含了多种农作物中常见的昆虫种类&#xff0c;包括军虫、豆蓟象、红蜘蛛、水稻瘿蚊、水稻卷叶蛾、水稻叶蝉、水稻水蚤、小麦薄翅薄翅蔗蝇、白背飞虱和黄稻螟。 1.1可能应用的领域 农业害虫监测与防控&#x…

C++,STL 044(24.10.24)

内容 1.set容器的构造函数。 2.set容器的赋值操作。 运行代码 #include <iostream> #include <set>using namespace std;void printSet(set<int> &s) {for (set<int>::iterator it s.begin(); it ! s.end(); it){cout << *it << &…

好书推荐|《Python最优化算法实战》

简介 本书以理论结合编程开发为原则&#xff0c;使用Python作为开发语言&#xff0c;讲解优化算法的原理和应用&#xff0c;详细介绍了Python基础、Gurobi 优化器、线性规划、整数规划、多目标优化、动态规划、图与网络分析、智能优化算法。对于算法部分的每一种算法都包含原理…

算法设计与分析——动态规划

1.动态规划基础 1.1动态规划的基本思想 动态规划建立在最优原则的基础上&#xff0c;在每一步决策上列出可能的局部解&#xff0c;按某些条件舍弃不能得到最优解的局部解&#xff0c;通过逐层筛选减少计算量。每一步都经过筛选&#xff0c;以每一步的最优性来保证全局的最优性…

NavMesh只制作可移动的导航网,清除多余不可走区域

只制作可移动的导航网。它使存储文件大小减小并提高性能。它消除了迁移到随机区域的问题。添加链接描述 1.如何使用 2.创建一个包含“NavMeshCleaner”组件的对象。Andadd指向可定制区域。 按住控制键并单击添加点。如果要移动它&#xff0c;请按 输入上的control键并单击。您…

flashback database 闪回数据库

1.修改闪回区大小&#xff0c;路径&#xff0c;保留时间 SQL> show parameter db_recovery_file_dest SQL> show parameter db_flashback_retention_targetSQL> alter system set db_recovery_file_dest_size20G scopeboth;System altered.SQL> alter system set …

ffmpeg视频滤镜: 裁剪-crop

滤镜简述 crop官网链接 > FFmpeg Filters Documentation crop滤镜可以对视频进行裁剪&#xff0c;并且这个滤镜可以接受一些变量比如时间和帧数&#xff0c;这样我们实现动态裁剪&#xff0c;从而实现一些特效。 滤镜使用 参数 out_w <string> ..…

云电脑使用教程标准版

云电脑&#xff0c;也称为云桌面&#xff0c;是一种通过互联网连接远程服务器&#xff0c;使用虚拟桌面环境来执行计算任务的技术。川翔云电脑通过创建软件镜像&#xff0c;让用户能够快速启动并使用预配置的软件和资料&#xff0c;提供高效且经济的云服务。相较于公有云服务&a…

83.【C语言】数据结构之顺序表的尾部插入和删除

目录 3.操作顺序表 2."伪"插入顺序表的元素 分析尾部插入函数SLPushBack 代码示例 SeqList.h main.c free(指针)出错的几种可能的原因 3."伪"删除顺序表元素 2.分析尾部删除函数SLPopBack 代码示例 错误检查 两种解决办法 1.判断size是否为负…

【Linux系统】页表的存在位 与 OS的按需加载策略

一、引入 加载程序会将程序代码全部从磁盘中加载进内存吗&#xff1f; 为什么你的电脑的运存只有16GB&#xff0c;但你可以运行上百GB的游戏&#xff0c;如黑神话马喽&#xff1f; 这就涉及到 操作系统的按需加载策略 二、页表的存在位 页表的一个标志位&#xff1a;存在位 …

webpack 老项目升级记录:从 node-sass 限制的的 node v8 提升至支持 ^node v22

老项目简介 技术框架 vue 2.5.17webpack 4.16.5"webpack-cli": "3.1.0""node-sass": "^4.7.2" 几个阶段 第一步&#xff1a;vue2 升级到最新 第一步&#xff1a;升级 vue2 至最新版本&#xff0c;截止到目前&#xff08;2024-10-…

【vim】手动安装 Leader-F

LeaderF 是一个功能强大的 Vim 插件&#xff0c;主要用于快速导航和搜索。它可以帮助用户在 Vim 中高效地查找文件、缓冲区、标签、函数等各种元素&#xff0c;极大地提高了编辑效率。 LeaderF 的安装如果按照仓库中的教程来的话可以很方便的实现安装&#xff0c;这里介绍一下…

面试官:常见的网络攻击手段有哪些?解决方案了解吗?零基础入门到精通,收藏这一篇就够了

引言&#xff1a;由于互联网和信息技术的高速发展&#xff0c;网络安全变得尤为重要&#xff0c;如果不熟悉常见的网络攻击手段&#xff0c;就会造成数据泄漏、信息安全问题、乃至国家安全问题&#xff0c;本文就来介绍下常见的网络攻击手段和一些防范措施。 题目 面试官&…