影片投影(二維影片投影到三維模型上)

影片投影分享

影片投影

前置知識

GPU 將影像渲染到螢幕上

image-20211030114355325

物體與紋理

影片投影:將影片作為圖片式貼在模型上

影片投影兩個關鍵元素,模型影片材質

物體組成

在虛擬世界中,所有物體由三角面構成(也有用四角形的,主流是三角形)

一般模型都是一張皮,內部是空心的

簡單模型

msedge_hjPLBGhDMF

紋理映射

將一張圖片貼在模型上,模型就是一張皮,可以看成是地球儀錶面平鋪為世界地圖,模型上每一個頂點對應紋理上的一個位置,頂點間用插值計算紋理顏色,紋理坐標使用的是百分比

gFUL2HEAzV

將紋理圖片(2k像素)貼在一個平面上

msedge_2evhu3Pn4c

將紋理坐標和頂點坐標一一對應,剩下部分利用插值計算

msedge_WWD6rYO4y5

隨著取樣點變少,影像失真程度越高,當取樣點變成像素時,便可以將紋理影像完全貼在物體表面(自動過程),程式需要做的,將紋理影像的關鍵點坐標與物體點坐標對應上

msedge_bCWXJxwftG

在三維世界中,物體就是由自己所有的頂點以及每個頂點表示的顏色組成,顏色可以是自定義,也可以從圖片材質中獲取

3D 轉換

我們能看到一個三維物體,我們需要四種元素,第一:眼睛;第二:大腦,對眼睛接受的數據進行處理;第三:三維世界,我們身處於三維世界中,比如地球,那我們就能描述我們的位置;第四:物體,否則看到就是透明空氣了。

重新定義這四個概念,眼睛—相機,大腦—渲染器,三維世界—場景,物體—物體

看到場景物體的流程

1. 存在一個物體

物體本身具有頂點坐標(原始坐標數據:position),以及自己的移動(模型矩陣:modelMatrix

msedge_BB2k5cgwz3

茶壺建模完成後會有自己的頂點數據,以及每個頂點對應的顏色,茶壺可以自己進行旋轉、移動和縮放,這三類操作會產生模型矩陣,用於計算。將茶壺自己元素坐標資訊與模型矩陣加入到程式中,就相當於將茶壺經過轉換,重置了茶壺上的每個頂點位置。

2. 存在一個相機,用於觀察物體

相機位置、相機朝向和相機向上方向用來唯一確定相機具體方位,由這三個資訊可組成視圖矩陣(viewMatrix

msedge_pABRWSTEKz

將視圖矩陣加入程式中,就相當於鎖定人眼了。

3. 根據相機參數的不同,得到不同的結構

比如:一個眼睛大,看得遠,一個眼睛小,看得近,一個近視眼,一個遠視眼。相機屬性構成了投影矩陣 (projectionMatrix)

msedge_NrCHrJpzw9

將投影矩陣加入到程式中,得到的就是從一個具體的人眼看到的三維世界

XOe1zeBfBH

4. 最終得到規範立方體(canonical view volume)

在立方體內的物體就是我們看到的物體,立方體外的都可以剔除掉,那些都是視野外的。於此同時,由於視圖矩陣和模型矩陣的加入,相機位於原點,看向 z 負軸。(規範立方體 (-1,-1,-1)到(1,1,1))

總結剛剛的過程,最終得到的物體坐標為

// projMatrix 投影矩陣,viewMatrix 視圖矩陣,modelMatrix 模型矩陣
gl_position = projMatrix * viewMatrix * modelMatrix * position;

5. 由最終三維場景到二維影像

規範立方體得到了,z 坐標 從 1 到 -1 ,z 坐標代表這個物體深度。好似從前往後發射射線,碰到的第一個點就將其顏色賦值在平面上,最終形成二維圖片

圖片

影片投影分析

關鍵:將影片紋理與模型上對應的頂點一一對應起來

1. 建立與現實一致的虛擬世界

模型比例與現實保持一致;投影的相機所處位置,參數,朝向,向上方向保持一致

Snipaste_2021-10-30_16-36-44

2. 獲取影片紋理,分析投影過程

目前整個場景有兩個相機,一個是主相機,就是上帝視角的這個相機;另一個是用作投影的相機,這裡就叫投影相機。

首先,先獲取到影片作為紋理對象,可以直接將影片看作一張圖片,這裡叫投影圖,投影圖就是投影相機拍出來的,因此,投影相機看到的二維影像就是投影圖

現在我們可以得到三個圖

  1. 上帝視角圖
  2. 投影相機視角圖
  3. 影片中的投影圖

其中,投影相機視角圖 = 影片投影圖 (等式 1),2 = 3

因此,現在我們求出投影相機與模型產生的交點,並且根據 「等式1」 找到這個點的顏色,並將顏色賦值上去,最終便得到影片投影效果

投影相機看到的視角圖

投影相機

真實世界攝像機的視角圖

影片圖

一一對應上,最終完成

3. 關鍵程式碼解析

  1. 頂點處理
// 獲取投影相機看到的標準立方體
c_Position = u_ProjectionMatrix * u_ViewMatrix * modelMatrix * vec4( position, 1.0 );

// 遍歷模型上的每個點
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  1. 顏色處理
// 投影相機計算出的 c_Position 處於 (-1,-1,-1)到(1,1,1)標準立方體中,z 是深度,x,y需要轉換區間到 0-1(紋理坐標)
vec4 c_Uv4 =  c_Position / c_Position.w;
c_Uv4.xyz = vec3( c_Uv4.xyz + 1.0) / 2.0;

// 根據投影相機看到的頂點找影片圖的對應位置的像素並賦值
gl_FragColor = texture2D(mapPicture, c_Uv4.xy);