第一章 用three.js创建你的第一个3D场景 第一章 用three.js创建你的第一个3D场景

到官网下载three.js的源码和示例。

创建HTML框架界面

第一个示例的代码如下: 01-basic-skeleton.html 位于

Learning Three.js- The JavaScript 3D Library for WebGLchapter-01

<!DOCTYPE html>
<html>
<head>
<title>Example 01.01 - Basic skeleton</title>
<script type="text/javascript" 
	src="../libs/three.js"></script>
<script type="text/javascript"
	src="../libs/jquery-1.9.0.js"></script>
<style>
body{
	/* set margin to 0 and overflow to hidden,
	to use the complete page */
	margin: 0;
	overflow: hidden;
}
</style>
</head>
<body>
<!-- Div which will hold the Output -->
<div >
</div>
<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
// once everything is loaded, we run our Three.js stuff.
$(function () {
// here we'll put the Three.js stuff
});
</script>
</body>
</html>

Three.js 有两个版本:

• Three.min.js:压缩版本,去掉了空格和换行,大小变小了,加载时占用系统资源小。

• Three.js:未压缩版本,易于阅读和调试,但加载时占用系统资源较大。

渲染和展示一个三维物体

我们接下来将会创建我们的第一个场景并添加一系列的物体。其中包括:

Plane :有两个面的矩形,作为我们场景的地面,将会在场景中部渲染成一个灰色的矩形。

Cube :正方体,我们将渲染成红色。

Sphere :球体,我们将渲染成蓝色。

Camera :相机决定了看到了什么。

Axes :坐标轴,x,y,z轴。一个很好的调试工具,能够让你知道物体渲染在哪里。

第二个示例的代码如下 02-first-scene.html 位于

Learning Three.js- The JavaScript 3D Library for WebGLchapter-01

<!DOCTYPE html>

<html>

<head>
<title>Example 01.02 - First Scene</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
<style>
    body{
        /* set margin to 0 and overflow to hidden, to go fullscreen */
        margin: 0;
        overflow: hidden;
    }
</style>
</head>
<body>

<!-- Div which will hold the Output -->
<div >
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

// once everything is loaded, we run our Three.js stuff.
$(function () {

    // create a scene, that will hold all our elements such as objects, cameras and lights.
    var scene = new THREE.Scene();

    // create a camera, which defines where we're looking at.
    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

    // create a render and set the size
    var renderer = new THREE.WebGLRenderer();

    renderer.setClearColorHex(0xEEEEEE);
    renderer.setSize(window.innerWidth, window.innerHeight);

    var axes = new THREE.AxisHelper( 20 );
    scene.add(axes);

    // create the ground plane
    var planeGeometry = new THREE.PlaneGeometry(60,20);
    var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc});
    var plane = new THREE.Mesh(planeGeometry,planeMaterial);


    // rotate and position the plane
    plane.rotation.x=-0.5*Math.PI;
    plane.position.x=15
    plane.position.y=0
    plane.position.z=0

    // add the plane to the scene
    scene.add(plane);

    // create a cube
    var cubeGeometry = new THREE.CubeGeometry(4,4,4);
    var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
    var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);


    // position the cube
    cube.position.x=-4;
    cube.position.y=3;
    cube.position.z=0;

    // add the cube to the scene
    scene.add(cube);

    var sphereGeometry = new THREE.SphereGeometry(4,20,20);
    var sphereMaterial = new THREE.MeshBasicMaterial({color: 0x7777ff, wireframe: true});
    var sphere = new THREE.Mesh(sphereGeometry,sphereMaterialMaterial);

    // position the sphere
    sphere.position.x=20;
    sphere.position.y=4;
    sphere.position.z=2;


    // add the sphere to the scene
    scene.add(sphere);

    // position and point the camera to the center of the scene
    camera.position.x = -30;
    camera.position.y = 40;
    camera.position.z = 30;
    camera.lookAt(scene.position);

    // add the output of the renderer to the html element
    $("#WebGL-output").append(renderer.domElement);

    // render the scene
    renderer.render(scene, camera);
});

</script>
</body>
</html>

可知有如下几个步骤:

  1. 创建并设置scene、render、camera。

  2. 创建对象,指定Geometry和Material,设置position并加入到scene中

  3. 把渲染的结果显示在 $('div#WebGL-output')对象中。

  4. 开始渲染。

加上材质、灯光和阴影

第三个示例的代码如下: 03-materials-light.html 位于

Learning Three.js- The JavaScript 3D Library for WebGLchapter-01

<!DOCTYPE html>

<html>

<head>
<title>Example 01.03 - Materials and light</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
    body{
        /* set margin to 0 and overflow to hidden, to go fullscreen */
        margin: 0;
        overflow: hidden;
    }
</style>
</head>
<body>

<!-- Div which will hold the Output -->
<div >
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

// once everything is loaded, we run our Three.js stuff.
$(function () {

    // create a scene, that will hold all our elements such as objects, cameras and lights.
    var scene = new THREE.Scene();

    // create a camera, which defines where we're looking at.
    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

    // create a render and set the size
    var renderer = new THREE.WebGLRenderer();

    renderer.setClearColorHex(0xEEEEEE, 1.0);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMapEnabled = true;

    // create the ground plane
    var planeGeometry = new THREE.PlaneGeometry(60,20);
    var planeMaterial =    new THREE.MeshLambertMaterial({color: 0xffffff});
    var plane = new THREE.Mesh(planeGeometry,planeMaterial);
    plane.receiveShadow  = true;

    // rotate and position the plane
    plane.rotation.x=-0.5*Math.PI;
    plane.position.x=15
    plane.position.y=0
    plane.position.z=0

    // add the plane to the scene
    scene.add(plane);

    // create a cube
    var cubeGeometry = new THREE.CubeGeometry(4,4,4);
    var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
    var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    cube.castShadow = true;

    // position the cube
    cube.position.x=-4;
    cube.position.y=3;
    cube.position.z=0;

    // add the cube to the scene
    scene.add(cube);

    var sphereGeometry = new THREE.SphereGeometry(4,20,20);
    var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
    var sphere = new THREE.Mesh(sphereGeometry,sphereMaterial);

    // position the sphere
    sphere.position.x=20;
    sphere.position.y=4;
    sphere.position.z=2;
    sphere.castShadow=true;

    // add the sphere to the scene
    scene.add(sphere);

    // position and point the camera to the center of the scene
    camera.position.x = -30;
    camera.position.y = 40;
    camera.position.z = 30;
    camera.lookAt(scene.position);

    // add spotlight for the shadows
    var spotLight = new THREE.SpotLight( 0xffffff );
    spotLight.position.set( -40, 60, -10 );
    spotLight.castShadow = true;
    scene.add( spotLight );

    // add the output of the renderer to the html element
    $("#WebGL-output").append(renderer.domElement);

    // call the render function
    renderer.render(scene, camera);
});

</script>
</body>
</html>

分析示例二和示例一可以发现不同之处。

首先,示例二添加的灯光 ,类型是点光源,并且打开了阴影效果。

 // add spotlight for the shadows
    var spotLight = new THREE.SpotLight( 0xffffff );
    spotLight.position.set( -40, 60, -10 );
    spotLight.castShadow = true;
    scene.add( spotLight );

然后,示例一采用的是BasicMaterial材质(效果为三角网格),而示例二采用的是LambertMaterial
材质(效果为一般的纸质效果)。

用动画拓展你的第一个场景

示例四的源码如下: 04-materials-light-animation.html 位于

Learning Three.js- The JavaScript 3D Library for WebGLchapter-01

<!DOCTYPE html>

<html>

<head>
<title>Example 01.04 - Materials, light and animation</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<style>
    body{
        /* set margin to 0 and overflow to hidden, to go fullscreen */
        margin: 0;
        overflow: hidden;
    }
</style>
</head>
<body>

<div >
</div>
<!-- Div which will hold the Output -->
<div >
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

// once everything is loaded, we run our Three.js stuff.
$(function () {

    var stats = initStats();

    // create a scene, that will hold all our elements such as objects, cameras and lights.
    var scene = new THREE.Scene();

    // create a camera, which defines where we're looking at.
    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

    // create a render and set the size
    var renderer = new THREE.WebGLRenderer();

    renderer.setClearColorHex(0xEEEEEE, 1.0);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMapEnabled = true;

    // create the ground plane
    var planeGeometry = new THREE.PlaneGeometry(60,20,1,1);
    var planeMaterial =    new THREE.MeshLambertMaterial({color: 0xffffff});
    var plane = new THREE.Mesh(planeGeometry,planeMaterial);
    plane.receiveShadow  = true;

    // rotate and position the plane
    plane.rotation.x=-0.5*Math.PI;
    plane.position.x=15
    plane.position.y=0
    plane.position.z=0

    // add the plane to the scene
    scene.add(plane);

    // create a cube
    var cubeGeometry = new THREE.CubeGeometry(4,4,4);
    var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
    var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
    cube.castShadow = true;

    // position the cube
    cube.position.x=-4;
    cube.position.y=3;
    cube.position.z=0;

    // add the cube to the scene
    scene.add(cube);

    var sphereGeometry = new THREE.SphereGeometry(4,20,20);
    var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
    var sphere = new THREE.Mesh(sphereGeometry,sphereMaterial);

    // position the sphere
    sphere.position.x=20;
    sphere.position.y=0;
    sphere.position.z=2;
    sphere.castShadow=true;

    // add the sphere to the scene
    scene.add(sphere);

    // position and point the camera to the center of the scene
    camera.position.x = -30;
    camera.position.y = 40;
    camera.position.z = 30;
    camera.lookAt(scene.position);

    // add subtle ambient lighting
    var ambientLight = new THREE.AmbientLight(0x0c0c0c);
    scene.add(ambientLight);

    // add spotlight for the shadows
    var spotLight = new THREE.SpotLight( 0xffffff );
    spotLight.position.set( -40, 60, -10 );
    spotLight.castShadow = true;
    scene.add( spotLight );

    // add the output of the renderer to the html element
    $("#WebGL-output").append(renderer.domElement);

    // call the render function
    var step=0;
    render();

    function render() {
        stats.update();
        // rotate the cube around its axes
        cube.rotation.x += 0.02;
        cube.rotation.y += 0.02;
        cube.rotation.z += 0.02;

        // bounce the sphere up and down
        step+=0.04;
        sphere.position.x = 20+( 10*(Math.cos(step)));
        sphere.position.y = 2 +( 10*Math.abs(Math.sin(step)));

        // render using requestAnimationFrame
        requestAnimationFrame(render);
        renderer.render(scene, camera);
    }

    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';

        $("#Stats-output").append( stats.domElement );

        return stats;
    }
});

</script>
</body>
</html>

分析源码可知与示例三的不同有:

 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';

        $("#Stats-output").append( stats.domElement );

        return stats;
    }

这里这个函数创建了一个Stats,也就是左上角的显示帧数的方框。方法就是创建一个Stats,并设置
参数,然后将结果显示在$('#Stats-output')中。

然后看这段代码:

	var step=0;
    render();

    function render() {
        stats.update();
        // rotate the cube around its axes
        cube.rotation.x += 0.02;
        cube.rotation.y += 0.02;
        cube.rotation.z += 0.02;

        // bounce the sphere up and down
        step+=0.04;
        sphere.position.x = 20+( 10*(Math.cos(step)));
        sphere.position.y = 2 +( 10*Math.abs(Math.sin(step)));

        // render using requestAnimationFrame
        requestAnimationFrame(render);
        renderer.render(scene, camera);
    }

这里更改了cube和sphere的角度和位置,然后调用requestAnimationFrame函数,该函数就是调用传入的参数render,然后就进入渲染循环,就产生了动画。

运用 dat.GUI库使得实验更简易

创建一个GUI 接受rotationSpeed和bouncingSpeed,值在0~0.5之间。

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

创建一个javascript对象用来包含rotationSpeed和bouncingSpeed。

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

然后改变的角度和位置可以采用controls的值。