示例代碼託管在: http://www.github.com/dashnowords/blogs博客園地址:《大史住在大前端》原創博文目錄html
華爲雲社區地址:【你要的前端打怪升級指南】前端
動圖效果可點擊查看:gif動圖效果示例git
通讀完上一篇博文中說起的教程,以爲應該搞個大做業鞏固一下所學的知識,想起剛上映的漫威宇宙第三階段收官之做《蜘蛛俠·英雄遠征》,因而決定仿一個MARVEL
的片頭動畫做爲three.js
的課後練習,使用的版本是R104
版本。本節先來解決視頻貼圖的問題。github
簡易片頭動畫的實現思路以下,除了正常的舞臺元素外,須要背景音樂,使用THREE.AudioLoader
就能夠從後後臺加載音樂,舞臺中主要的實體元素是MARVEL
這幾個字母的立體模型,可使用THREE.TextGeometry
來進行建模(【Three.js繪製字體模型】),它要求先載入字體文件,而後才能實例化,參考官方文檔的實現就能夠了。有了字體模型之後,還須要一些影片素材貼在字體模型上,THREE.VideoTexture
能夠解決這個問題(【Three.js使用VideoTexture實現視頻Video更新紋理】),它能夠將HTML中的<video>
標籤引入的資源做爲表面紋理經過材料實例的map
參數與之關聯在一塊兒,而後貼在幾何體表面,最後要解決的問題就是鏡頭的變化了,看過漫威電影的同窗都知道,片頭動畫最後一部分的畫面先是鏡頭後退,而後MARVEL
幾個字母逐漸翻轉過來,這個效果的實現方式不少,能夠調整相機參數,也能夠調整物體參數,建議本身動手時各類方法都嘗試一下。爲了熟悉更多特性,筆者本身在實現中使用正交相機,經過調整正交相機的視場寬度來模擬鏡頭後退動畫(在透視相機下能夠直接調整相機的Z軸座標實現相似的效果),而後經過設置幾何體的位移和旋轉來模擬鏡頭的移動。express
整個大做業中最難處理的就是視頻紋理貼圖的部分,因此本篇先來搞定這個知識點。若是使用THREE.js
提供的Geometry
基本不會遇到什麼問題,例如上圖中的示例,就將視頻素材貼在了立方體的各個面上,然而當你使用其餘帶有一些自定義性質的幾何體實例,好比本身畫了一個shape
而後拉伸成爲拉伸體
,或者本次大做業中須要使用的TextGeometry
字體模型時。視頻貼圖就直接失效了。一樣尺寸的立方體,若是用THREE.BoxGeometry
來生成實例,表面就能夠直接貼視頻,若是使用shape
畫一個矩形再拉伸成一樣尺寸的實體,視頻就沒法正常覆蓋在模型表面,以下圖所示:npm
仔細看你會發現圖片邊界的地方有發光的條,將細節放大後能夠看到下面的場景:canvas
能夠看到,視頻實際上的確是覆蓋在立方體表面了,但只是佔了很小的一塊,因此須要針對這種狀況進行模型紋理修復,使視頻能夠覆蓋幾何體的單個表面。數組
在Three.js
中,幾何體是經過點
和面
的特徵構建起來的,若是將一個幾何體實例對象在控制檯打印出來,就能夠看到存儲端點座標信息的vertexs
和存儲面信息的faces
數組。當你構建一個立方體時,會發現它的faces
屬性數組中有12個面的信息,由於Three.js
中默認使用三角面片來構建幾何體,一個矩形表面須要用兩個三角面片來構建,(你能夠將立方體材料material
中傳入 wireframe:true
來看到立方體的線框圖),faces
數組中每個面中存儲的是構建這個三角面的3個點的位置信息。app
紋理貼圖座標也稱爲UV
座標,它的貼圖原理是這樣的,首先將貼圖素材x軸和y軸的長度以0-1來標記,那麼使用3個座標範圍在[0~1,0~1]的點就能夠在圖形素材中以三角形剪裁出須要的部分,同理使用4個座標範圍在[0~1,0~1]的點,就能夠在圖形素材中以四邊形剪裁出須要的部分,以此類推,以下圖所示:ide
右圖中白色三角形的三個頂點在歸一化座標系中的座標值已經列出,將[0.2,0.2],[0.2,0.8],[0.7,0.2]
這三個座標點信息填充到對應的UV
映射數組中後,Three.js
就會用這個三角形區域來對一個三角面進行貼圖。因爲默認面是三角面,因此咱們經過實例化3個THREE.Vector2(x,y)
對象來表示從素材中截取的三角形區域,獲得了素材後要如何將它與三角面的頂點座標對應起來呢?這就引出了本節中的關鍵概念——UV映射矩陣。
大部分高大上的概念都離不開一個土掉渣的實現,
UV映射矩陣
也不例外。
因爲貼圖素材是三個點,幾何體某個三角面也是有三個頂點,若是不限制索引,那麼就可能存在不少種貼圖結果:
爲了保證貼圖素材的方向,它們之間就有存在一個對應關係,不然最後渲染的紋理可能就是倒着的或者旋轉90°的圖像,因此UV映射矩陣
中存儲的依然是上例中右圖的三個點,但默認索引和構成幾何體指定面的三個頂點的索引相對應,這就惟一限定了截取表面到幾何體三角面的貼圖樣式。
完整的示例能夠從附件或開頭處的github
代碼倉中獲取,示例是一個express
工程,npm install
裝一下依賴,跑起來以後訪問localhost:3333
就能夠看到。
//重構UV Mapping function rebuildUVMapping() { //在紋理素材上標記關鍵點 let pos = [ new THREE.Vector2(0,0.1), new THREE.Vector2(1,0.1), new THREE.Vector2(1,0.9), new THREE.Vector2(0,0.9), ] //uv映射的紋理存放在幾何體實例的下面這個屬性中 let uvs = geometry.faceVertexUvs[0]; //背面 //生成網格時材料能夠傳數組,materialIndex能夠爲不一樣面指定不一樣的材質,本例中對應不一樣的視頻片斷 geometry.faces[0].materialIndex = 4; geometry.faces[1].materialIndex = 4; //重構UV映射關係矩陣 uvs[0] = [pos[1], pos[0], pos[3]]; uvs[1] = [pos[3], pos[2], pos[1]]; //正面 geometry.faces[2].materialIndex = 0; geometry.faces[3].materialIndex = 0; uvs[2] = [pos[3], pos[0], pos[1]]; uvs[3] = [pos[1], pos[2], pos[3]]; //標記uv映射是可更新的 geometry.uvsNeedUpdate = true; }
視頻紋理是本例中最難的部分了,下一篇中筆者將構建字體模型,並加入鏡頭轉換,完成整個預期的動畫,敬請關注,也但願感興趣的小夥伴一塊兒交流。