threejs入门第一节如何用threejs创建一个简单的场景

什么是threejs?

threejs是一个用于在浏览器中绘制3D图像的JS库。它是基于webgl实现了,包括了webgl1和webgl2的渲染引擎。同时也包括了最新的webgpu。(部分浏览器基本不支持)。

准备工作

你可以新建一个vue或者react的工程项目,然后在命令行中使用命令

npm i three

如果是使用typescript进行开发的话,需要安装dts定义文件,使用命令

npm i @types/three

如果你是使用单个html文件进行开发的话,就很简单了,直接下载threejs的文件,然后用script引入进来就可以了

<script src="js/three.js"></script> //注意使用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="js/three.js"></script>
		<script>
			// Our Javascript will go here.
		</script>
	</body>
</html>

然后在script标签中写入创建场景的代码。

创建一个场景

three的场景主要包括了三个对象,场景Scene,相机Camera和渲染器Render,同时在正常应用的时候还需要包括物体 Object和控制器Contro以及灯光Light。

  • 场景Scene:按照名字来理解,就是一个场景,就是各种物体和模型放在哪里展示,就是展示3D元素的地方,所以场景是必不可少的。
  • 相机Camera:相机的意思就是场景有了,那么我们怎么看这个场景呢,Camera就相当于我们的眼睛,定义了我们是用什么角度,站在多远的距离来看这个场景的,根据相机参数的不同,同样的场景在屏幕上显示的内容是不同的,就像人眼从不同地方看一个东西肯定是不同的。
  • 渲染器Render:屏幕是二维,用来展示3D的三维场景,就需要在场景展示时不停的进行渲染,这时候就需要Render,可以设置Render的参数来控制场景渲染的效果。
  • 物体Object:场景定义了,就可以在场景上展示一些物体了,包括,点、线、面、3D模型等,three官方定义了很多种展示的物体,最基础的Mesh。
  • 控制器Control:场景绘制好了,物体也添加了,那么我们需要操作物体,旋转切换视角,平移物体等,这个时候需要Control,一般使用的是轨道控制器(OrbitControls)
  • 灯光Light:灯光就是定义了在什么位置有一个什么样的光照向物体,一般没有特殊的要求可以不定义灯光,或者使用自然光,关于灯光的定义在three的官方文档中也有说明。

创建一个场景的代码

const scene = new THREE.Scene();//创建一个场景Scene
//定义一个相机Camera
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
//定义一个渲染器Render
const renderer = new THREE.WebGLRenderer();
//设置render的渲染范围
renderer.setSize( window.innerWidth, window.innerHeight );
//将场景元素添加到body中
document.body.appendChild( renderer.domElement );

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

three.js里有几种不同的相机,在这里,我们使用的是PerspectiveCamera(透视摄像机)。

第一个参数是视野角度(FOV)。视野角度就是无论在什么时候,你所能在显示器上看到的场景的范围,它的单位是角度(与弧度区分开)。

第二个参数是长宽比(aspect ratio)。 也就是你用一个物体的宽除以它的高的值。比如说,当你在一个宽屏电视上播放老电影时,可以看到图像仿佛是被压扁的。

接下来的两个参数是近截面(near)和远截面(far)。 当物体某些部分比摄像机的远截面远或者比近截面近的时候,该这些部分将不会被渲染到场景中。或许现在你不用担心这个值的影响,但未来为了获得更好的渲染性能,你将可以在你的应用程序里去设置它。

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

除了创建一个渲染器的实例之外,我们还需要在我们的应用程序里设置一个渲染器的尺寸。比如说,我们可以使用所需要的渲染区域的宽高,来让渲染器渲染出的场景填充满我们的应用程序。因此,我们可以将渲染器宽高设置为浏览器窗口宽高。对于性能比较敏感的应用程序来说,你可以使用setSize传入一个较小的值,例如window.innerWidth/2window.innerHeight/2,这将使得应用程序在渲染时,以一半的长宽尺寸渲染场景。

如果你希望保持你的应用程序的尺寸,但是以较低的分辨率来渲染,你可以在调用setSize时,将updateStyle(第三个参数)设为false。例如,假设你的 标签现在已经具有了100%的宽和高,调用**setSize(window.innerWidth/2, window.innerHeight/2, false)**将使得你的应用程序以一半的分辨率来进行渲染。

最后一步很重要,我们将renderer(渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中。这就是渲染器用来显示场景给我们看的元素。

给场景添加一个物体

const geometry = new THREE.BoxGeometry();//定义一个geometry,geometry定义了物体的形状,three有很多种geometry
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );//material定义了物体的材质,简单说就是外观
const cube = new THREE.Mesh( geometry, material );//mesh定义了一个物体,物体由geometry和material定义组成,形状加外观
scene.add( cube );//然后将物体添加到场景中去
camera.position.z = 5;//定义相机的z坐标,就是相机看的位置,此时要注意一下three中相机坐标系的概念,x横向,z纵向,y是竖直的,后期有兴趣可以慢慢研究three的坐标系

要创建一个立方体,我们需要一个BoxGeometry(立方体)对象. 这个对象包含了一个立方体中所有的顶点(vertices)和面(faces)。未来我们将在这方面进行更多的探索。

接下来,对于这个立方体,我们需要给它一个材质,来让它有颜色。Three.js自带了几种材质,在这里我们使用的是MeshBasicMaterial。所有的材质都存有应用于他们的属性的对象。在这里为了简单起见,我们只设置一个color属性,值为0x00ff00,也就是绿色。这里所做的事情,和在CSS或者Photoshop中使用十六进制(hex colors)颜色格式来设置颜色的方式一致。

第三步,我们需要一个Mesh(网格)。 网格包含一个几何体以及作用在此几何体上的材质,我们可以直接将网格对象放入到我们的场景中,并让它在场景中自由移动。

默认情况下,当我们调用**scene.add()的时候,物体将会被添加到(0,0,0)**坐标。但将使得摄像机和立方体彼此在一起。为了防止这种情况的发生,我们只需要将摄像机稍微向外移动一些即可,就是向你的面前移动。

渲染场景

现在场景和物体都有了,这个时候,如果刷新页面,你会发现它是空白,并不能看到添加到场景中的立方体。这是因为我们还没有对它进行真正的渲染。为此,我们需要使用一个被叫做“渲染循环”(render loop)或者“动画循环”(animate loop)的东西。

//定义渲染的动画函数
function animate() 
{ 
    //将animate函数添加到requestAnimationFrame,进行循环调用
    requestAnimationFrame( animate ); 
    //执行渲染器的渲染函数
    renderer.render( scene, camera ); 
}
//执行渲染函数
animate();

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

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。更多的详细内容参考requestAnimationFrame

使立方体动起来

在开始之前,如果你已经将上面的代码写入到了你所创建的文件中,你可以看到一个绿色的方块。让我们来做一些更加有趣的事 —— 让它旋转起来。

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

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

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

当然我们还有别的办法让这个立方体自然旋转起来,那就是利用Control,到此,你就可以用three来画一个立方体了。这就是一个成功的three 3d程序。

<html>
	<head>
		<meta charset="utf-8">
		<title>My first three.js app</title>
		<style>
			body { margin: 0; }
		</style>
	</head>
	<body>
		<script src="js/three.js"></script>
		<script>
			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 );

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

			camera.position.z = 5;

			function animate() {
				requestAnimationFrame( animate );

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

				renderer.render( scene, camera );
			};

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

更多three的代码示例,你可以看three的官方网站,支持中文的。three example

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值