2、Three.js初步认识场景Scene、相机Camera、渲染器Renderer三要素

发布于:2024-11-29 ⋅ 阅读:(12) ⋅ 点赞:(0)

三要素之间关系:

有了虚拟场景Scene,相机录像Camera,在相机小屏幕上看到的Renderer

Scene当前空间 Mesh人在场景 Camera相机录像 Renderer显示器上
在这里插入图片描述
首先先描述下Scene:
这个场景为三要素之一,一切需要展示的东西都需要添加到Scene里面,也就是画布,你需要在页面展示的东西都需要add到Scene中,
在场景里面我们可以添加 Mesh网格模型、光源等

Mesh网格模型组成需要两部分 需要几何体Geometry和对应的材质模型Material

1、如何创建Scene、camera 、renderer 三要素并渲染:

<!DOCTYPE html>
<html>

<head>
    <title>three.js</title>
    <meta charset="utf-8">
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <!-- 类似于创建 并设置别名 -->
    <script type="importmap">
            {
              "imports": {
                "three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
                "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
              }
            }
          </script>
    <!-- 导入包名 -->
    <script type="module">
        import * as THREE from 'three';
        // 创建一个新的场景对象
        const scene = new THREE.Scene();

        // 创建一个透视相机,参数分别为视野角度、宽高比、近平面和远平面
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

        // 创建一个WebGL渲染器
        const renderer = new THREE.WebGLRenderer();
        // 设置渲染器的大小,使其充满整个窗口
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 将渲染器的DOM元素添加到文档的body中
        document.body.appendChild(renderer.domElement);
    </script>
</body>

</html>

现在建立了场景、相机和渲染器;但是页面还是不能正常渲染的~

Threejs提供了正投影相机OrthographicCamera (opens new window)和透视投影相机PerspectiveCamera

OrthographicCamera:适用于:CAD 图纸、工程图、UI 设计、2D 游戏等场景,这些场景通常需要保持物体的比例和形状。
PerspectiveCamera:适用于:3D 游戏、虚拟现实、建筑设计等场景,这些场景通常需要模拟真实世界的视觉效果。

透视投影相机PerspectiveCamera

透视投影相机的四个参数fov, aspect, near, far构成一个四棱台3D空间,被称为视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示在Canvas画布上。

PerspectiveCamera( fov, aspect, near, far )

第一个参数是视野角度(FOV)。视野角度就是无论在什么时候,你所能在显示器上看到的场景的范围,它的单位是角度(与弧度区分开)。默认值:50

第二个参数是长宽比(aspect ratio)。 也就是你用一个物体的宽除以它的高的值。比如说,当你在一个宽屏电视上播放老电影时,可以看到图像仿佛是被压扁的。默认值:1

最后两个参数是近截面(near)和远截面(far)。 当物体某些部分比摄像机的远截面远或者比近截面近的时候,该这些部分将不会被渲染到场景中。或许现在你不用担心这个值的影响,但未来为了获得更好的渲染性能,你将可以在你的应用程序里去设置它。near默认值:0.1;far默认值:2000

在这里插入图片描述

创建正方体到场景中

	  // 创建一个网格模型
      const geometry = new THREE.BoxGeometry(1, 1, 1);    // 创建一个立方体几何体
      const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });      // 创建一个材质对象
      const mesh = new THREE.Mesh(geometry, material);        // 创建一个网格模型对象
      scene.add(mesh);            // 将网格模型对象添加到场景中

这个时候Scene里面已经有了一个Mesh网格模型,也就是一个人进入到了想要拍摄的场景之中。默认在原点坐标
我们也可以设置这个人站在哪里:

 // 创建一个网格模型
    const geometry = new THREE.BoxGeometry(1, 1, 1);    // 创建一个立方体几何体
    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });      // 创建一个材质对象
    const mesh = new THREE.Mesh(geometry, material);        // 创建一个网格模型对象
    mesh.position.set(1,1,1,)       // 设置网格模型对象的位置
    scene.add(mesh);            // 将网格模型对象添加到场景中

这个时候 我们 场景Scene准备好了,场景里面要拍摄的人Mesh也准备好了,相机camera也准备好了,这个时候我们需要相机放到一个可以拍摄到咱们物体的一个位置position,然后让相机看向哪里呢?

相机对象Camera具有位置属性.position,通过位置属性.position可以设置相机的位置。

   // 创建一个透视相机,参数分别为视野角度、宽高比、近平面和远平面
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    //相机在Three.js三维坐标系中的位置
    // 根据需要设置相机位置具体值
    camera.position.set(5, 5, 5); 

相机已经放到了xyz都为5的位置,默认看向xyz都为000的位置,现在我们想让它看向人也就是网格模型的位置

     // 创建一个透视相机,参数分别为视野角度、宽高比、近平面和远平面
     const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
     //相机在Three.js三维坐标系中的位置
     // 根据需要设置相机位置具体值
     camera.position.set(5, 5, 5);   
     // 设置相机方向(指向的场景对象)                            
     camera.lookAt(mesh.position); 

这个时候 页面还是不展示嘻嘻 不慌~
渲染场景
这是因为我们还没有对它进行真正的渲染。为此,我们需要使用一个被叫做“渲染循环”(render loop)或者“动画循环”(animate loop)的东西。

      /**
       * 动画函数
       * 该函数通过不断地请求下一帧来实现动画效果
       * 它在每一帧中调用渲染器来重新渲染场景和相机
       */
      function animate() {
          // 请求下一帧动画
          requestAnimationFrame(animate);
          // 使用当前场景和相机进行渲染
          renderer.render(scene, camera);
      }

      // 调用animate函数开始动画
      animate();

这下就相当于一直在录像了~
看下页面:
在这里插入图片描述
我们添加一个坐标系,这样就可以更好的看出所在的位置:
辅助观察坐标系同样的添加到场景中

     // 创建辅助观察坐标系
     const asesHelper = new THREE.AxesHelper(200);
     scene.add(asesHelper);

three.js坐标轴颜色红R、绿G、蓝B分别对应坐标系的x、y、z轴,对于three.js的3D坐标系默认y轴朝上
在这里插入图片描述
我们可以让Z轴朝上

        // 默认是 0 1 0
        camera.up.x = 0;
        camera.up.y = 0;
        camera.up.z = 1; 

在这里插入图片描述

这个时候我们想让他跟随鼠标移动,可拖动旋转我们使用

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 	const controls = new OrbitControls(camera, renderer.domElement)   
    function animate() {
       controls.update();
       // 请求下一帧动画
       requestAnimationFrame(animate);
       // 使用当前场景和相机进行渲染
       renderer.render(scene, camera);
   }

这时候我们就可以随意的拖动

我们可以设置这个人Mesh网格模型翻跟头,比如我们让他跟随z轴渲染,只需要在循环动画中增加旋转即可

     function animate() {
         // 跟随Z轴旋转
         mesh.rotation.z += 0.01;
         controls.update();
         // 请求下一帧动画
         requestAnimationFrame(animate);
         // 使用当前场景和相机进行渲染
         renderer.render(scene, camera);
     }

好了,到目前位置,做了哪些?

  1. 创建场景
  2. 在场景中增加Mesh模型,模型由几何体和它对应的材质组成,设置了它的定位位置
  3. 增加camera相机录像,它的四个参数的含义,位置position,看向何方lookAt
  4. 渲染器renderer
  5. 增加辅助坐标系,默认Y朝上
  6. 增加控制器
  7. 增加动画围绕z轴旋转