创建一个场景

开始之前

在开始使用three.js之前,你需要一个地方来显示它。将下列HTML代码保存为你电脑上的一个HTML文件,同时将three.js复制到该HTML文件所在的目录下的js/目录下,然后在你的浏览器中打开这个HTML文件。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>My first three.js app</title>
		<style>
			body { margin: 0; }
		</style>
	</head>
	<body>
		<script src="https://threejs.org/build/three.js"></script>
		<script>
			// Our Javascript will go here.
		</script>
	</body>
</html>

创建一个场景

需要以下几个对象:场景、相机和渲染器,这样我们就能透过摄像机渲染出场景。

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

我们花一点点时间来解释一下这里发生了什么。我们现在建立了场景、相机和渲染器。

PerspectiveCamera(透视摄像机)

  • 第一个参数是视野角度(FOV)。视野角度就是无论在什么时候,你所能在显示器上看到的场景的范围,它的单位是角度(与弧度区分开)。
  • 第二个参数是长宽比(aspect ratio)。 也就是你用一个物体的宽除以它的高的值。比如说,当你在一个宽屏电视上播放老电影时,可以看到图像仿佛是被压扁的。
  • 接下来的两个参数是近截面(near)和远截面(far)。 当物体某些部分比摄像机的远截面远或者比近截面近的时候,该这些部分将不会被渲染到场景中。或许现在你不用担心这个值的影响,但未来为了获得更好的渲染性能,你将可以在你的应用程序里去设置它。

渲染器

除了我们在这里用到的WebGLRenderer渲染器之外,Three.js同时提供了其他几种渲染器,当用户所使用的浏览器过于老旧,或者由于其他原因不支持WebGL时,可以使用这几种渲染器进行降级。

  • 对于性能比较敏感的应用程序来说,你可以使用setSize传入一个较小的值,例如 window.innerWidth/2window.innerHeight/2 ,这将使得应用程序在渲染时,以一半的长宽尺寸渲染场景。
  • 如果你希望保持你的应用程序的尺寸,但是以较低的分辨率来渲染,你可以在调用 setSize 时,将 updateStyle (第三个参数)设为 false 。例如,假设你的 <canvas> 标签现在已经具有了100%的宽和高,调用 setSize(window.innerWidth/2, window.innerHeight/2, false) 将使得你的应用程序以一半的分辨率来进行渲染。
  • 最后一步很重要,我们将 renderer (渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中。这就是渲染器用来显示场景给我们看的<canvas>元素。

添加立方体

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

camera.position.z = 5;
  • BoxGeometry(立方体)对象
    这个对象包含了一个立方体中所有的顶点(vertices)和面(faces)。
    对于这个立方体,我们需要给它一个材质,来让它有颜色。Three.js自带了几种材质,在这里我们使用的是 MeshBasicMaterial 。所有的材质都存有应用于他们的属性的对象。在这里为了简单起见,我们只设置一个color属性,值为0x00ff00,也就是绿色。这里所做的事情,和在CSS或者Photoshop中使用十六进制(hex colors)颜色格式来设置颜色的方式一致。
  • Mesh(网格)
    网格包含一个几何体以及作用在此几何体上的材质,我们可以直接将网格对象放入到我们的场景中,并让它在场景中自由移动。
  • scene.add()
    默认情况下,当我们调用scene.add()的时候,物体将会被添加到(0,0,0)坐标。但将使得摄像机和立方体彼此在一起。为了防止这种情况的发生,我们只需要将摄像机稍微向外移动一些即可。

渲染场景

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

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

创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环(在大多数屏幕上,刷新率一般是60次/秒)。

如果你是一个浏览器游戏开发的新手,你或许会说“为什么我们不直接用 setInterval 来实现刷新的功能呢?”当然啦,我们的确可以用 setInterval ,但是, requestAnimationFrame 有很多的优点。最重要的一点或许就是当用户切换到其它的标签页时,它会暂停,因此不会浪费用户宝贵的处理器资源,也不会损耗电池的使用寿命

使立方体动起来

将下列代码添加到animate()函数中renderer.render调用的上方:

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

这段代码每帧都会执行(正常情况下是60次/秒),这就让立方体有了一个看起来很不错的旋转动画。基本上来说,当应用程序运行时,如果你想要移动或者改变任何场景中的东西,都必须要经过这个动画循环。当然,你可以在这个动画循环里调用别的函数,这样你就不会写出有上百行代码的animate函数。

安装

教程:three.js 安装

兼容性检查

把下面文件引入到开始执行,用于检测浏览器是否支持运行WebGL

if (WebGL.isWebGLAvailable()) {
    // Initiate function or other initializations here
    animate();
} else {
    const warning = WebGL.getWebGLErrorMessage();
    document.getElementById('container').appendChild(warning);
}

画线

  • 定义一个材质。对于线条来说,我们能使用的材质只有 LineBasicMaterial 或者 LineDashedMaterial
//create a blue LineBasicMaterial
const material = new THREE.LineBasicMaterial( { color: 0x0000ff } );
  • 需要一个带有一些顶点的geometry(几何体)。
const points = [];
points.push( new THREE.Vector3( - 10, 0, 0 ) );
points.push( new THREE.Vector3( 0, 10, 0 ) );
points.push( new THREE.Vector3( 10, 0, 0 ) );

const geometry = new THREE.BufferGeometry().setFromPoints( points );

注意,线是画在每一对连续的顶点之间的,而不是在第一个顶点和最后一个顶点之间绘制线条(线条并未闭合)。
既然我们已经有了能够画两条线的点和一个材质,那我们现在就可以将他们组合在一起,形成一条线。

const line = new THREE.Line( geometry, material );

剩下的事情就是把它添加到场景中,并调用render(渲染)函数。

创建文字

  • DOM + CSS
    使用HTML通常是最简单、最快速的添加文本的方法,这是大多数的Three.js示例中用于添加描述性叠加文字的方法。

  • 将文字绘制到画布中,并将其用作Texture(纹理)
    如果你希望在three.js的场景中的平面上轻松地绘制文本,请使用此方法
    https://www.three3d.cn/docs/index.html#api/zh/textures/Texture

  • 在你所喜欢的3D软件里创建模型,并导出给three.js
    如果你更喜欢使用3D建模软件来工作并导出模型到three.js,请使用这种方法。

  • three.js自带的文字几何体
    如果你更喜欢使用纯three.js来工作,或者创建能够由程序改变的、动态的3D文字,你可以创建一个其几何体为THREE.TextGeometry的实例的网格:

new THREE.TextGeometry( text, parameters );

然而,为了使得它能够工作,你的TextGeometry需要在其“font”参数上设置一个THREE.Font的实例。
请参阅 TextGeometry 页面来阅读如何完成此操作的详细信息,以及每一个接收的参数的描述,还有由three.js分发、自带的JSON字体的列表。

示例
WebGL / geometry / text
WebGL / shadowmap

如果Typeface已经关闭,或者没有你所想使用的字体,这有一个教程:http://www.jaanga.com/2012/03/blender-to-threejs-create-3d-text-with.html
这是一个在blender上运行的python脚本,能够让你将文字导出为Three.js的JSON格式。

  • 位图字体
    BMFonts (位图字体) 可以将字形批处理为单个BufferGeometry。BMFont的渲染支持自动换行、字母间距、字句调整、signed distance fields with standard derivatives、multi-channel signed distance fields、多纹理字体等特性。 详情请参阅 three-mesh-ui 或 。
    现有库存的字体在项目中同样可用,就像A-Frame Fonts一样, 或者你也可以从任何TTF字体中创建你自己的字体,优化时,只需要包含项目中所需的字符即可。

载入3D模型

推荐的工作流程

如果有可能的话,我们推荐使用 glTF(gl传输格式)。.GLB.GLTF 是这种格式的这两种不同版本, 都可以被很好地支持。由于glTF这种格式是专注于在程序运行时呈现三维物体的,所以它的传输效率非常高,且加载速度非常快。 功能方面则包括了网格、材质、纹理、皮肤、骨骼、变形目标、动画、灯光和摄像机

glTF 不可用的时候,诸如 FBXOBJ 或者 COLLADA 等等其它广受欢迎的格式在Three.js中也是可以使用、并且定期维护的。

加载

在three.js中只会内置一部分加载器(例如:ObjectLoader) —— 其它的需要在你的应用中单独引入。

import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

一旦你引入了一个加载器,你就已经准备好为场景添加模型了。不同加载器之间可能具有不同的语法 —— 当使用其它格式的时候请参阅该格式加载器的示例以及文档。对于glTF,使用全局script的用法类似:

const loader = new GLTFLoader();

loader.load( 'path/to/model.glb', function ( gltf ) {

	scene.add( gltf.scene );

}, undefined, function ( error ) {

	console.error( error );

} );

请参阅 GLTFLoader documentation 来深入了解详细信息。

故障排除

请求帮助