欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Three.js 学习 1. 绘制一个旋转的立方体

程序员文章站 2024-03-16 19:50:40
...

原址

Three.js 学习 1. 绘制一个旋转的立方体

参考:https://threejs.org/docs/index.html#manual/zh/introduction/Creating-a-scene

引入

Three.js 没有安装文档,示例中就直接引入一个 Three.js 的脚本文件,我去 jsdelivr 上找到寻找到了 Three.js 的 cdn,直接引入即可。

另外,Three.js 默认的全局变量是 THREE,例如:

<script
  src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"
  integrity="sha256-qdgepj/cuK3QsiLmELb2ouRo37UbWaIhCJmRisNu0/c="
  crossorigin="anonymous"
></script>
<script>
  const Three = window.THREE;
</script>

场景(Scene)、相机(Camera)和渲染器(Renderer)

Three.js 由场景、相机和渲染器的组合来生成一个视图。其中相机和渲染器的选择有多种,示例中选择了名为透视相机的类型,渲染器使用 WebGL 来实现。

场景就如字面意思,后续所有需要渲染的物体都需要填充到场景中。

相机就是一双眼睛,通过相机来观察一个场景,比如 FPS 中,相机就被安装在人物模型的头部,玩家通过鼠标和键盘来移动相机,从而实现人物的移动和视野的变换。

渲染器类似渲染引擎,Three.js 默认使用的是 WebGL 渲染器,如果浏览器不支持,也会通过其他方式降阶,具体是 svg 还是 Canvas2D 示例文档中没有说明。

另外,渲染器创建后内置了一个 canvas 元素,可以把其添加到 DOM 中显示。

比如:

const Three = window.THREE;

// 场景
const scene = new Three.Scene();

// 相机
const camera = new Three.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

// 渲染器
const renderer = new Three.WebGLRenderer();

renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

Three.PerspectiveCamera 是一个透视相机,有以下四个参数:

  • 第一个参数是 视野角度(FOV),这是在显示器上看到场景看到场景的范围,单位是角度。
  • 第二个参数是 长宽比(aspect ratio),这个比例和渲染器的大小有关,也就是给渲染器的 setSize 这个方法提供的参数,如果比例一致,正方形就是正方形,否则就是扁的或者拉长的。
  • 第三和第四个参数是 近截面(near)远截面(far)。比近截面更近或者比远截面更远的物体将不会再渲染到场景中。就类似打游戏时,太远和太近的物体不会渲染一样,太近会阻碍视线,太远则不用关心。

Three.WebGLRenderer 是 WebGL 渲染器,可以通过 Rederer.setSize 来初始化画布的宽高。渲染器内置了一个 Rederer.domElement ,这个东西就是准备好的画布。不过要想渲染场景和相机,还需要把它们组合起来。

建立一个正方体

Three.js 中建立一个正方体需要先建立一个立方体的几何(Geometry)图形,然后使用材质(Material)来对其进行着色。例如:

// geometry 几何
const geometry = new Three.BoxGeometry();

// material 材料
const material = new Three.MeshBasicMaterial({ color: 0x00ff00 });

// cube 立方体
const cube = new Three.Mesh(geometry, material);

我们创建了一个 Three.BoxGeometry,它具有一个立方体所有的顶点(vertices)和面(face)。然后创建一个纯绿色的 Three.MeshBasicMaterial 材质,接着使用 Three.Mesh 来生成这个立方体。

在场景中添加这个立方体并组合场景、相机和渲染器

scene.add(cube);

// 设置相机的位置
camera.position.z = 5;

function animate() {
  requestAnimationFrame(animate);

  // 每帧改变立方体的旋转偏移量,使其旋转起来
  cube.rotation.x += 0.01;
  cube.rotation.y += 0.01;

  // 渲染场景和相机
  renderer.render(scene, camera);
}

animate();

上面的代码并不难理解,重要的是设置相机的位置,还有使用渲染器渲染场景和相机。上面的代码运行后会显示一个打转转的立方体,我很想知道它旋转的方向,于是我进行了一些尝试。

我开始尝试访问相机的 rotation 属性和立方体的 position 属性,很庆祥都可以访问,并且都能设置 x、y、z 三轴,于是我在 x、y、z 轴上都试了试。

x、y、z 轴

测试下来,x 轴的方向是水平,y 轴的方向是垂直,z 轴的方向是透视。

  • 通过改变相机的 position.x,就类似打吃鸡时的 AD 键,用来左右移动;
  • 同理 position.z 类似打吃鸡时的 WS 键,用来前进和后退,注意这里没写错,z 轴是透视方向。
  • 最后 position.y 类似打吃鸡时跳跃和下蹲的时,视野改变的方向。

还有就是旋转,

  • 相机的 rotation.xrotation.y 对应了我们打吃鸡时,鼠标的移动,x 是左右 y 是上下,这个简单。
  • 相机的 rotation.y 会让相机沿着透视方向旋转,就是酒喝多了的那种打转转,更直接点就是拼夕夕永不中奖转盘那种旋转。

至于物体,它的 positionrotation 其实和相机是一样的,只是参考物体不是相机,而是物体本身。最简单的方式就是把物体理解成打吃鸡时的敌人,敌人也会移动鼠标,也会左右前后移动奔跑,就是那么简单。

完整代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Static Template</title>
    <script
      src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"
      integrity="sha256-qdgepj/cuK3QsiLmELb2ouRo37UbWaIhCJmRisNu0/c="
      crossorigin="anonymous"
    ></script>
  </head>
  <body>
    <script>
      const Three = window.THREE;

      // 场景
      const scene = new Three.Scene();

      // 相机
      const camera = new Three.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

      // 渲染器
      const renderer = new Three.WebGLRenderer();

      renderer.setSize(window.innerWidth, window.innerHeight);
      document.body.appendChild(renderer.domElement);

      // geometry 几何
      const geometry = new Three.BoxGeometry();

      // material 材料
      const material = new Three.MeshBasicMaterial({ color: 0x00ff00 });

      // cube 立方体
      const cube = new Three.Mesh(geometry, material);

      scene.add(cube);

      camera.position.z = 5;

      function animate() {
        requestAnimationFrame(animate);
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
        renderer.render(scene, camera);
      }

      // function animate() {
      //   requestAnimationFrame(animate);
      //   if (camera.position.x > 3) {
      //     camera.position.x = -3;
      //   } else {
      //     camera.position.x += 0.01;
      //   }
      //   renderer.render(scene, camera);
      // }

      // function animate() {
      //   requestAnimationFrame(animate);
      //   camera.rotation.z += 0.01;
      //   renderer.render(scene, camera);
      // }

      animate();

      console.log(1);
    </script>
  </body>
</html>
相关标签: 笔记 three.js