1、什么是three.js

  • Three.js是基于webGL的封装的一个易于使用且轻量级的3D库,Three.js对WebGL提供的接口进行了非常好的封装,简化了很多细节,大大降低了学习成本,极大地提高了性能,功能也非常强大,用户不需要详细地学习 WebGL,就能轻松创作出三维图形,是前端开发者研发3D绘图的主要工具。

2、three.js三大要素

  • 场景(scene):场景是一个三维空间,是存放所有物品的容器,可以把场景想象成一个空房间,房间里面可以放置要呈现的物体、相机、光源等。
var scene = new THREE.Scene(); // 创建场景
  • 相机(camera):在场景中需要添加一个相机,相机用来确定观察位置、方向、角度,相机看到的内容,就是我们最终在屏幕上看到的内容。在程序运行过程中,可以调整相机的位置、方向、角度。
  • 在Three.js中有两种常用的相机:透视投影相机(perspectiveCamera)和正交投影相机(OrthographicCamera )
  • 透视投影相机(perspectiveCamera):透视相机的效果是模拟人眼看到的效果,跟人眼看到的世界是一样的,近大远小。
var camera = new THREE.PerspectiveCamera(
  75,	//视野:表示摄像机能看到的视野。推荐默认值50
  window.innerWidth / window.innerHeight,	//指定渲染结果水平方向和竖直方向长度的比值,推荐默认值为窗口的宽高比
  0.1,	//近端渲染距离:指定从距离摄像机多近的位置开始渲染,推荐默认值0.1
  1000	//远端距离:指定摄像机从它所在的位置最远能看到多远,太小场景中的远处不会被渲染,太大会浪费资源影响性能,推荐默认值1000。
);// 创建透视投影相机

// 设置相机位置
camera.position.x = 5;
camera.position.y = 10;
camera.position.z = 10;
// 以上设置相机位置可以简写为:
camera.position.set(5, 10, 10);

  • 正交投影相机(OrthographicCamera ):正交投影则远近都是一样的大小,三维空间中平行的线,投影到二维空间也一定是平行的。
var camera = new THREE.OrthographicCamera(-2, 2, 1, -1, 1, 10); // 创建正交投影相机

// 设置相机位置
camera.position.x = 5;
camera.position.y = 10;
camera.position.z = 10;
// 以上设置相机位置可以简写为:
camera.position.set(5, 10, 10);
  • 渲染器(renderer):渲染器的作用就是将相机拍摄出的画面在浏览器中呈现出来。渲染器决定了渲染的结果应该画在页面的什么元素上面,并且以怎样的方式来绘制。
var renderer = new THREE.WebGLRenderer(); // 创建一个 WebGL 渲染器
renderer.setSize(window.innerWidth, window.innerHeight); // 通过调用 setSize() 方法设置渲染的长宽(设置渲染器为全屏)
document.body.appendChild(renderer.domElement); // 将渲染结果展示到页面上
renderer.render(scene, camera); // 结合场景和相机进行渲染,即用摄像机拍下此刻的场景(最后一步)

3、three.js创建物体的设计模式

  • 在计算机世界里,3D世界是由点组成,两个点能够组成一条直线,三个不在一条直线上的点就能够组成一个三角形面,在 Three.js中 将任何物体(拍摄对象)结构为一个个小三角形。
  • 在 Three.js 中三角形是最小分割单位,这就是网格结构模型,我们通常把这种网格模型叫做Mesh模型,Mesh模型是三维开发中使用的最为广泛的模型。

4、几何体模型

平面几何体模型

  • PlaneGeometry(平面几何体)
  • CircleGeometry(圆形几何体)
  • RingGeometry(圆环几何体)

三维几何体模型

  • BoxGeometry(立方几何体)
  • SphereGeometry(球几何体)
  • CylinderGeometry(圆柱几何体)
  • TorusGeometry(圆环几何体)
  • TubeGeometry(管道几何体)

几何体实例化

var geometry = new THREE.BoxGeometry(1, 1, 1); // 创建一个长、宽、高均为1个单位的立方体	

5、材质

  • 基础网格材质(MeshBasicMaterial)【常用】:一个以简单着色(平面或线框)方式来绘制几何体的材质,这种材质不受光照的影响。
  • Lambert网格材质(MeshLambertMaterial)【常用】:一种非光泽表面的材质,没有镜面高光。这种材质可以很好地模拟一些表面(例如未经处理的木材或石材),但不能模拟具有镜面高光的光泽表面(例如涂漆木材)。
  • 法线网格材质(MeshNormalMaterial)【拓展:不常用】:一种RGB颜色的材质

特殊说明:在同一个网格结构中我们可以多种材质进行叠加。

var materialBasic = new THREE.MeshBasicMaterial({
    color: 0xffffff, // 白色
    wireframe: true // //是否将几何体渲染为线框,默认值为false(即渲染为平面多边形)
}); // 创建基础网格材质
var materialNormal = new THREE.MeshNormalMaterial(); // 创建法线网格材质

6、网格

  • 网格(Mesh):当我们拥有了几何体模型和材质之后,我们需要通过一个网格(Mesh)将两者结合起来,创建我们正在的拍摄对象。
// 两种不同的拍摄对象构造方法
// 第一个参数代表物体的形状,第二个参数代表物体的材质。
// 创建一种网格,将材质包裹在几何体模型上,这个方法只能用一种材质
var cube = new THREE.Mesh(geometry, material); 

// 创建多种网格,将材质包裹在几何体模型上,这个方法可以用多种材质
var cube = THREE.SceneUtils.createMultiMaterialObject(geometry, [
    materialBasic,
    materialNormal
]);

// 让相机 看向(对着)物体(拍摄对象)的位置(默认状态下,相机将指向三维坐标系的原点。)
camera.lookAt(cube.position);

7、光源

  • 环境光(AmbientLight):环境光是一种基本光源,它会均匀的照亮场景中的所有物体,环境光没有特定的来源方向,且不会产生阴影。
  • 聚光灯(SpotLight):聚光灯(类似手电筒、舞台聚光灯)是从一个方向上的一个点发出,沿着一个圆锥体,它离光越远,它的尺寸就越大。这种光源会产生阴影。
  • 平行光(DirectionalLight):平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光 的效果; 太阳足够远,因此我们可以认为太阳的位置是无限远,所以我们认为从太阳发出的光线也都是平行的。这种光源会产生阴影。
// 创建光源
var spotLight = new THREE.SpotLight(0xffffff);
// 设置光源在三维空间的位置
spotLight.position.set(0, 20, 20);
// 设置光源照射的强度,默认值为 1
spotLight.intensity = 5;
// 将光源添加到场景中
scene.add(spotLight);

8、使用Three.js,在屏幕上展示 3D 图形的大概步骤:

  • 创建一个三维空间场景( Scene );
  • 创建一个相机( Camera ),确定一个观察点,并设置相机的观察方向和角度;
  • 创建渲染器,设置渲染器的长宽,将渲染结果展示到页面上;
  • 创建物体(几何体、材质、网格)、光源(同时设置光源位置),并添加到场景中去;
  • 最后通过渲染器,把场景、相机渲染到页面上。

9、一个基础案例

<html>

<head>
    <title>Cube</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }

        canvas {
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <!-- 引入three.js -->
    <script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
    <script>
        // 1、创建场景
        var scene = new THREE.Scene();

        // 2、创建相机(透视投影相机)
        var camera = new THREE.PerspectiveCamera(
            50, // 相机视野
            window.innerWidth / window.innerHeight, // 水平方向和竖直方向长度的比值
            0.1, // 近端渲染距离
            1000 // 远端渲染距离
        );
        // 2.1 设置相机位置
        // camera.position.x = 5;
        // camera.position.y = 10;
        // camera.position.z = 10;
        // 2.1 设置相机位置简写方式:
        camera.position.set(5, 10, 10);

        // 3、创建渲染器
        var renderer = new THREE.WebGLRenderer();
        // 3.1 设置渲染器的大小(长宽)(设置渲染器为全屏)
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 3.2 将渲染结果展示到页面上
        document.body.appendChild(renderer.domElement);
      
        // 4、创建几何体模型(立方几何体)
        var geometry = new THREE.BoxGeometry(4, 4, 4);

        // 5、创建材质(基础网格材质和法线网格材质)
        // 5.1 创建基础网格材质
        var materialBasic = new THREE.MeshBasicMaterial({
            color: 0xffffff, // 白色
            // color: 0x00ff00, // 绿色
            wireframe: true //是否将几何体渲染为线框,默认值为false(即渲染为平面多边形)
        });
        // 5.2 创建法线网格材质
        var materialNormal = new THREE.MeshNormalMaterial();

        // 6、创建多种网格(因为有多个材质)
        // 第一个参数是几何模型,第二参数是材质
        var cube = THREE.SceneUtils.createMultiMaterialObject(geometry, [
            materialBasic,
            materialNormal
        ]);
      
      	// 6.1、将网格添加到场景中
        scene.add(cube);
        // 6.2 让相机 看向(对着)物体(拍摄对象)的位置(默认状态下,相机将指向三维坐标系的原点。)
        camera.lookAt(cube.position);
        
        // 7、创建光源
        var spotLight = new THREE.SpotLight(0xffffff);
        // 7.1 设置光源位置
        spotLight.position.set(0, 20, 20);
        // 7.2 设置光源照射的强度,默认值为 1
        spotLight.intensity = 5;
        // 7.3 将光源添加到场景中
        scene.add(spotLight);
      
        // 8、为了方便观察3D图像,添加三维坐标系对象
        var axes = new THREE.AxisHelper(6);
        scene.add(axes);
      
        // 9、 结合场景和相机进行渲染,即用摄像机拍下此刻的场景
        renderer.render(scene, camera);
    </script>
</body>

</html>

10、three.js中的动画

  • 动画原理:动画实际上是由一些列的图片在一定时间内,以一定的频率播放而产生的错觉。为了让动画以连贯、平滑的方式进行过渡,一般我们以 60 帧/秒,甚至更高的速率渲染动画。
  • 创建动画:在Three.js中使用 requestAnimationFrame()方法来创建动画。因为动画需要以一定的频率播放,所以需要创建一个循环渲染的函数,并且最后要调用这个函数。
function animate() {
  	//循环调用函数
    requestAnimationFrame(animate);
  	// 每一次animate函数调用,都让网格比上一次 X 轴、Y 轴各旋转增加 0.01 弧度
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    // 渲染器结合场景和相机进行渲染
    renderer.render(scene, camera);
};

animate();
  • 动画完整效果如下
<html>

<head>
    <title>Cube</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }

        canvas {
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
  	<!-- 引入three.js -->
    <script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>
    <script>
        // 1、创建场景
        var scene = new THREE.Scene();

        // 2、创建相机(透视投影相机)
        var camera = new THREE.PerspectiveCamera(
            50, // 相机视野
            window.innerWidth / window.innerHeight, // 水平方向和竖直方向长度的比值
            0.1, // 近端渲染距离
            1000 // 远端渲染距离
        );
        // 2.1 设置相机位置
        // camera.position.x = 5;
        // camera.position.y = 10;
        // camera.position.z = 10;
        // 2.1 设置相机位置简写方式:
        camera.position.set(5, 10, 10);

        // 3、创建渲染器
        var renderer = new THREE.WebGLRenderer();
        // 3.1 设置渲染器的大小(长宽)(设置渲染器为全屏)
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 3.2 将渲染结果展示到页面上
        document.body.appendChild(renderer.domElement);
      
        // 4、创建几何体模型(立方几何体)
        var geometry = new THREE.BoxGeometry(4, 4, 4);

        // 5、创建材质(基础网格材质和法线网格材质)
        // 5.1 创建基础网格材质
        var materialBasic = new THREE.MeshBasicMaterial({
            color: 0xffffff, // 白色
            wireframe: true //是否将几何体渲染为线框,默认值为false(即渲染为平面多边形)
        });
        // 5.2 创建法线网格材质
        var materialNormal = new THREE.MeshNormalMaterial();

        // 6、创建多种网格(因为有多个材质)
        // 第一个参数是几何模型,第二参数是材质
        var cube = new THREE.Mesh(geometry, materialNormal);
        // 6.1 让相机 看向(对着)物体(拍摄对象)的位置(默认状态下,相机将指向三维坐标系的原点。)
        camera.lookAt(cube.position);
        // 6.2、将网格添加到场景中
        scene.add(cube);
        // 7、创建光源
        var spotLight = new THREE.SpotLight(0xffffff);
        // 7.1 设置光源位置
        spotLight.position.set(0, 20, 20);
        // 7.2 设置光源照射的强度,默认值为 1
        spotLight.intensity = 5;
        // 7.3 将光源添加到场景中
        scene.add(spotLight);
        // 8、为了方便观察3D图像,添加三维坐标系对象
        var axes = new THREE.AxisHelper(6);
        scene.add(axes);
        // 9、创建动画循环渲染函数
        function animate() {
            // 9.1 循环调用函数
            requestAnimationFrame(animate);
            // 每一次animate函数调用,都让网格比上一次 X 轴、Y 轴各旋转增加 0.01 弧度
            cube.rotation.x += 0.01;
            cube.rotation.y += 0.01;
            // 3.3 结合场景和相机进行渲染,即用摄像机拍下此刻的场景
            renderer.render(scene, camera);
        };
        // 调用动画函数
        animate();
    </script>
</body>

</html>

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐