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坐标每次减1
sprite.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); //网格模型对象Mesh
mesh.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坐标每次减1
sprite.position.y -= 1;
if (sprite.position.y < 0) {
// 如果雨滴落到地面,重置y,从新下落
sprite.position.y = 200;
}
});
renderer.render(scene, camera); //执行渲染操作
requestAnimationFrame(renderModle)
}
renderModle ()
</script>
</body>
</html>
纹理图片
实现效果图