Three.js(18)——Haunted House(1)

230 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情 >>

初始场景

今天我们来实现下图的鬼屋效果:

微信截图_20220824164136.png

在这个场景中,我们有房子、草丛、坟墓、鬼魂、雾气、阴影、灯光等元素,

创建房屋组别

因为我们的房屋可能包含门、墙壁、屋顶等很多东西,所以需要创建一个房屋组,将所有属于房屋的物体都添加到该组中,当我们后续想要移动整个屋子时,只需移动整个房屋组,而不用单独移动每个物体的位置。

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);
}

截止目前,我们实现的效果如下图所示:

微信截图_20220825135836.png

关于纹理、鬼魂、动画以及场景优化等,我们下一篇再详细讨论(´・ᴗ・`)