视频投影(二维视频投影到三维模型上)

视频投影分享

视频投影

前置知识

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);
希望读者在看完后能提出意见, 点个赞, 鼓励一下, 我们一起进步. 加油 !!
原文地址:https://www.cnblogs.com/xiaxiangx/p/15486863.html