本文來自網易雲社區css
做者:唐釗html
那是在一個毫無徵兆的下午,我還沉浸在 vue 的世界中,忽然編輯跑過來講N的新官網想作一些3D全景的東西,一開始其實個人心裏是拒絕的,一是沒怎麼實質性作過 WEBGL 的東西,只是組內 mini 項目的時候看了看基礎的內容,再者當時也很忙,感受這東西聽起來就很複雜,隨着項目開發結束在此寫下這篇文章,記錄一下本身在開發過程當中遇到的問題和解決的思路以供備忘。前端
開發使用: WS、threejs-r82,3DsMax;vue
最初遇到的問題:其實3D 全景其實並不必定非要使用 webgl,css3一樣能夠作到,可是考慮到後續要增長模型動畫的問題,因此不得不用 webgl 了。那麼 webgl 究竟是什麼呢?WebGL是一種3D繪圖標準,這種繪圖技術標準容許把JavaScript和OpenGL ES 2.0結合在一塊兒,經過增長OpenGL ES 2.0的一個JavaScript綁定,WebGL能夠爲HTML5 Canvas提供硬件3D加速渲染,這樣Web開發人員就能夠藉助系統顯卡來在瀏覽器裏更流暢地展現3D場景和模型了,還能建立複雜的導航和數據視覺化。因爲webgl是基於OpenGL和JavaScript技術結合,而OpenGL與微軟DirectX存在着競爭關係,並且微軟自身也開發了Silverlight插件,與webgl實際上是相似的,因此微軟對webgl技術並不支持。可是最新的 IE11和 edge 瀏覽器是 ok 的。因此一開始的難點就在於怎麼去構建這個3D的場景和內部的模型動畫等。(特此說明:本文不會講解 threejs 的基本知識,因此如下內容須要必定的 webgl 基礎,見下面連接)css3
先安利一款 chrome 的 threeJs 插件 https://chrome.google.com/webstore/detail/threejs-inspector/dnhjfclbfhcbcdfpjaeacomhbdfjbebi 賊好用!github
整個場景分爲3大部分,最外層的天空,中間的建築,以及內部的各類燈籠,蝴蝶,魚等等模型動畫,因此咱們須要分佈考慮各個場景如何構建,首先是最外層的天空和建築,由於 N 項目組有特殊的場景編輯工具,能夠很是方便的輸出場景的魚眼圖,因此我打算利用這個魚眼圖直接構建一個球形,也就是構建了2個球形,一內一外,分別爲天空和建築,讓天空的球形作 圍繞 Y 軸的TWEEN動畫,造成天空在轉動的效果,同時內部的建築使用 png 貼圖,對材質增長 transparent:true 的選項,讓天空可見,若是你不加透明度這個選項,png 貼圖的透明部分是會變成白色的。web
外面兩層的球形模型很好搭建,接下來的問題就來了,如何作模型動畫,由於你們都歷來沒作過,因此一開始我是束手無策,由於這個玩意壓根不知道從何下手,後面瞭解到模型動畫須要由專門的動畫師去建模而後貼圖而且製做動畫,導出相應的文件由前端放進場景裏面去,因此我就興致沖沖的讓遊戲那邊的動畫導出 dae 文件給我,爲何導出 dae 呢,由於我看 threejs 的示例裏面是用的 dae 的模型,因此當時想固然的認爲只要導出 dae 就能放進去了,事實證實,我仍是 too young too simple. 爲何,我看着官方的示例那天下午一遍一遍的問本身,爲何個人就不行,難道我導出的模型就不是模型,因而我又是一頓查資料,那一刻,搜狗百度谷歌全上陣,但是依舊苦苦無果,打算去研究官方的 dae 文件,能夠導入max發現全亂掉了,根本無法下手,終於在次日中午快要吃飯的時候在一個 max 論壇發現一個哥兒們的一段話讓咱們恍然大悟,他的原話我記不清了,不過中心意思就一個:web 所用的 dae 文件須要模型所有塌陷之後從新撘骨骼,而且不能用鏡像骨骼,我那個去,敲代碼的我確定不懂這是什麼意思啊,可是從這裏面確定說明了直接導出的 dae 文件就是有問題,因而我去問了咱們組的動畫師,她看了看說:「原來是這樣,那我試試吧」。因而咱們的動畫師開始了各類嘗試,給了我各類文件進行導入,一開始模型是能夠正常導入了,可是動畫老是不對,要麼骨骼信息各類丟失,要麼就是各類奇葩的抖動頻率,咱們再一次被打擊了,後面再查文檔時發現 R7X 以上的動畫調用和 R6X 的發生了變化,因而我進行了必定的代碼更改,oh my god 終於在場景裏面看到了一個活的模型了,接着咱們又開始研究貼圖和自發光問題。chrome
總的來講上面這一部分是當時最打擊信心以及最費時間的一部分了,由於吃螃蟹老是不容易的,不事後續發現還有不少其餘的問題等着本身,首先是模型因爲沒有燈光,顯得很暗淡,因此須要增長一個光源,因爲場景裏面的背景是一張圖片,若是增長一個照射範圍很大的光源勢必會影響到圖片,會改變圖片的曝光,因此只能去研究模型的自發光,後來發現仍是比較簡單,須要動畫師給我一個合適的色值,設置自身的 color 和 emissive 便可。segmentfault
場景中的花瓣採用的是粒子發射器生成的隨機粒子,添加花瓣的紋理,花瓣的降落由隨機數生成在一個合適的值。可是因爲粒子自己是沒有 XYZ 的,因此無法作旋轉。
場景中的貼圖因爲 webgl 的同源策略,因此不能在跨域的狀況下使用貼圖。
場景中的字體問題,在 threejs 中默認是不支持中文字體的,只能使用英文,緣由嘛,你懂得,中文字符太多了,因此若是項目中須要在場景中使用中文,能夠參考該文章 地址,另外若是不是非得使用最好仍是用英文吧,由於這加載的都是流量啊。
最後是場景內的鼠標事件,若是你沒有作過你必定會一臉懵逼,由於這裏面根本沒有什麼 click 事件,就好比一個鼠標移入到可點擊物體上變成手型都不知道怎麼搞,而後找資料,知道了ThreeJS提供了一個 raycaster的API用於返回用戶光標所在位置的全部3維元素,它的實現原理是在屏幕上某個二維座標點與相機位置和視角造成的向量方向上投射一條射線,返回與射線相交的全部三維物體的集合,集合的第一個物體爲距離相機最近的物體,最後一個則爲離相機最遠的。當使用拾取器去獲取用戶點擊的物體時,須要事先將全部可參與用戶交互的三維物體放到一個集合裏。在建立拾取器後獲取兩個集合的交集,即當前用戶在屏幕點擊的位置上全部被設置爲可被選擇的物體,第一個便可視爲用戶直接點擊的物體。因此在場景內部的全部交互都只能經過射線的方式去完成,固然 github 上也有一些封裝的場景物體點擊的事件庫,其原理也是基於射線。可是因爲上面提到的 png 貼圖問題,我讓動畫師將交互對象也作成了動畫模型,而後我就發現爲何個人射線發射過去沒有交集了,一開始覺得是我鼠標有問題,可是後來重現了幾回發現確實是動畫模型就不行,普通的 mesh 就 OK,那麼問題就確定在動畫上面了,去 github 上找了好久看到了有人和我有一樣的問題。 傳送門,回答者說skinnedMesh 已經從射線集合中移除了,老版本曾經有支持,因此我只能想一想其餘的方法,最後採用了在動畫模型前面添加了一個普通的 mesh,將其透明掉,這樣射線就有了交集。能完美的點擊到了物體。
至此整個場景內部的物件基本上交互的功能和動畫功能都 OK 了,可是還有不少以前研究的內容最後沒有放到整個項目中去,好比攝像機的移動旋轉,場景更濃厚的氣氛渲染,一是受限於web 瀏覽器,說實話 web 上搞3D 原本就不是太好,又卡消耗又大,而是確實時間也不長,前先後後全部的算滿也才26天,這其中還要花不少時間整合雙端的新聞發佈系統,還要作其餘的整合適配等等,因此後面空了仍是要再看看 threeJs 的東西,加強一下本身的技術棧,同時更深刻的理解 webgl。
網易雲免費體驗館,0成本體驗20+款雲產品!
更多網易研發、產品、運營經驗分享請訪問網易雲社區
相關文章:
【推薦】 知物由學 | 這些企業大佬如何看待2018年的安全形勢?
【推薦】 一行代碼搞定Dubbo接口調用
【推薦】 4月第4周業務風控關注 | 網絡犯罪經濟每一年1.5萬億美圓 GDP居全球第12位