如何从头开始创建自定义的Verge3D应用 - Soft8Soft

# 编程基础

本节的目标是为Verge3D做一个简要的介绍。我们将首先设置一个场景，其中包含了一个旋转的立方体。在本页结尾提供了一个完成了的示例，以防您遇到瓶颈或需要帮助。

- 开始之前
- 创建场景
- 渲染场景
- 为立方体做动画
- 结果

#

## 开始之前

Verge3D之前，您需要在某个地方展示它。将以下HTML保存到计算机上的一个文件中，同时将Verge3D的复制到应用目录中，然后在浏览器中打开。

`<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>My first Verge3D app</title> <style> body { margin: 0; } canvas { width: 100%; height: 100% } </style> </head> <body> <script src="v3d.js"></script> <script> // Our Javascript will go here. </script> </body> </html>`

好了，接下来的所有代码将会写入到空的<script>标签中。

#

## 创建场景

为了真正能够用Verge3D显示内容，我们需要三样对象：场景、摄影机和渲染器，这样我们就可以通过摄影机来渲染场景。

`const scene = new v3d.Scene(); const camera = new v3d.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new v3d.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement);`

让我们花点时间来解释一下其基本原理。我们现在已经建立了场景，摄影机和渲染器。

在Verge3D中有几种不同类型的摄影机。我们先来使用 PerspectiveCamera(透视摄影机)。

第一个属性是field of view(视场).FOV是指在任何特定时刻在显示器上看到的场景的范围。该值以角度为单位。

第二个属性是 aspect ratio(长宽比)。您应该始终使用元素的宽度除以高度作为屏幕高宽比，否则画面将会如同在宽屏电视上播放老电影一样——图像像是被压扁了。

接下来的两个属性是剪切屏幕的 near 和 far 。这代表着，对象离摄影机的距离比 far 远的或比 near 近的都不会渲染。暂时不必担心这些，但您可以用于应用设定以提升性能。

接下来是渲染器。这里是奇迹发生的地方。除了我们在这里使用的WebGLRenderer之外，Verge3D还附带了一些其他的渲染器，通常用作老式浏览器的用户或由于某种原因不支持WebGL的用户的后备措施。

除了创建渲染器实例之外，我们还需要设置应用中的渲染器尺寸。将应用填满需要显示区域的空间是个好主意——在本案例中，我们使用浏览器窗口的宽度和高度定义尺寸。对于性能敏感的应用，您还可以将 setSize 设置小一点，如 Window.InnerWidth/2 和 Window.InnerHeight/2，这将使应用渲染尺寸长宽都是窗口的四分之一。

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

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

“嗯，看起来很不错，那您说的那个立方体在哪儿？”接下来，我们就来添加立方体。

`const geometry = new v3d.BoxGeometry(); const material = new v3d.MeshBasicMaterial({ color: 0x00ff00 }); const cube = new v3d.Mesh(geometry, material); scene.add(cube); camera.position.z = 5;`

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

除了几何形状，我们还需要一个材质来给它上色。Verge3D自带了几种材质，在这里我们暂时使用 MeshBasicMaterial 。所有的材质都存有应用于他们的属性的对象。在这里为了简单起见，我们只设置一个color属性，值为 0x00ff00，也就是绿色。这与CSS或Photoshop中的颜色工作方式相同（十六进制颜色）。

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

默认情况下，当我们调用 scene.add()时，我们添加的东西会添加到坐标上 (0,0,0)。这将导致摄影机和立方体进入彼此内部。为避免这种情况，我们只需要将摄影机稍微向外移动一些即可。

#

## 渲染场景

如果您把上面的代码复制到我们先前创建的HTML文件中，您将不会看到任何东西。这是因为我们还没开始真正的渲染。为此，我们需要 render or animate loop(渲染或动画循环)。

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

这将创建一个循环，使渲染器在每次刷新屏幕时都绘制场景（在典型的屏幕上，这意味着每秒 60 次）。如果您刚开始在浏览器中编写游戏，您也许会问：“为什么我们不直接创建一个setInterval呢？”当然可以，但 requestAnimationFrame 有许多优点。也许这是最重要的一个原因：当用户导航到另一个浏览器标签时，渲染器会暂停工作，因此不会浪费宝贵的CPU性能和电池功耗。

#

## 为立方体做动画

如果您将上面的所有代码插入到我们开始之前创建的文件中，应该会看到一个绿色的盒子。让我们来做一些更加有趣的事 —— 让它旋转起来。

在renderer.render 中调用 animate 功能：

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

这会将每帧运行一次（通常为每秒60次），并给立方体一个漂亮的旋转动画。基本上，当应用运行时，任何您想要移动或改变的东西都必须经过动画循环。当然，您可以从那里调用其他函数，这样就不至于最后出现一个几百行的 animate 函数。

#

## 结果

恭喜您！您现在完成了您的第一个Verge3D应用。虽然很简单，但您现在有了一个起点。

完整的代码如下所示。试玩一下，以便更好地理解工作原理。

`<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>My first Verge3D app</title> <style> body { margin: 0; } canvas { width: 100%; height: 100% } </style> </head> <body> <script src="v3d.js"></script> <script> const scene = new v3d.Scene(); const camera = new v3d.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new v3d.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); const geometry = new v3d.BoxGeometry(); const material = new v3d.MeshBasicMaterial({ color: 0x00ff00 }); const cube = new v3d.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>`