通过Three.js手搓一根魔法魔力仗(夜里走路就不怕啦)

169 阅读2分钟

这是我空闲时期,收集素材,通过Three.js绘制的一根魔法魔力仗,花了点心思,算是铜鼓开发小Demo来另类记录学习进步。

创作灵感

2023-08-13-19-35-59.gif

  • 使用Three.js创造出一颗神秘而神奇的魔力仗,它含嵌了一个魔核,散发出淡淡的光芒,暗示着这个物品蕴含着无穷的魔力和力量。
  • 当你仔细观察这个魔力仗时,你会发现它的颜色似乎在不断变化,每一个角度都有着不同的颜色和光芒。
  • 魔力仗似乎有着自己的灵魂,它蕴含着神秘的力量和无尽的可能性,静静等待来人靠近。

开发流程

设置场景

  1. 创建用于渲染Three.js场景的(容器元素):
const canvas = document.querySelector("canvas.webgl") as HTMLCanvasElement;
  1. 创建渲染器(Renderer)
const renderer = new THREE.WebGLRenderer({
  canvas: document.querySelector("canvas.webgl")!,
  antialias: true,
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(0x000000, 0.0);
renderer.setSize(canvas.offsetWidth, canvas.offsetHeight);
  1. 创建场景(Scene)
const scene = new THREE.Scene();
  1. 创建相机(Camera)
const camera = new THREE.PerspectiveCamera(
  40,
  window.innerWidth / window.innerHeight,
  1,
  200
);
camera.position.set(0, 4, 20);
camera.lookAt(0, 0, 0);
  1. 添加轨道控制器(OrbitControls)
const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0);
controls.autoRotate = true;
controls.autoRotateSpeed = 0.5;
controls.enableZoom = false;

设置环境

  1. 添加光照
let light = new THREE.DirectionalLight();
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 1.0));
  1. 添加全景图
let envMap = (await getCubeMapTexture(
  renderer,
  "./hdr/satara_night_4k.hdr"
)) as THREE.Texture;

设置模型

  1. 添加魔法杖
let { models, mixer }: any = await addModel(scene);
  1. 添加魔法阵
let { ring, ringMixer }: any = await addRing(scene);
  1. 添加光粒子
let particles = new Particles(scene);

设置EffectComposer(后期处理)

  1. 添加UnrealBloomPass后期处理
let selectiveBloom = new SelectiveBloom(scene, camera, renderer);

设置场景渲染

let time = new Time();
let clock = new THREE.Clock();
window.addEventListener("resize", onResize);
renderer.setAnimationLoop(() => {
  let delta = clock.getDelta();

  time.tick();

  particles.update({
    value: time.value(),
  });

  const shader = ring.material.userData.shader;

  if (shader) {
    shader.uniforms["uTime"].value = time.value() * 0.0005;
  }

  if (mixer) mixer.update(delta);
  if (ringMixer) ringMixer.update(delta);

  if (models) {
    world.material.color.set(0x000000);
    models.forEach((model: THREE.Mesh) => {
      // @ts-ignore;
      model.material.color.set(0x000000);
    });
    ring.material.color.set(0x000000);
    scene.background = null;
    scene.environment = null;
    renderer.toneMappingExposure = 1.02;
  }
  renderer.setClearColor(0x000000);
  selectiveBloom.bloomComposer.render();
  if (models) {
    world.material.color.copy(world.userData.color);
    models.forEach((model: THREE.Mesh) => {
      // @ts-ignore;
      model.material.color.copy(model.userData.color);
    });
    ring.material.color.copy(ring.userData.color);
  }
  if (envMap) {
    scene.background = envMap;
    scene.environment = envMap;
    renderer.toneMappingExposure = 1.0;
  }
  renderer.setClearColor(0x1d1d1d);
  selectiveBloom.finalComposer.render();

  // renderer.render(scene, camera);
  controls.update();
});

相关资料