threejs-d-2.0

threejs-d-2.0

一、创建第一个threejs应用

代码汇总:

//main.js
import * as THREE from 'three'

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 );//将输出canvas的大小调整为(width, height)并考虑设备像素比,且将视口从(0, 0)开始调整到适合大小
document.body.appendChild( renderer.domElement );//将renderer(渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中

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;//调整相机位置(默认0,0,0)

//几何体循环旋转动画
function animate() {
    requestAnimationFrame( animate );
  //旋转坐标变换
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
  //重新渲染几何体
    renderer.render( scene, camera );
}
animate();

1.创建场景、相机、渲染器

如果我们有玩过三维软件的同学应该不会陌生这几个概念

我们下面以三维软件C4D来简单认识一下吧

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

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

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)**将使得你的应用程序以一半的分辨率来进行渲染。

document.body.appendChild( renderer.domElement );

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

2.创建几何体、材质

对于材质这块,就是给一个没有任何属性的物体添加属性,玻璃、金属、玉、有颜色的立方体。

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

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;

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

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

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

3.创建渲染

这个就比较好理解了,添加x,y,z方向的位置变化

现在,如果将之前写好的代码复制到HTML文件中,你不会在页面中看到任何东西。这是因为我们还没有对它进行真正的渲染。为此,我们需要使用一个被叫做“渲染循环”(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函数。

效果演示:

二、控制器(轨道控制器)

控制器有许多,我们这先说这一种

轨道控制器是以物体为中心,对物体做环绕运动

代码汇总:

//main.js
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' //导入轨道控制器

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

const geometry = new THREE.BoxGeometry( 5, 5, 5 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
const controls = new OrbitControls( camera,renderer.domElement  );
camera.position.set(0,20,100);
controls.update();//更新控制器。必须在摄像机的变换发生任何手动改变后调用
function animate() {
    requestAnimationFrame( animate );
    controls.update();//循环更新轨道控制器
    renderer.render( scene, camera );
}
animate();

OrbitControls( object : Camera, domElement : HTMLDOMElement )

object: (必须)将要被控制的相机。该相机不允许是其他任何对象的子级,除非该对象是场景自身。

domElement: 用于事件监听的HTML元素。

那我们现在就可以移动我们的相机来观察我们的物体了。

三、添加辅助器

这个来自与我们help里面的东西,文档里查就可以了

添加辅助器的用处是为了更好的去开发

1.坐标辅助器

用于简单模拟3个坐标轴的对象.
红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.

const axesHelper = new THREE.AxesHelper( 5 );//轴的线段长度. 默认为 1.
scene.add( axesHelper );//添加到场景

2.相机辅助器

用于模拟相机视锥体的辅助对象.
它使用 LineSegments 来模拟相机视锥体.

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

CameraHelper( camera : Camera )

camera – 被模拟的相机.

为指定相机创建一个新的相机辅助对象 CameraHelper .

3.平面辅助器

用于模拟平面 Plane 的辅助对象.

const plane = new THREE.Plane( new THREE.Vector3( 1, 1, 0.2 ), 3 );
const helper = new THREE.PlaneHelper( plane, 100, 0xffff00 );
scene.add( helper );

PlaneHelper( plane : Plane, size : Float, hex : Color )

plane – 被模拟的平面.
size – (可选的) 辅助对象的单边长度. 默认为 1.
color – (可选的) 辅助对象的颜色. 默认为 0xffff00.

创建一个线框辅助对象来表示指定平面.

终结:

其他的辅助器,我们就自己按照需求去加吧,这个就是做一个参照

四、物体的属性

物体的属性,那我们要看一下cube是什么了

根据控制台打印,它是个Mesh类,下面有许多属性

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

1.物体的位移

控制物体的位置

cube.position.set(10,0,0)//默认为x,y,z方向

2.物体的旋转

控制问题的旋转角度

这个不是单纯的三维向量了

是一个Euler类

cube.rotation.set(Math.PI/4,0,0,'XYZ')//默认为‘xyz’

Euler( x : Float, y : Float, z : Float, order : String )

x - (optional) 用弧度表示x轴旋转量。 默认值是 0
y - (optional) 用弧度表示y轴旋转量。 默认值是 0
z - (optional) 用弧度表示z轴旋转量。 默认值是 0
order - (optional) 表示旋转顺序的字符串,默认为’XYZ’(必须是大写)。

3.物体的缩放

控制物体缩放

cube.scale.set(3,2,1)

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2022-2023 alan_mf
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信