ThreeJS——精灵模型实现下雨场景效果
精灵模型对像sprite和网格模型对象一样需要设置材质效果,不同的是精灵模型对像不需要绘制几何体,ThreeJS引擎在渲染时会自动设置。引用精灵模型对像可以实现很多比较炫的特效,比如实现模拟下雨、下雪、渲染森林、如PM2.5数据可视化等等。
小猿这里介绍的模拟下雨场景效果的思路是通过足够多的精灵模型构成一个粒子系统,雨滴在一定空间内随机分布,每个精灵模型都使用一个背景透明的雨滴图片作为纹理贴图。
创建精灵模型,并加载一个背景透明的原形贴图。
// 加载一个背景透明的圆形贴图,矩形精灵显示为圆形效果let textureTree = new THREE.TextureLoader().load("./../img/rain_1.png");// 批量创建表示雨滴的精灵模型for (let i = 0; i < 400; i++) {let spriteMaterial = new THREE.SpriteMaterial({map: textureTree,// 设置精灵纹理贴图});// 创建精灵模型对象let sprite = new THREE.Sprite(spriteMaterial);// 控制精灵大小,sprite.scale.set(8, 10, 1); // 只需要设置x、y两个分量就可以let k = Math.random() - 0.5;let k2 = Math.random() - 0.5;// 设置精灵模型位置,在空间中随机分布sprite.position.set(1000 * k, 300 * Math.random(), 1000 * k2)group.add(sprite);}
创建一个组表示所有的精灵模型。
// 创建一个组表示所有的雨滴let group = new THREE.Group();
设置透视投影相机对像。
/**透视投影相机对象*/let camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000);camera.position.set(292, 109, 268);//设置相机位置camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
渲染方法实现。
//执行渲染操作 指定场景、相机作为参数function renderModle() {group.children.forEach(sprite => {// 雨滴的y坐标每次减1sprite.position.y -= 1;if (sprite.position.y < 0) {// 如果雨滴落到地面,重置y,从新下落sprite.position.y = 200;}});renderer.render(scene, camera); //执行渲染操作requestAnimationFrame(renderModle)}
完整代码如下:
<html lang="en"><head><meta charset="UTF-8"><title></title><style>body{margin: 0;overflow: hidden;}</style></head><body><script src="./../js/three.js"></script><script src="./../js/OrbitControls.js"></script><script>/** 创建场景对象Scene* */let scene = new THREE.Scene();// 创建一个组表示所有的雨滴let group = new THREE.Group();let geometry = new THREE.PlaneGeometry(1000, 1000); //矩形平面// 加载树纹理贴图let texture = new THREE.TextureLoader().load('./../img/grass.jpg');// 设置阵列texture.wrapS = THREE.RepeatWrapping;texture.wrapT = THREE.RepeatWrapping;// uv两个方向纹理重复数量texture.repeat.set(10, 10);let material = new THREE.MeshLambertMaterial({map: texture,side: THREE.DoubleSide});let mesh = new THREE.Mesh(geometry, material); //网格模型对象Meshmesh.position.set(0,0,0)mesh.rotateX(-80)// mesh.rotateY(10)scene.add(mesh)// 加载一个背景透明的圆形贴图,矩形精灵显示为圆形效果let textureTree = new THREE.TextureLoader().load("./../img/rain_1.png");// 批量创建表示雨滴的精灵模型for (let i = 0; i < 400; i++) {let spriteMaterial = new THREE.SpriteMaterial({map: textureTree,// 设置精灵纹理贴图});// 创建精灵模型对象let sprite = new THREE.Sprite(spriteMaterial);// 控制精灵大小,sprite.scale.set(8, 10, 1); // 只需要设置x、y两个分量就可以let k = Math.random() - 0.5;let k2 = Math.random() - 0.5;// 设置精灵模型位置,在空间中随机分布sprite.position.set(1000 * k, 300 * Math.random(), 1000 * k2)group.add(sprite);}scene.add(group)/*** 光源设置*///点光源let point = new THREE.PointLight(0xffffff);point.position.set(400, 200, 300);scene.add(point);//环境光let ambient = new THREE.AmbientLight(0x444444);scene.add(ambient);/*** 相机设置*/let width = window.innerWidth; //窗口宽度let height = window.innerHeight;let k1 = width / height; //窗口宽高比let s = 200;/**透视投影相机对象*/let camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000);camera.position.set(292, 109, 268);//设置相机位置camera.lookAt(scene.position); //设置相机方向(指向的场景对象)/*** 创建渲染器对象*/let renderer = new THREE.WebGLRenderer();renderer.setSize(width, height);//设置渲染区域尺寸renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色document.body.appendChild(renderer.domElement); // body元素中插入canvas对象//执行渲染操作 指定场景、相机作为参数function renderModle() {group.children.forEach(sprite => {// 雨滴的y坐标每次减1sprite.position.y -= 1;if (sprite.position.y < 0) {// 如果雨滴落到地面,重置y,从新下落sprite.position.y = 200;}});renderer.render(scene, camera); //执行渲染操作requestAnimationFrame(renderModle)}renderModle ()</script></body></html>
纹理图片
实现效果图
