注册

Three.js 随着元宇宙开启WEB3D之路

当视频游戏遇到Web 2.0时会发生什么? 当虚拟世界相遇地球的地理空间地图?当模拟变成现实,生活和商业变成虚拟?当你使用虚拟地球在物理地球上导航时,你的化身就变成了你的在线代理?这一切发生的就是元宇宙。

元宇宙设想了一个由虚拟世界和3D技术广泛应用重塑的未来。 Three.js 是一个非常令人印象深刻的 JavaScript 3D 库,它也使用 WebGL(或 2d Canvas)进行渲染。随着 WebGL API 标准的改进,以及对 WebXR 的支持, Three.js 成为了一个可以用来营造沉浸式体验的主流工具。与此同时,浏览器对 3D 渲染和 WebXR 设备 API 的支持也得到提升,使得 web 成为一个越来越有吸引力的 3D 内容平台。

Three.js

Three.js Ricardo Cabello(@mrdoob) 在2010年开发的一个JavaScript库(如今它在Github上有许多贡献者)。这个令人难以置信的工具让用户可以在浏览器上处理 3D 图形,使用 WebGL 技术非常简单和直观的方式来实现。而 WebGL 技术已经非常普及和被浏览器广泛支持。

8375c7437223e8c342dd56ce822ad3db.png

WebGL 在许多设备和浏览器中创建丰富的交互体验, 点击查看浏览器支持程度。

c90ebd03811adf5db3cd7f5c43f19e1a.png

开始

本文将以 Vue 为基础框架来构建 Three.js 示例,关于代码可以查阅 GitHub

首先安装依赖:

npm install three --save

构建

现在开始添加代码到页面,如下:

<template>
<div id="app"></div>
</template>

<script>
import * as THREE from "three";
export default {
name: "App",
data() {
return {};
},
mounted() {
this.init();
},
methods: {
init() {
const scene = new THREE.Scene();

// 创建一个基本透视相机 camera
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 4;

// 创建一个抗锯齿渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });

// 配置渲染器清除颜色
renderer.setClearColor("#000000");

// 配置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);

// 添加渲染器到DOM
document.body.appendChild(renderer.domElement);

// 创建一个立方体网格
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: "#433F81" });
const cube = new THREE.Mesh(geometry, material);

// 将立方体到场景中
scene.add(cube);

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

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

renderer.render(scene, camera);
};

render();
},
},
};
</script>

然后再添加简单的样式:

body {
margin: 0;
}
canvas {
width: 100%;
height: 100%;
}

执行脚本 yarn serve ,打开浏览器将看到如下效果:

8f18964a9060784ddca287aef2fd18f3.gif

这是每个 Three.js 应用程序一种常见模式,包括 WebGlRendererSceneCamera ,如下:

  1. 创建渲染器WebGlRenderer

  2. 创建 Scene

  3. 创建Camera

渲染器是放置场景结果的地方。在 Three.js 中,可以有多个场景,每个场景可以有不同的对象。

1a1e6634a369617643c6cbc9db4f58ae.png

在示例中创建 WebGLRenderer,再将窗口的大小作为参数传递给它,然后将它附加到 DOM 中。

// 创建一个抗锯齿渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });

// 配置渲染器清除颜色
renderer.setClearColor("#000000");

// 配置渲染器尺寸
renderer.setSize(window.innerWidth, window.innerHeight);

// 添加渲染器到DOM
document.body.appendChild(renderer.domElement);

首先需要创建一个空场景,将在其中添加创建的立方体对象:

const scene = new THREE.Scene();

最后创建一个相机 camera ,将 视野 、纵横比以及近平面和远平面作为参数:

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

到此 Three.js 应用程序的 3 个基本元素已经完成了。

几何、材料和网格

第二种常见模式是向场景添加对象:

  1. 创建几何

  2. 创建材质

  3. 创建网格

  4. 将网格添加到场景中。

在 Three.js 中,网格是几何体与材质的组合。

68ed7f60d3050893f972670d9f11dfd6.png

几何是对象的数学公式,在 Three.js 中有很多几何,将在以后的章节中探索它,几何体提供了要添加到场景中的对象的顶点。

1f690cea38c2a291e89d76da003d0a50.png

材质可以定义为对象的属性及其与场景光源的行为。如下图所示,有不同类型的材料。

5470f3e3d094ad0a584167468405f76f.png

现在知道了网格、几何体和材质是什么,将把它们添加到场景中。在示例中,使用基本材质创建一个立方体:

// 创建一个立方体网格
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: "#1b55e3" });
const cube = new THREE.Mesh(geometry, material);

// 将立方体到场景中
scene.add(cube);

请求动画帧

最后一段代码是为场景设置动画,使用 requestAnimationFrame,它允许有一个以每秒 60 帧(最多)运行的函数。

const render = () => {
  requestAnimationFrame(render);
  renderer.render(scene, camera);
};

render();

立方体动画

为了在渲染循环中为立方体设置动画,需要更改它的属性。当创建一个网格时,可以访问一组在动画制作时非常有用的属性。

// Rotation (XYZ) 弧度
cube.rotation.x;
cube.rotation.y;
cube.rotation.z;

// Position (XYZ)
cube.position.x;
cube.position.y;
cube.position.z;

// Scale (XYZ)
cube.scale.x;
cube.scale.y;
cube.scale.z;

在示例中,为立方体设置 X 和 Y 旋转动画:

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

控制台

作为前端,控制台是最好的调试工具。当使用 Three.js 时,控制台是必不可少的工具。

效果增持

现在理解了示例的逻辑,将向场景中添加更多片段,目的是生成更复杂的片段。

/**
* 创建材质的方法
*/
const createMesh = (boxOptions, meshOptions) => {
  const geometry = new THREE.BoxGeometry(...boxOptions);
  const material = new THREE.MeshBasicMaterial(meshOptions);
  return new THREE.Mesh(geometry, material);
};

const cube01 = createMesh([1, 1, 1], {
  color: "#A49FEF",
  wireframe: true,
  transparent: true,
});
scene.add(cube01);

const cube01_wireframe = createMesh([3, 3, 3], {
  color: "#433F81",
  wireframe: true,
  transparent: true,
});
scene.add(cube01_wireframe);

const cube02 = createMesh([1, 1, 1], {
  color: "#A49FEF",
});
scene.add(cube02);

const cube02_wireframe = createMesh([3, 3, 3], {
  color: "#433F81",
  wireframe: true,
  transparent: true,
});

scene.add(cube02_wireframe);

const bar01 = createMesh([10, 0.05, 0.5], {
  color: "#00FFBC",
});
bar01.position.z = 0.5;
scene.add(bar01);

const bar02 = createMesh([10, 0.05, 0.5], {
  color: "#ffffff",
});
bar02.position.z = 0.5;
scene.add(bar02);

const render = () => {
  requestAnimationFrame(render);

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

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

  cube02.rotation.x -= 0.01;
  cube02.rotation.y -= 0.01;

  cube02_wireframe.rotation.x -= 0.01;
  cube02_wireframe.rotation.y -= 0.01;

  bar01.rotation.z -= 0.01;
  bar02.rotation.z += 0.01;

  renderer.render(scene, camera);
};

render();

运行后效果如图:

9a6715e760e61e63d6096dae613582ea.jpg

作者:天行无忌
来源:http://blog.51cto.com/u_15088848/4670782

0 个评论

要回复文章请先登录注册