携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情 >>
初始场景
今天我们来实现下图的鬼屋效果:
在这个场景中,我们有房子、草丛、坟墓、鬼魂、雾气、阴影、灯光等元素,
创建房屋组别
因为我们的房屋可能包含门、墙壁、屋顶等很多东西,所以需要创建一个房屋组,将所有属于房屋的物体都添加到该组中,当我们后续想要移动整个屋子时,只需移动整个房屋组,而不用单独移动每个物体的位置。
const house = new THREE.Group();
scene.add(house);
下面先初始化房屋该有的物体,具体细节后面再设置
创建墙体
// Walls
const walls = new THREE.Mesh(
new THREE.BoxBufferGeometry(4, 2.5, 4),
new THREE.MeshStandardMaterial({ color: "#ac8e82" })
);
walls.position.y = 1.25;
scene.add(walls);
创建屋顶
// Roof
const roof = new THREE.Mesh(
new THREE.ConeBufferGeometry(3.5, 1, 4),
new THREE.MeshStandardMaterial({ color: "#B35F45" })
);
roof.position.y = 3;
// 旋转45度,将屋顶转正适配立方体
roof.rotation.y = Math.PI * 0.25;
house.add(roof);
创建门
// Door
const door = new THREE.Mesh(
new THREE.PlaneBufferGeometry(2.2, 2.2, 100, 100),
new THREE.MeshStandardMaterial({ color: "#aa7b7b" })
);
door.position.z = 2.01;
door.position.y = 1;
house.add(door);
创建灌木丛
// Busher
const bushGeometry = new THREE.SphereBufferGeometry(1, 16, 16);
const bushMaterial = new THREE.MeshStandardMaterial({ color: "#89c854" });
const bush1 = new THREE.Mesh(bushGeometry, bushMaterial);
// 缩放
bush1.scale.set(0.5, 0.5, 0.5);
// 位置
bush1.position.set(0.8, 0.2, 2.2);
const bush2 = new THREE.Mesh(bushGeometry, bushMaterial);
bush2.scale.set(0.25, 0.25, 0.25);
bush2.position.set(1.4, 0.1, 2.1);
const bush3 = new THREE.Mesh(bushGeometry, bushMaterial);
bush3.scale.set(0.4, 0.4, 0.4);
bush3.position.set(-0.8, 0.1, 2.2);
const bush4 = new THREE.Mesh(bushGeometry, bushMaterial);
bush4.scale.set(0.15, 0.15, 0.15);
bush4.position.set(-1, 0.05, 2.6);
house.add(bush1, bush2, bush3, bush4);
创建墓碑组别
营造鬼屋氛围,在房子周围放一写凌乱的墓碑。
// Graves 墓碑组别
const graves = new THREE.Group();
scene.add(graves);
创建墓碑
我们需要在鬼屋周围创建很多个墓碑,无法一个一个去加,因此使用for循环来实现。因为我们的地面中心处于远点,房屋也位于地面中心,因此各个置应该是围绕着屋子以原点为中心四散分布,也就是墓碑放置轨迹应该是以原点为圆心、且出去房屋的一个圆。
const graveGeometry = new THREE.BoxBufferGeometry(0.6, 0.8, 0.2);
const graveMaterial = new THREE.MeshStandardMaterial({
color: "#a9b6b1",
});
for (let i = 0; i < 80; i++) {
const angle = Math.random() * Math.PI * 2;
const radius = 3 + Math.random() * 6;
const x = Math.sin(angle) * radius;
const z = Math.cos(angle) * radius;
const grave = new THREE.Mesh(graveGeometry, graveMaterial);
grave.position.set(x, 0, z);
//改变墓碑朝向以及倾斜度
grave.rotation.y = (Math.random() - 0.5) * 0.4;
grave.rotation.z = (Math.random() - 0.5) * 0.4;
graves.add(grave);
}
截止目前,我们实现的效果如下图所示:
关于纹理、鬼魂、动画以及场景优化等,我们下一篇再详细讨论(´・ᴗ・`)