【帶著canvas去流浪(12)】用Three.js製作簡易的MARVEL片頭動畫(上)

来源:https://www.cnblogs.com/dashnowords/archive/2019/07/20/11216540.html
-Advertisement-
Play Games

示例代碼托管在: "http://www.github.com/dashnowords/blogs" 博客園地址: "《大史住在大前端》原創博文目錄" 華為雲社區地址: "【你要的前端打怪升級指南】" [TOC] 一. 大作業說明 通讀完上一篇博文中提及的教程,覺得應該搞個大作業鞏固一下所學的知識, ...


目錄

示例代碼托管在:http://www.github.com/dashnowords/blogs

博客園地址:《大史住在大前端》原創博文目錄

華為雲社區地址:【你要的前端打怪升級指南】

一. 大作業說明

通讀完上一篇博文中提及的教程,覺得應該搞個大作業鞏固一下所學的知識,想起剛上映的漫威宇宙第三階段收官之作《蜘蛛俠·英雄遠征》,於是決定仿一個MARVEL的片頭動畫作為three.js的課後練習,使用的版本是R104版本。本節先來解決視頻貼圖的問題。

二.基本思路

簡易片頭動畫的實現思路如下,除了正常的舞臺元素外,需要背景音樂,使用THREE.AudioLoader就可以從後後臺載入音樂,舞臺中主要的實體元素是MARVEL這幾個字母的立體模型,可以使用THREE.TextGeometry來進行建模(【Three.js繪製字體模型】),它要求先載入字體文件,然後才能實例化,參考官方文檔的實現就可以了。有了字體模型以後,還需要一些影片素材貼在字體模型上,THREE.VideoTexture可以解決這個問題(【Three.js使用VideoTexture實現視頻Video更新紋理】),它可以將HTML中的<video>標簽引入的資源作為錶面紋理通過材料實例的map參數與之關聯在一起,然後貼在幾何體錶面,最後要解決的問題就是鏡頭的變化了,看過漫威電影的同學都知道,片頭動畫最後一部分的畫面先是鏡頭後退,然後MARVEL幾個字母逐漸翻轉過來,這個效果的實現方式很多,可以調整相機參數,也可以調整物體參數,建議自己動手時各種方法都嘗試一下。為了熟悉更多特性,筆者自己在實現中使用正交相機,通過調整正交相機的視場寬度來模擬鏡頭後退動畫(在透視相機下可以直接調整相機的Z軸坐標實現類似的效果),然後通過設置幾何體的位移和旋轉來模擬鏡頭的移動。

三.視頻紋理錶面修複——UV映射

3.1 問題描述

整個大作業中最難處理的就是視頻紋理貼圖的部分,所以本篇先來搞定這個知識點。如果使用THREE.js提供的Geometry基本不會遇到什麼問題,例如上圖中的示例,就將視頻素材貼在了立方體的各個面上,然而當你使用其他帶有一些自定義性質的幾何體實例,比如自己畫了一個shape然後拉伸成為拉伸體,或者本次大作業中需要使用的TextGeometry字體模型時。視頻貼圖就直接失效了。同樣尺寸的立方體,如果用THREE.BoxGeometry來生成實例,錶面就可以直接貼視頻,如果使用shape畫一個矩形再拉伸成同樣尺寸的實體,視頻就無法正常覆蓋在模型錶面,如下圖所示:

仔細看你會發現圖片邊界的地方有發光的條,將細節放大後可以看到下麵的場景:

可以看到,視頻實際上的確是覆蓋在立方體錶面了,但只是占了很小的一塊,所以需要針對這種情況進行模型紋理修複,使視頻可以覆蓋幾何體的單個錶面。

3.2 紋理貼圖的基本原理-UV映射

Three.js中,幾何體是通過的特征構建起來的,如果將一個幾何體實例對象在控制台列印出來,就可以看到存儲端點坐標信息的vertexs和存儲面信息的faces數組。當你構建一個立方體時,會發現它的faces屬性數組中有12個面的信息,因為Three.js中預設使用三角面片來構建幾何體,一個矩形錶面需要用兩個三角面片來構建,(你可以將立方體材料material中傳入 wireframe:true來看到立方體的線框圖),faces數組中每一個面中存儲的是構建這個三角面的3個點的位置信息。

紋理貼圖坐標也稱為UV坐標,它的貼圖原理是這樣的,首先將貼圖素材x軸和y軸的長度以0-1來標記,那麼使用3個坐標範圍在[0~1,0~1]的點就可以在圖形素材中以三角形剪裁出需要的部分,同理使用4個坐標範圍在[0~1,0~1]的點,就可以在圖形素材中以四邊形剪裁出需要的部分,以此類推,如下圖所示:

右圖中白色三角形的三個頂點在歸一化坐標系中的坐標值已經列出,將[0.2,0.2],[0.2,0.8],[0.7,0.2]這三個坐標點信息填充到對應的UV映射數組中後,Three.js就會用這個三角形區域來對一個三角面進行貼圖。由於預設面是三角面,所以我們通過實例化3個THREE.Vector2(x,y)對象來表示從素材中截取的三角形區域,得到了素材後要如何將它與三角面的頂點坐標對應起來呢?這就引出了本節中的關鍵概念——UV映射矩陣

大部分高大上的概念都離不開一個土掉渣的實現,UV映射矩陣也不例外。

由於貼圖素材是三個點,幾何體某個三角面也是有三個頂點,如果不限制索引,那麼就可能存在很多種貼圖結果:

為了保證貼圖素材的方向,它們之間就有存在一個對應關係,否則最後渲染的紋理可能就是倒著的或者旋轉90°的圖像,所以UV映射矩陣中存儲的依然是上例中右圖的三個點,但預設索引和構成幾何體指定面的三個頂點的索引相對應,這就唯一限定了截取錶面到幾何體三角面的貼圖樣式。

3.3 關鍵示例代碼

完整的示例可以從附件或開頭處的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;
}

四.小結

視頻紋理是本例中最難的部分了,下一篇中筆者將構建字體模型,並加入鏡頭轉換,完成整個預期的動畫,敬請關註,也希望感興趣的小伙伴一起交流。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 幾乎所有的編程語言都可以存儲,訪問,修改變數,那在JavaScript中這些變數放在那裡?程式如何找到他們? js被歸類於解釋執行語言,但事實上他也是一門編譯語言,因為他也要編譯,但於傳統的編譯語言不同,他不是提前編譯,編譯結果也不能在分散式系統中進行移植。但js引擎編譯的步驟和傳統的編譯語言非常相 ...
  • 依賴註入通常也是我們所說的ioc模式,今天分享的是用typescript語言實現的ioc模式,這邊用到的主要組件是 reflect-metadata 這個組件可以獲取或者設置元數據信息,它的作用是拿到原數據後進行對象創建類似C#中的反射,先看第一段代碼: 上面的代碼是創建一個類級別的裝飾器,表示凡是 ...
  • 本片文章將為您詳細講解在Vue中,父給子傳值、子給父傳值以及兄弟之間傳值方式! 父傳子;父組件 父傳子;子組件 需要註意的是,父組件傳值給子組件,如果子組件不需要修改父組件的參數,可以使用這種方式!如果子組件要修改父組件中的參數,父組件必須用引用類型的參數傳給子組件! 子傳父;父組件 子傳父;子組件 ...
  • Node.js插件(addons) Node.js 插件是用 C++ 編寫的動態鏈接共用對象,可以使用 require() 函數載入到 Node.js 中,且像普通的 Node.js 模塊一樣被使用。 它們主要用於為運行在 Node.js 中的 JavaScript 與 C/C++ 庫之間提供介面。 ...
  • 1、foreach foreach迴圈對不能使用return來停止迴圈 2、filter item對象就是遍曆數組中的一個元素,includes是es6中的新方法,在search方法中直接返回新數組 3、findIndex 返回true後index就可以獲取到匹配的元素在進行刪除 4、some 如果 ...
  • 摘要: JS引擎開始升級了... 原文: "技術棧中的愛馬仕?Facebook發佈全新JavaScript引擎:Hermes" 作者:Carson_Ho "Fundebug" 經授權轉載,版權歸原作者所有。 前言 目前,用戶的流暢體驗是用戶能長期使用某個移動客戶端應用App的重要指標之一,因此,移動 ...
  • 前端開發工程師不僅僅要掌握一些基礎的美工設計等還要懂得網頁設計類的HTML JavaScript和css,這三種能力缺一不可,雖不要求你特別的精通,但至少要熟練的掌握,能夠運用自己所瞭解的這些技術和知識解決工作中遇到的問題,而不是頻繁的請教別人。 我們常說IT行業技術更新較快,這是事實,但也給能提高 ...
  • 補充:header,fotter,article,section都是div語義化的結果 歡迎評論😀 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...