Three-js 创建第一个3D场景

时间:2021-10-03 06:07:02

1.一个场景至少需要的三种类型组件

    相机/决定哪些东西将在屏幕上渲染
    光源/他们会对材质如何显示,以及生成阴影时材质如何使用产生影响
    物体/他们是在相机透视图里主要的渲染队形:方块、球体等

2.浏览器兼容

    Moziller Firefox:4.0版本以后开始支持;
    Google Chrome:第9版以后开始支持
    Safari:5.1版本开始支持;
    Opera:12.00版本以后开始支持。要让Opera支持WebGL,你还需要打开opera:config文件,设置WebGL,并将Enable hardare Acceleration设置为1;
    Inernet Explorer:从IE11开始支持WebGL
    如果想让旧版本IE支持WebGL,可以使用iewebgl插件,下载网址是http://iewebgl.com/

3.材质

    Three.js里有两种材质对光源产生反应:MeshLambertMaterial和MashPhongMaterial。

4.添加阴影

    添加阴影必须指定几个步骤。首先需要让渲染器支持阴影:

render.shadowMapEabled = true; // render为WebGLRenderer对象

    其次需要设置哪些物体作为阴影源,哪些物体作为接受阴影:

plane.receiveShadow = true; // plane平面接受阴影
cube.castShadow = true; // cube立方体产生阴影
sphere.castshadow = true; // sphere球体产生阴影

    最后需要置顶哪些光源可产生投影:

spotLight.castShadow = true // spotLight光源可产生阴影

5.检测动画帧频插件state.js

    Three.js作者也写了一个显示每秒帧数(FPS)的插件,可用来统计渲染。首先在页面引入state.js文件。然后创建一个检测显示的div:

<div id="State-output"></div>

    写一个初始化统计函数:

function initStats() {

            var stats = new Stats();

            stats.setMode(0); // 0: fps, 1: ms

            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';

            document.getElementById("Stats-output").appendChild(stats.domElement);

            return stats;
        }

    在创建渲染对象时,我们也初始化state:   

var state = initState();

    在执行渲染的动画函数中,每次执行时都调用下state的update函数:

function render() {
            stats.update();
            ...
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

6.使用dat.GUI库简化试验

    Google几个人创建了一个名为dat.GUI的库,使用它,你很容易就可以创建一个简单的界面组件,用以修改代码中的变量。例如我们可以实时修改球体的弹跳速度,方块的旋转速度等等。    
    就像添加其他对象一样,首先需要引入dat.gui.js,接下来需要一定一个javascript对象,保存想通过dat.GUI库修改的那些变量,也可以绑定函数而调用对象函数。如定义一个controls对象:     

var controls = new function(){             
this.rotationSpeed = 0.02;             
this.bouncingSpeed = 0.03;         
}

    定义了两个属性,以及设置了默认值。接下来把这个对象传递给dat.GUI对象,并定义两个属性的取值范围,如下所示:

(function(){
...
var gui = new dat.GUI();
gui.add(controls, 'rotationSpeed', 0, 0.5);
gui.add(controls, 'bouncingSpeed', 0, 0.5);
...
});

    现在要做的是保证在render循环里直接饮用这两个属性。这样当我们在dat.GUI界面修改时可直接影响物体的旋转速度和弹跳速度。

function render(){
...
cube.rotation.x += controls.rotationSpeed;
cube.rotation.y += controls.rotationSpeed;
cube.rotation.z += controls.rotationSpeed;
step += controls.bouncingSpeed;

sphere.position.x = 20 + (10 * (Math.cos(step)));
sphere.position.y = 2 + (10 * Math.abs(Math.sin(step)));
...
requestAnimationFrame(render);
}

    运行界面,在界面右上角可看到定义的两个属性,我们可以实时修改属性,查看界面动画效果。

Three-js 创建第一个3D场景

7.Three.Scene常用函数和属性

    scene.add(object):添加一个对象到场景对象汇总。包括Sphere、Box、Cube、Light等。
    scene.remove(object):从Scene中删除一个对象
    scene.getChildByName(name):通过名称获取Scene下的对象,名称可通过例如cube.name = 'cube-1'这种方式指定。
    scene.children():获取场景中的所有子对象列表
    scene.traverse(function(e){}):遍历scene下的子对象。我们可以通过例如e instaceof THREE.Mesh来判断类型进行过滤
    scene.fog:通过该属性设置场景的雾化效果。它可以渲染出一层雾气,隐藏远处的物体
    scene.overrideMaterial:通过这个属性,你可以强制场景中的所有物体使用同一个材质

8.雾化效果

    three.js添加雾化效果很简单,第一种方式:

//new THREE.Fog(color, near, far)
scene.fog = new THREE.Fog(0xffffff, 0.015, 100);

    包含三个参数,第一个参数color指定雾化颜色,第二个参数near指定近点位置,第三个far参数指定远点位置。第二种方式:

scene.fog = new THREE.FogExp2(0xffffff, 0.015);

    这种方式不指定near和far属性,只给颜色和浓度。浓度也就是雾化因子,雾化因子也是通过near和far算出来的。

9.动态修改物体的顶点

    three.js假设一个网格的几何体在其生命周期内不会改变。为了支持动态修改顶点坐标。我们需要在渲染的时候添加下面的代码:

mesh.children.forEach(function(e){
                e.geometry.vertices = vertices;
                e.geometry.verticesNeedUpdate = true;
                e.geometry.computeFaceNormals();
            });

    verticesNeedUpdate属性指定顶点需要重新渲染,computeFaceNormals指定Face需要重新渲染。

10.网格Mesh常用函数和属性

    position(位置)/决定该对象相对其父对象的位置。多数情况下,一个对象的父对象是THREE.Scene()对象

    rotation(旋转)/通过这个属性你可以设置对象绕任何一个轴旋转弧度

    scale(比例)/通过这个属性可以沿着x、y、z轴缩放对象

    translateX(amout)/沿x轴将对象平移指定的距离。如果是负数则沿着x轴负方向  

    translateY(amout)/沿y轴将对象平移指定的举例。如果是负数则沿着y轴负方向

    translateZ(amout)/沿z轴将对象平移指定的举例。如果是负数则沿着z轴负方向

11.正投影相机和透视投影相机

    three.js提供了两种相机:THREE.PerspectiveCamera(透视投影相机)和THREE.OrthographicCamera(正投影相机)。首先看PerspectiveCamera构造函数new THREE.PerspectiveCamera(fov, aspect, near, far)参数:

    fov/fov表示视场。这是从相机位置能够看到的部分场景。推荐默认值为45

    aspect/长宽比,这是渲染结果输出区的横向长度和纵向长度的比值。默认推荐window.innerWidth/window.innerHeight。

    near/近面,near属性定义的是three.js库从距离相机多斤的地方开始渲染场景。默认值推荐为0.1。

    far/远面,far属性定义的而是相机可以从它所处的位置看多远。默认值推荐为1000.

    正投影相机构造函数new THREE.OrthographicCamera(left, right, top, bottom, near, far)的参数:

    left/左边界;right/右边界;top/上边界;bottom/下边界;near/近边界;far远边界。

    创建了相机之后,我们需要指定聚集点的位置:

    camera.lookAt(new THREE.Vector3(x, y, z));

12.Canvas Renderer和WebGL Renderer区别

    HTML5 canvas renderer和WebGL renderer主要区别是,HTML5 canvas渲染器直接使用javascript在canvas上绘制3D场景。这种方式最主要的问题是糟糕的表现。而使用THREE.WebGLRenderer,我们可以通过硬件加速执行渲染。但THREE.CanvasRenderer对象,我们不得不完全依赖软件渲染,这导致了低性能呈现。另外一个缺点是,THREE.CanvasRenderer不能使用three.js提供的高级材质,而只有WebGL才可以使用。