本文会从实战到源码进行一些简单例子的讲解,让你理论实战通通掌握。

搭建场景

        先写一个载体文件,用于承载整个资源的html。

        我们需要以下对象:scene, camera和renderer,这样我们就可以通过camera渲染场景。

        直接写出:

<!DOCTYPE html>
<html>
	<head>
		<meta charset=utf-8>
		<title>创建一个简单的ThreeJS场景</title>
		<style>
			body { margin: 0; }
			#mainCanvas { width: 100%; height: 100% }
		</style>
	</head>
	<body>
        <div id="mainCanvas"></div>
		<script src="js/three.js"></script>
		<script>
			var scene = new THREE.Scene();
            var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );

            var renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.querySelector('#mainCanvas').appendChild( renderer.domElement );
		</script>
	</body>
</html>

现在我们已经设置好了场景、相机和渲染器。我们使用PerspectiveCamera作为镜头的摄像机。

分几部走:

看看PerspectiveCamera的API

function PerspectiveCamera( fov, aspect, near, far ) {

		Camera.call( this );

		this.type = 'PerspectiveCamera';

		this.fov = fov !== undefined ? fov : 50;
		this.zoom = 1;

		this.near = near !== undefined ? near : 0.1;
		this.far = far !== undefined ? far : 2000;
		this.focus = 10;

		this.aspect = aspect !== undefined ? aspect : 1;
		this.view = null;

		this.filmGauge = 35;	// width of the film (default in millimeters)
		this.filmOffset = 0;	// horizontal film offset (same unit as gauge)

		this.updateProjectionMatrix();

}

第一个参数是视场(FOV)。视角是你在任何时候都能在监视器上看到的场景范围,以角度(不包括弧度)来测量。

第二个参数是纵横比。也就是说,你用一个物体的宽度除以它的高度。例如,当你在宽屏电视上播放一部老电影时,图像看起来会被压缩。

接下来的两个参数是near和far。当一个物体的部分比相机的远或近部分更远或更近时,它们将不会被渲染到场景中。现在您可能不需要担心这个值,但是将来您将能够在应用程序中设置它以获得更好的呈现性能。

渲染器

WebGLRenderer是关键。除了我们在这里使用的WebGLRenderer, three.js还提供了几个其他的渲染器,当用户使用的浏览器太旧或出于其他原因不支持WebGL时,可以使用这些渲染器来降级。

来看看WebGLRenderer的源码

this.setSize = function ( width, height, updateStyle ) {
            ....
}

我们还需要在应用程序中设置渲染器的大小。例如,我们可以使用渲染区域所需的宽度和高度,用渲染器渲染的场景填充我们的应用程序。因此,我们可以将渲染器的宽度设置为浏览器窗口的宽度。对于性能敏感的应用程序,可以使用setSize传入较小的值,例如window。Innerwidth /2和窗口。Innerheight /2,这将导致应用程序以宽度和长度的一半渲染场景。

如果希望保持应用程序的大小,但以较低的分辨率呈现,可以在调用setSize时将updateStyle(第三个参数)设置为false。

例如,假设你的<canvas> 标签现在已经具有了100%的宽和高,调用setSize(window.innerWidth/2, window.innerHeight/2, false)将使得你的应用程序以一半的分辨率来进行渲染。

载入WebGL

renderer(渲染器)的dom元素(renderer.domElement)添加到最初创建的HTML文件中。

给场景加一个物体

// 创建geo: 长方体geo 参数:长,宽,高
const geometry = new THREE.BoxGeometry(100, 100, 100);
// 创建材质 :颜色 16进制
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
// 将材质和物体合体
const cube = new THREE.Mesh( geometry, material );
// 添加入场景
scene.add( cube );

要创建一个立方体,我们需要一个BoxGeometry对象。这个对象包含立方体中的所有顶点和面。后续会专门讲解Geo源码

现在,对于这个立方体,我们需要给它一种材质来给它上色。Three.js附带了几种材料。这里我们使用的是MeshBasicMaterial。所有的材料都有应用于其属性的对象。为了简单起见,我们将设置一个颜色属性,其值为0x00FF00,即绿色。你在这里所做的与你在CSS或Photoshop中使用十六进制颜色格式设置颜色的方法相同。

第三步,我们需要一个网格。网格包含一个几何体和作用于那个几何体上的材质,我们可以将网格对象直接放置到场景中,让它在场景中自由移动。

默认情况下,当我们调用scene.add()时,对象将被添加到(0,0,0)坐标。但它会把相机和立方体结合在一起。为了防止这种情况发生,我们只需要将摄像机移出一点。

渲染场景

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

我们需要使用一个被叫做“渲染循环”(render loop)或者“动画循环”(animate loop)的东西。

在这里我们创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环(在大多数屏幕上,刷新率一般是60次/秒)。如果你是一个浏览器游戏开发的新手,你或许会说“为什么我们不直接用setInterval来实现刷新的功能呢?”当然啦,我们的确可以用setInterval,但是,requestAnimationFrame有很多的优点。最重要的一点或许就是当用户切换到其它的标签页时,它会暂停,因此不会浪费用户宝贵的处理器资源,也不会损耗电池的使用寿命。

这样一个基础场景已经搭建完成。

完整代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset=utf-8>
		<title>创建一个简单的ThreeJS场景</title>
		<style>
			body { margin: 0; }
			#mainCanvas { width: 100%; height: 100% }
		</style>
	</head>
	<body>
        <div id="mainCanvas"></div>
		<script src="js/three.js"></script>
		<script>
			var scene = new THREE.Scene();
            var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );

            var renderer = new THREE.WebGLRenderer();
            renderer.setSize( window.innerWidth, window.innerHeight );
            document.querySelector('#mainCanvas').appendChild( renderer.domElement );

            const geometry = new THREE.BoxGeometry(100, 100, 100);;
			const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
			const cube = new THREE.Mesh( geometry, material );
			scene.add( cube );

			const animate = function () {
				requestAnimationFrame( animate );

				cube.rotation.x += 0.01;
				cube.rotation.y += 0.01;

				renderer.render( scene, camera );
			};

			animate();
		</script>
	</body>
</html>

更多推荐

ThreeJS从实战到源码 - 创建场景