使用单应矩阵在后处理中进行平面重投影

时间:2016-07-29 16:22:08

标签: 3d linear-algebra transformation unreal-engine4 homography

让我们解决代理问题 - 您正在查看某些3D场景。现在我用从你眼睛位置完成的渲染来替换场景,所以你看不出任何区别。然后我用墙壁和投影仪替换渲染的图像。我需要的是一个图像,当投影在墙上时,看起来就像你在看场景一样。

看起来像这样: Here's my setup 左侧摄像头是观察者,右侧是投影仪。

我的方法是从观察者位置渲染场景,然后在后期处理中我采样渲染图像以添加失真。

我有一些概念代码证明可以解决我需要调试的一些偏移量,但大多数计算是在像素着色器中完成的,所以它不是最好的解决方案。

在我完成初始版本后,我读到了单应性矩阵,它似乎是满足我需求的正确工具。如果我理解正确,我应该能够计算单应矩阵,然后只将我的屏幕空间UV与其相乘以得到重投影的UV。

很遗憾,我能找到的关于单应性的大部分信息都涉及到我有一些物体的2张照片,手工挑选4对应点对并从中计算矩阵的情况,但我没有这样的点。相反,我知道两个视图的精确变换,它们的垂直和水平FOV和平面,所以我认为这就是我所需要的。

完美的解决方案是使用一些变换来映射[0,1]范围内的图像空间UV,以校正UV以进行纹理采样。你们有没有看到类似的解决方案?

修改

我已经从我的POC实施中截取了屏幕截图: Reprojected with ugly code 我不确定它1:1是否正确,但它显示了我需要的东西。渲染失真,但是当我将这个图像投影到墙上时,这种失真应该会被取消。请看一下桌面 - 它看起来仍然是从侧面渲染而不是从投影仪渲染。当我将这个图像投影到墙上时,它应该看起来像是从你的眼睛位置渲染出来的。

2 个答案:

答案 0 :(得分:3)

我终于找到了解决方案。

在一些关于Homography的文章中,我看到了一个方程式,用两个视口的已知变换来计算H矩阵,但无法使其工作,也许我误解了某些东西或者我的数学错了所以我决定尝试4点方法,但如何自动获得这些点?

鉴于,我将在渲染的后处理阶段使用它,因此主要在屏幕空间中操作我决定将目标视口的角映射到我的源视口。

Projector转换,我得到forward direction并将其旋转一半垂直和水平FOV。结合正值和负值,我可以得到4个向量,对应于我的视口的4个角,在世界空间中计算。

使用Projector位置作为开始,使用4个计算向量作为方向,我可以计算与Plane的4个交点。这些是世界空间点,位于我Plane上,代表what is visible from projector的角落。

有了这4点我用Observer相机投影到它的屏幕空间。

我得到的点是Observer-screen-space点,并且我已经映射了Projector的整个视口我可以使用典型的[0,0],[1,0],[0,1],[1,1]矩形作为Projector-screen-space points。< / p>

这样我就可以使用four corresponding pairs of points来使用我的Homography。

单应

这有点棘手,因为我仍然不完全理解这里的数学,但我已经用过这个:http://www.cse.psu.edu/~rtc12/CSE486/lecture16.pdf 文章,第29页,有一个使用8x8方阵的矩阵方程。链接可能会消失,但您可以在很多地方找到相同的等式,重要的是我使用了8x8版本,但是使用8x9矩阵查看了符号。

这是屏幕:

enter image description here 一般来说,它是一个A * x = b表示法,我们知道A和b并且想要计算x。

对于计算,我使用了Eigen库中的JacobiSVD类。

在我得到8个浮点数后,我可以构建我正在寻找的矩阵的3个行向量。前3个值构成第一个向量,另外3个值构成第2个向量,然后我们只剩下2个值,所以我们附加一个1.0f得到最后一个向量。

我们称之为矩阵H

Pixel Shader

每帧完成所有这些计算Pixel shader非常简单 - 我们只需要使用UV矩阵(但在同构坐标中)转换屏幕空间H向量。

我们得到u,v值并追加1.0得到[u,v,1.0]然后我们将它与H矩阵相乘。我们已将此矩阵作为行向量传递,因此我们可以将[u,v,1.0]向量与3行相加并对结果求和。这样我们得到的结果如[x,y,z],但实际上它意味着[x/z,y/z] 2D向量 - 这是我们正在寻找的UV。现在我只用这个UV对纹理进行采样,我就完成了。

为什么它比Pavel方法更好?

我不需要单独的几何渲染,这在延迟渲染引擎中尤其慢,例如Unreal。

我可以同时使用很少的这样的纹理,所有这些都在不同的平面上。我可以,例如通过几个alpha遮罩和纹理平面,决定我击中哪一个。

通过分别处理屏幕的每一半,我可以重新投影3D并排渲染,以便并排重新投影。

答案 1 :(得分:2)

在我们的discussion中,在UE中未实现梯形失真校正。所以我会想到以下几点:

  1. 使用观察者相机
  2. 创建所需的场景
  3. 在屏幕上的某处添加平面程序!)和相机,相机正在查看平面
  4. 相机设为播放器的主摄像头
  5. 将材质创建为RenderTarget(tutorial)并将 Observer 相机设置为该材质的来源。
  6. 现在您已经设置了在 plane 上渲染场景,而播放器将会看到该平面。

    如果需要模拟梯形失真校正,可以更改 Plane的位置或旋转。 (您可以将这些操作绑定到您的设置GUI等。)由于它是程序,您可以以垂直或水平方式更改大小(和形状)。 (UE docs

    由于你有一个具有恒定UV的平面并且你正在改变它的形状,结果将是该平面上的梯形失真效果,(在正确的平面设置的情况下)将导致与HW投影仪的梯形失真效果相反,从而产生正确的形象。

    对于设置,您只需重置平面上的所有设置(旋转,位置,比例等)并设置另一个材质,最好使用方形 - 您可以轻松查看和这可以帮助您正确修改 Plane 。所以它只是搞乱了投影平面。