3

总结以前的开发经验可以发现,再复杂的项目都是有着必不可少的骨架,所做的工作都是往骨架中去添加更多的内容。

在除去一切可以去除的内容之后,三维动画可以用一个球体来描述。
网格球.png

从零画一个球体

1、引入three.js

书中第一章用了不少篇幅写环境搭建,实际上有前端基础的同学都可以略过这部分。
如果选择webpack模块化的方法引入的话,在引用书中提到的几个辅助工具的时候会有些麻烦
(我因为这个浪费了几个小时🤯)
建议初期可以先直接使用案例代码学习

2、分析实例代码

书中提供了一些代码实例,拿最简单的01-02.js 来做分析

https://github.com/hiwords/learning-threejs-third/blob/master/src/chapter-01/js/01-02.js

实例代码中创建了四个物体:坐标轴、平面、立方体、球体
我们可以去掉不必要代码,直接分析如何创建球体

1、如何创建球体

    // 定义物体的几何结构
    var sphereGeometry = new THREE.SphereGeometry(30, 10, 10);
    // 定义物体的材质
    var sphereMaterial = new THREE.MeshBasicMaterial({
        color: 0x7777FF,
        wireframe: true
    });
    // 用刚才定义的几何结构和材质来创建物体
    var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);

    // 定位球体中心的位置
    sphere.position.set(0, 0, 0);

    // 把球体添加到场景中
    scene.add(sphere);

综上总结创建物体必须要:

  1. 定义几何结构
  2. 定义材质
  3. 根据结构和材质创建物体
  4. 确定物体在场景中的位置
  5. 把物体添加进场景中

2、如何创建三维场景

    // 创建场景,所有三维物体的内容都是放在场景中的
    var scene = new THREE.Scene();
    // 创建相机:相机决定了我们能看到什么
    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

    var renderer = new THREE.WebGLRenderer();  // 创建一个渲染器
    renderer.setClearColor(new THREE.Color(0x000000)); // 设置场景背景色
    renderer.setSize(window.innerWidth, window.innerHeight); // 设置尺寸
    
    // 定义相机的位置和能够看到的内容(scene)
    camera.position.set(30, 40, 80);
    camera.lookAt(scene.position);
    // 渲染场景和相机
    renderer.render(scene, camera)

综上总结三维场景必定包含:

场景:scene是一定要new一个的
相机:就相当于我们看三维图像世界的眼睛
渲染器:可以理解为绘制场景极其内容的

还有一句代码:

document.getElementById("webgl-output").appendChild(renderer.domElement);

复制代码重点是这个render.domElement,它应该就是three.js封装的创建一个WebGL上下文的方法,返回的是一个canvas的Element object

丰富场景和物体内容

改变材质

因为不是每一种材质(Material)都会对光源有反应,所以我们先换一个对光源会产生反应的材质。

// MeshBasicMaterial  换成  MeshLambertMaterial
new THREE.MeshLambertMaterial({color: 0x7777FF});

更改完成后会发现页面变成了一片漆黑,这时候实际上是有渲染球体的,只是当前是黑色和背景色区分不开

为什么球体材质颜色明明是0x7777FF,但是却显示的漆黑的呢?
因为场景中没有光源,所以就相当于整个场景处于伸手不见五指的夜晚……黑漆漆

添加光源

“这个世界要有光!”
光源也可以理解为和球体同样级别的一个物体,所以添加光源要有这三步:

  1. 定义光源的属性
  2. 设置光源的位置
  3. 把光源添加到场景里
    var spotLight = new THREE.SpotLight(0xFFFFFF)
    spotLight.position.set(60, 70, 20);
    scene.add(spotLight)

guangqiu.png

这样球体就可以被我们给看到了
但是整个场景还是有些暗
还有个环境光:AmbientLight,环境光的添加非常的简单

var ambienLight = new THREE.AmbientLight(0x555555); scene.add(ambienLight);

liang_guang_qiu.png

有了光就应该有影子

在我们的世界光和阴影总是会同时存在。可以这样理解:球被光照射,产生影子,投射在了地面上
我们要设置:

  1. 球可以产生影子:sphere.castShadow = true
  2. 地面可以承载影子: 类似创建球体一样创建一个平面plane
    设置承载影子的属性plane.receiveShadow = true;
  3. 光源要是能产生影子的光源: spotLight.castShadow = true
  4. 渲染器要允许渲染影子:render.shadowMap.enabled = true, 因为渲染阴影会耗费大量的计算资源,所以Three.js 默认是不会渲染阴影的,需要主动设置

注意:three.js开发指南第三版中 说到renderer.shadowMap.Enabled = true; 这里是会导致阴影无法出现的。正确的应该是 renderer.shadowMap.enabled = true

shadow.png

动起来

简单的动画无非就是requestAnimationFrame(渲染函数render)

var step = 0.1;
    var n = 0
    function render() {
        n += step
        sphere.position.set(0, -40, n)
        console.log(n)
        requestAnimationFrame(render)
        renderer.render(scene, camera);
    }
最最简单的就是这样平移改变球体位置的一个动画,更丰富的动画放在后面在了解吧,继续学习下一章的内容去了~

总结

  1. 不管是几何体还是摄像机还是光源,都是可以理解为一个物体。在创建的时候首先设定其属性,然后选择(设置)在场景中的位置xx.position.set(x,y,z)。最后添加进场景中scene.add(xx),一定要记得add进来,不然就不会显示
  2. 对光源能够产生反应的材质,场景中一定要加光源,如果没有光源,这种材质的几何都会呈现黑色
  3. 设置阴影需要:

    • 让渲染器允许渲染阴影效果:renderer.shadowMap.enabled = true;
    • 光源要是能够产生影子的spotLight.castShadow = true;
    • 要有产生阴影和接收阴影的物体:xx.castShadow = true/xx.receiveShadow = true
  4. 生成一个简单的三维世界必须要创建的:创建场景、创建渲染器、创建几何体、创建相机

友情提示:three.js里面坐标系是右手定则的,可以理解为:拇指为Z,手掌为Y,四指为X

            Y
            ↑       
            。----→  X
          ↙
        Z
        
        上面这个就是坐标系

前端工程队
80 声望3 粉丝