瀏覽器中的 3D 圖形自首次推出以來一直是個熱門話題。但如果您要使用純 WebGL 建立應用程序,則需要很長時間。這正是最近出現一些真正有用的函式庫的原因。 Three.js 是最受歡迎的之一,在本系列中,我將向您展示如何最好地使用它,以便為您的用戶創建令人驚嘆的 3D 體驗。
在開始之前,我確實希望您在開始閱讀本教學之前對 3D 空間有基本的了解,因為我不會解釋座標、向量等內容。
首先,建立三個檔案:index.html
、main.js
和 style.css
。現在,下載 Three.js(帶有範例和原始程式碼的整個 zip 文件,或單獨的 JavaScript 文件,您可以選擇)。現在,打開 index.html
並插入以下程式碼:
<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="./style.css"> <script src="./three.js"></script> </head> <body> <script src="./main.js"></script> </body> </html>
這就是您在此文件中所需要的全部內容。只是腳本和样式表的聲明。所有的魔力都會發生在 main.js
中,但在我們實現這一點之前,我們還需要一個技巧來讓應用程式看起來更好。開啟 style.css
並插入以下程式碼:
canvas { position: fixed; top: 0; left: 0; }
這會將畫布定位在左上角,因為預設情況下 body
將具有 8px 的邊距。現在我們可以繼續處理 JavaScript 程式碼。
Three.js 使用顯示清單的概念。這意味著所有物件都儲存在列表中,然後繪製到螢幕上。
Three.js 使用顯示清單的概念。這意味著所有物件都儲存在列表中,然後繪製到螢幕上。在這裡,這是一個 THREE.Scene
物件。您需要將想要在螢幕上繪製的任何物件新增到場景中。您可以擁有任意多個場景,但一個渲染器一次只能繪製一個場景(當然您可以切換顯示的場景)。
渲染器只是將場景中的所有內容繪製到 WebGL 畫布上。 Three.js 也支援在 SVG 或 2D Canvas 上繪圖,但我們將專注於 WebGL。
首先,讓我們將視窗的寬度和高度儲存在變數中,稍後我們將使用它:
var width = window.innerWidth; var height = window.innerHeight;
現在定義渲染器和場景:
var renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(width, height); document.body.appendChild(renderer.domElement); var scene = new THREE.Scene;
第一行定義 WebGL 渲染器。您可以將第一個參數中的渲染器選項作為地圖傳遞。這裡,我們將 antialias
設為 true,因為我們希望物件的邊緣平滑,而不是鋸齒狀。
第二行將渲染器大小設為視窗的大小,在第三行中,我們將渲染器的canvas
元素新增至文件(您也可以使用庫來執行此操作,例如jQuery: $( 'body').append(renderer.domElement)
)。
最後一個定義場景,不需要參數。
現在讓我們加入要繪製的內容。讓它成為一個立方體,因為它是最簡單的 3D 物件。在 Three.js 中,螢幕上繪製的物件稱為網格。每個網格都必須有自己的幾何形狀和材質。幾何是一組需要連接才能建立物件的點。材質只是覆蓋物件的油漆(或繪畫,但這不是本教學的主題)。那麼,讓我們創建我們的立方體。幸運的是,Three.js 中有一些用於建立基元(簡單形狀)的輔助函數:
var cubeGeometry = new THREE.CubeGeometry(100, 100, 100); var cubeMaterial = new THREE.MeshLambertMaterial({ color: 0x1ec876 }); var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.rotation.y = Math.PI * 45 / 180; scene.add(cube);
如您所見,首先我們建立幾何圖形。參數定義立方體的大小:寬度、高度和深度。
接下來,我們定義立方體的材質。 Three.js中有一些材質類型,但這次我們將使用THREE.MeshLambertMaterial
,因為我們稍後想要一些光照(該材質使用蘭伯特演算法進行光照計算)。您可以將第一個參數中的選項作為映射傳遞,與渲染器相同 - 這幾乎是 Three.js 中更複雜物件的規則。在這裡,我們只使用顏色,它以十六進制數字形式傳遞。
在第三行,我們使用先前建立的幾何體和材質來建立一個網格。接下來,我們將立方體在 Y 軸上旋轉 45 度,使其看起來更好。我們必須將度數改為弧度,這是透過您可能記得的高中物理課上的方程式來處理的:Math.PI * 45 / 180
。最後,立方體被添加到場景中。
現在您可以在瀏覽器中開啟 index.html
來查看結果,但您將看不到任何內容,因為場景尚未渲染。
要渲染某些內容,首先我們需要將相機加入場景中,以便渲染器知道應該從哪個角度渲染內容。 Three.js 中有幾種類型的相機,但您可能只會使用 THREE.PerspectiveCamera
。這種類型的相機呈現出我們所看到的世界的場景。讓我們創建一個:
var camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 10000);
“要渲染某些内容,首先我们需要将相机添加到场景中,以便渲染器知道应该从哪个角度渲染内容。”
创建相机比我们迄今为止所做的其他事情要复杂一些。第一个参数定义 FOV(视野),即从相机所在位置可以看到的角度。 45 度的 FOV 看起来很自然。接下来,我们定义相机的比率。这始终是渲染器的宽度除以高度,除非您想实现一些特殊效果。最后两个数字定义了对象与要绘制的相机的距离。
现在我们必须稍微向后和向上移动相机,因为在 Three.js 中创建的所有对象都将其位置设置在场景中间(x: 0, y: 0, z: 0)默认:
camera.position.y = 160; camera.position.z = 400;
z
坐标在观看者的方向上为正,因此具有较高 z
位置的对象会显得离您更近(在这种情况下,由于我们移动了相机,所有对象都会显得更远)来自您)。
现在,让我们将相机添加到场景并渲染它:
scene.add(camera); renderer.render(scene, camera);
添加相机就像添加立方体一样。下一行使用该相机渲染场景。现在您可以打开浏览器,您应该看到以下内容:
您应该只能看到立方体的顶部。这是因为我们将相机向上移动,但它仍然看起来在它的正前方。这个问题可以通过让相机知道它应该看什么位置来解决。在设置相机位置的行之后添加此行:
camera.lookAt(cube.position);
传入的唯一参数是相机将看到的位置。现在,场景看起来更好了,但立方体仍然是黑色,无论您在创建立方体时设置了什么颜色:
立方体是黑色的,因为场景中没有灯光,所以它就像一个完全黑的房间。您会看到白色背景,因为除了立方体之外没有任何东西可以绘制。为了避免这种情况,我们将使用一种称为天空盒的技术。基本上,我们将添加一个大立方体来显示场景的背景(如果是开放空间,通常是一些远处的地形)。那么,让我们创建这个盒子。此代码应位于 renderer.render
调用之前:
var skyboxGeometry = new THREE.CubeGeometry(10000, 10000, 10000); var skyboxMaterial = new THREE.MeshBasicMaterial({ color: 0x000000, side: THREE.BackSide }); var skybox = new THREE.Mesh(skyboxGeometry, skyboxMaterial); scene.add(skybox);
此代码与创建多维数据集的代码类似。但这一次的几何形状要大得多。我们还使用了 THREE.MeshBasicMaterial
因为我们不需要照亮天空盒。另外,请注意传递给材料的附加参数:side: THREE.BackSide
。由于立方体将从内部显示,因此我们必须更改绘制的侧面(通常,Three.js 只绘制外墙)。
现在渲染的场景是全黑的。为了解决这个问题,我们必须向场景添加灯光。我们将使用 THREE.PointLight
,它像灯泡一样发出光。在天空盒后添加这些行:
var pointLight = new THREE.PointLight(0xffffff); pointLight.position.set(0, 300, 200); scene.add(pointLight);
如您所见,我们创建了白色的点光源,然后将其位置设置为向上和向后一点,以照亮立方体的正面和顶部。最后,灯光像任何其他对象一样添加到场景中。打开浏览器,您应该会看到一个彩色阴影立方体:
但是立方体仍然很无聊。让我们为其添加一些动作。
现在我们将为场景添加一些运动。让我们让立方体绕 Y 轴旋转。但首先,我们必须改变渲染场景的方式。一次 renderer.render
调用,渲染场景的当前状态一次。因此,即使我们以某种方式为立方体设置动画,我们也不会看到它移动。要改变这一点,我们必须将渲染循环添加到我们的应用程序中。这可以使用专门为此目的创建的 renderAnimationFrame
函数来实现。大多数主要浏览器都支持它,对于那些不支持它的浏览器,Three.js 附带了自己的 polyfill。那么,让我们改变一下:
renderer.render(scene, camera);
对此:
function render() { renderer.render(scene, camera); requestAnimationFrame(render); } render();
实际上,那里没有循环,因为它会冻结浏览器。 requestAnimationFrame
函数的行为有点像 setTimeout
,但它会在浏览器准备就绪时调用该函数。因此,显示的场景没有任何变化,立方体仍然没有移动。让我们解决这个问题。 Three.js自带了THREE.Clock
,可以用来实现对象的平滑动画。首先在render
函数定义之前进行初始化:
var clock = new THREE.Clock;
现在,每次调用 clock.getDelta
时,它都会返回自上次调用以来的时间(以毫秒为单位)。这可以用来旋转立方体,如下所示:
cube.rotation.y -= clock.getDelta();
在 render
函数中的 renderer.render
和 requestAnimationFrame
调用之间添加此行。它只是减去立方体在 Y 轴上旋转所花费的时间(记住它以弧度为单位)来顺时针旋转立方体。现在打开浏览器,您应该看到立方体顺时针平稳旋转。
在本系列的这一部分中,您学习了如何准备场景、添加对象和灯光以及如何为事物设置动画。您可以尝试该应用程序,添加更多或不同的对象、灯光。由你决定。下次我将向您展示如何使用纹理以及如何使用粒子创建一些漂亮的效果。如果遇到任何问题,请不要忘记查看文档。
以上是基礎入門:使用Three.js進行WebGL開發的詳細內容。更多資訊請關注PHP中文網其他相關文章!