参考资料
- 精灵模型Sprite
- …
- Sprite模拟下雨、下雪
知识点
注:基于Three.jsv0.155.0
- 精灵模型Sprite
- 精灵模型标注场景(贴图)
- Sprite模拟下雨、下雪
精灵模型Sprite
Three.js的精灵模型Sprite
和Threejs的网格模型Mesh
一样都是模型对象,父类都是Object3D
,关于精灵模型对象Sprite
的方法和属性除了可以查看文档Sprite,也可以查看父类Object3D
。
Sprite
与矩形平面Mesh
的区别在于,当你旋转三维场景的时候,如果通过相机控件OrbitControls旋转测试,你可以发现Sprite
矩形平面会始终平行于Canvas画布或者说屏幕,而矩形平面Mesh
的姿态角度会跟着旋转,不一定平行于canvas画布。
代码实现
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Three.js</title>
</head><body></body><!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 --><script type="importmap">{"imports": {"three": "./js/three.module.js","three/addons/": "../three.js/examples/jsm/"}}</script><script type="module">import * as THREE from 'three';import { OrbitControls } from 'three/addons/controls/OrbitControls.js';const width = 800const height = 500// 场景const scene = new THREE.Scene();const texture = new THREE.TextureLoader().load("./img/6.JPG");// 创建精灵材质对象SpriteMaterialconst spriteMaterial = new THREE.SpriteMaterial({// color:0x00ffff,//设置颜色rotation:Math.PI/4,//旋转精灵对象45度,弧度值map: texture, //设置精灵纹理贴图transparent:true,//SpriteMaterial默认是true});const geometry = new THREE.BoxGeometry(25, 100, 50);geometry.translate(0, 50, 0);// 材质const material = new THREE.MeshBasicMaterial({color: 0x00ff00,transparent: true,opacity: 0.5});// mesh顶部中心添加标注,顶部中心坐标是(0,100,0)const mesh = new THREE.Mesh(geometry, material);scene.add(mesh);// 创建精灵模型对象,不需要几何体geometry参数const sprite = new THREE.Sprite(spriteMaterial);// sprite.scale.set(100, 100, 1); //只需要设置x、y两个分量就可以sprite.scale.set(10, 10, 1);// sprite.position.set(0,50,0);sprite.position.set(0, 100 + 10/2, 0);//设置位置,要考虑sprite尺寸影响scene.add(sprite);console.log(sprite);// 环境光const ambientLight = new THREE.AmbientLight( 0xffffff, 0.2);scene.add( ambientLight );// 坐标系const axes = new THREE.AxesHelper(200);scene.add(axes);const group = new THREE.Group();for (let i = 0; i < 16000; i++) {// 精灵模型共享材质const sprite = new THREE.Sprite(spriteMaterial);group.add(sprite);sprite.scale.set(1, 1, 1);// 设置精灵模型位置,在长方体空间上上随机分布const x = 1000 * (Math.random() - 0.5);const y = 600 * Math.random();const z = 1000 * (Math.random() - 0.5);sprite.position.set(x, y, z)}scene.add(group);const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000);camera.position.set(200, 200, 200);camera.lookAt(scene.position);// 渲染器const renderer = new THREE.WebGLRenderer();renderer.setSize(width, height);renderer.render(scene, camera);document.body.appendChild(renderer.domElement);const clock = new THREE.Clock();function loop() {// loop()两次执行时间间隔const t = clock.getDelta();group.children.forEach(sprite => {// 雨滴的y坐标每次减t*60sprite.position.y -= t*60;if (sprite.position.y < 0) {sprite.position.y = 600;}});requestAnimationFrame(loop);renderer.render(scene, camera);}loop();// 控制器const controls = new OrbitControls(camera, renderer.domElement);controls.addEventListener('change', () => {// 因为动画渲染了,所以这里可以省略// renderer.render(scene, camera);});</script>
</html>