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

时间:2024-11-17 13:07:02

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

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

创建HTML框架界面

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

Learning Three.js- The JavaScript 3D Library for WebGL\chapter-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 id="WebGL-output">
</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 WebGL\chapter-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 id="WebGL-output">
</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 WebGL\chapter-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 id="WebGL-output">
</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 WebGL\chapter-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 id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</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的值。