Three.js使用canvas样式化粒子(代码实例)
程序员文章站
2022-06-13 11:30:01
简介
使用canvas样式化粒子,那么我们首先需要先绘制一个canvas画布的纹理。比如:
这是教程使用canvas绘制的吃豆人里面的一个小怪物,而我们今天要实现的就是,使...
简介
使用canvas样式化粒子,那么我们首先需要先绘制一个canvas画布的纹理。比如:
这是教程使用canvas绘制的吃豆人里面的一个小怪物,而我们今天要实现的就是,使用它来样式化粒子。
过程
通过上一节的代码,我们再扩展一下,首先需要获取到canvas对象,通过canvas对象生成可以供粒子使用的three.texture对象。 然后,将纹理对象赋值给three.pointsmaterial的map属性,按照上一节的代码继续往下写,就发现,实现了当前的效果。
成千上万的五颜六色的小怪物,恐怖感油然而生!
案例代码
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>title</title> <style type="text/css"> html, body { margin: 0; height: 100%; } canvas { display: block; } </style> </head> <body onload="draw();"> </body> <script src="https://johnson2heng.github.io/three.js-demo/lib/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="https://johnson2heng.github.io/three.js-demo/lib/js/libs/dat.gui.min.js"></script> <script> var renderer; function 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 camera; function initcamera() { camera = new three.perspectivecamera(45, window.innerwidth / window.innerheight, 1, 1000); camera.position.set(20, 0, 100); } var scene; function initscene() { scene = new three.scene(); } var light; function initlight() { scene.add(new three.ambientlight(0x404040)); light = new three.directionallight(0xffffff); light.position.set(1, 1, 1); scene.add(light); } function initmodel() { //轴辅助 (每一个轴的长度) var object = new three.axeshelper(500); scene.add(object); } //随机生成颜色 function 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; function initstats() { stats = new stats(); document.body.appendchild(stats.dom); } //用户交互插件 鼠标左键按住旋转,右键按住平移,滚轮缩放 var controls; function initcontrols() { controls = new three.orbitcontrols(camera, renderer.domelement); // 如果使用animate方法时,将此函数删除 //controls.addeventlistener( 'change', render ); // 使动画循环使用时阻尼或自转 意思是否有惯性 controls.enabledamping = true; //动态阻尼系数 就是鼠标拖拽旋转灵敏度 //controls.dampingfactor = 0.25; //是否可以缩放 controls.enablezoom = true; //是否自动旋转 controls.autorotate = false; //设置相机距离原点的最远距离 controls.mindistance = 20; //设置相机距离原点的最远距离 controls.maxdistance = 10000; //是否开启右键拖拽 controls.enablepan = true; } //生成gui设置配置项 var gui; //生成纹理图形 function 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; function 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(); } //生成粒子的方法 function createparticles(size, transparent, opacity, vertexcolors, sizeattenuation, color) { //存放粒子数据的网格 var geom = new three.geometry(); //样式化粒子的three.pointcloudmaterial材质 var material = new three.pointsmaterial({ 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(math.random() * range - range / 2, math.random() * range - range / 2, math.random() * range - 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); } //生成模型,添加到场景当中 cloud = new three.points(geom, material); scene.add(cloud); } function render() { renderer.render(scene, camera); } //窗口变动触发的函数 function onwindowresize() { camera.aspect = window.innerwidth / window.innerheight; camera.updateprojectionmatrix(); render(); renderer.setsize(window.innerwidth, window.innerheight); } function animate() { //更新控制器 controls.update(); render(); //更新性能插件 stats.update(); requestanimationframe(animate); } function draw() { initrender(); initscene(); initcamera(); initlight(); initmodel(); initcontrols(); initstats(); initgui(); animate(); window.onresize = onwindowresize; } </script> </html>