opengl 世界观投影背后的想法是什么?

piztneat  于 2022-11-04  发布在  其他
关注(0)|答案(2)|浏览(197)

我对光栅化的工作原理有一个相当模糊的理解,所以我完全理解顶点是如何组成3d图像的。我还尝试了模型到世界的投影,尽管我不理解它背后的数学原理(我使用辅助库来乘以矩阵,并有一个图表来指示如何应用不同的变换:旋转,缩放,平移等)。所以我很容易用blender建立一些3d模型,并应用该逻辑为每个对象建立一个世界矩阵。
但是,我在试图想象摄像机矩阵应该如何“查看”一个特定的顶点簇,以及在摄像机矩阵应用于世界矩阵后,物体的世界坐标到底发生了什么?摄像机矩阵看起来像什么,摄像机的“视图轴”如何影响它的矩阵(摄像机可以分别查看z,x,y轴)
我已经设法用各种渲染引擎渲染了一些3d物体(OpenGL,XNA等)但大部分是由于遵循了互联网上的一些指南,或者试图解释YouTube上的一些家伙试图教什么,我仍然在努力获得一个“直观”的感觉,矩阵应该如何工作,每个相机参数,以及相机应该如何改变对象'的世界矩阵

dauxcl2d

dauxcl2d1#

从“世界空间”(Wx,Wy,Wz)到“屏幕空间”(Sx,Sy)有5个步骤:视图,裁剪,投影,透视分割,视口。这是描述得很好here,但一些细节被掩盖了。我将尝试从概念上解释这些步骤。
假设你有一些顶点(我们想要渲染的),一个摄像机(有位置和方向-它指向的方向),和一个屏幕(WIDTHxHEIGHT像素的矩形网格)。
模型矩阵我想您已经了解:最后一个“1.0“(有时称为w分量)允许我们将平移和投影(以及缩放和旋转)表示为单个4x 4矩阵。
视图矩阵(也称为相机矩阵)将所有顶点移动到相机的视点。我认为它分为两个步骤:首先,它平移整个场景(包括摄像机在内的所有顶点),使摄像机在新坐标系中位于原点。其次,它旋转整个场景,使摄像机从原点向-Z轴的方向看。对于here有一个很好的描述。(数学上,旋转首先发生,但是我发现如果我先做平移的话会更容易可视化。)此时,每个顶点都在视图坐标(Vx,Vy,Vz,1.0)中。抓住冰块并移动它,使摄影机位于原点,并沿着-z轴指向(世界上的所有其他对象都将随它们嵌入的冰块一起移动)。
接下来,投影矩阵对照相机具有什么类型的透镜(广角与长焦)进行编码;换句话说,世界上有多少地方将在屏幕上可见。这是描述得很好的here,但以下是它的计算方法:

[    near/width   ][        0        ][         0              ][        0       ]
[        0        ][    near/height  ][         0              ][        0       ]
[        0        ][        0        ][(far+near)/(far-near)   ][        1       ]
[        0        ][        0        ][-(2*near*far)/(far-near)][        0       ]

near = near plane distance (everything closer to the camera than this is clipped).
far  = far plane distance (everything farther from the camera than this is clipped).
width  = the widest object we can see if it is at the near plane.
height = the tallest object we can see if it is at the near plane.

。结果为“剪辑坐标”(Cx,Cy,Cz,Cw=Vz)。请注意,视图空间z坐标(Vz)在裁剪坐标的w坐标中结束(Cw)这个矩阵拉伸了世界,使摄像机的视野现在是上下左右45度。换句话说,如果你从原点看(摄影机位置)沿着-z轴直线(摄像机指向的方向),您将看到屏幕中心的内容,如果您向上{下,左,右}旋转头部,您将看到顶部{下,左,right}。您可以将其可视化为一个金字塔形状,其中摄像机位于金字塔的顶部,摄像机直接向下看金字塔内部。(如果使用近平面和远平面剪切棱锥的顶部和底部,则此形状称为“截锥”-请参见下一段。)Cz值计算使近平面上的顶点具有Cz = -Cw,远平面上的顶点具有Cz = Cw
剪切发生在剪切坐标中(这就是为什么它们被称为剪切坐标)。剪切意味着你用剪刀剪切掉金字塔形状之外的任何东西。你还剪切了离相机太近的所有东西(“近平面”)和离相机太远的所有东西(“远平面”)。请参阅here了解详细信息。
接下来是透视分割。还记得Cw == Vz吗?这是从相机到顶点沿着z轴的距离。(摄像机指向的方向)。我们将每个组件除以此Cw值,以获得归一化投影坐标(NPC)(Nx=Cx/Cw, Ny=Cy/Cw, Nz=Cz/Cw, Nw=Cw/Cw=1.0).所有这些值(NxNyNz)之间的差值-因为我们剪掉了Cx > CwCx < -CwCy > CwCy < -CwCz > CwCz < -Cw,关于这个的更多细节,请看here。透视分割是使距离更远的物体看起来更小的方法。物体离相机越远,Cw(Vz)就越大,分割时它的X和Y坐标就减少得越多。
最后一步是视口变换。NxNyNz(每个范围从-1到1)被转换成像素坐标。例如,Nx=-1在屏幕的左边,而Nx=1在屏幕的右边,所以我们得到Sx = (Nx * WIDTH/2) + (WIDTH/2)或等价的Sx = (Nx+1) * WIDTH。对于Sy类似。你可以认为Sz是将在深度缓冲器中使用的值,因此,它的范围需要从用于近平面(Vz=near)处的顶点的0到用于远平面(Vz=far)处的顶点的深度缓冲器可以保持的最大值(例如,对于24位z缓冲器,2^24= 16777216)。

pkln4tw6

pkln4tw62#

您所称的“摄像机矩阵”听起来像是两个矩阵的组合:视图矩阵和投影矩阵。有可能你只是在讨论其中的一个,但它并不清晰。

**视图矩阵:**视图矩阵是摄像机模型矩阵的 * 逆 *,如果你在世界上绘制它。为了绘制不同的摄像机Angular ,我们实际上在相反的方向移动整个世界-所以只有一个摄像机Angular 。

通常在OpenGL中,相机“实际上”停留在(0,0,0),并沿着Z轴的正方向(朝向0,0,+∞)观看。您可以对投影矩阵进行旋转,以获得不同的方向,但为什么要这样做呢?在视图矩阵中进行所有旋转,您的生活会更简单。
例如,如果你想让你的摄像头在(0,3,0),而不是把摄像头向上移动3个单位,我们把它留在(0,0,0),把整个世界向下移动3个单位。如果你想让它旋转90度,我们实际上把世界向相反的方向旋转90度。世界不会介意--它只是电脑里的数字--它不会头晕。
我们只在渲染时才这样做。例如,所有的游戏物理计算 * 都不是 * 在旋转世界中完成的。当我们旋转摄像头时,世界中物体的坐标不会改变--除非在渲染系统内部。通常,我们告诉GPU物体的正常世界坐标,然后让GPU使用矩阵为我们移动和旋转它们。

**投影矩阵:**您知道 * 视锥 * 吗?您可能以前见过这个形状:(credit)(英文)

在截棱锥形状(截锥体)内的所有内容都显示在屏幕上。
只是计算机实际上并不是呈现一个截锥,而是呈现一个立方体,视图矩阵将截锥转换成立方体。
如果你熟悉线性代数,你可能会注意到一个3D矩阵不能把一个立方体变成一个截锥。通过使用使w依赖于z的视图矩阵,远处点的坐标被除以更大的数,所以它们被推向屏幕的中间--这就是立方体如何变成平截头体的原因。
你不一定要有一个平截头体--这是你用透视投影得到的。你也可以使用正投影,它把一个立方体变成一个立方体,只要不改变w。
除非你想自己做一大堆数学运算,否则我建议你只使用库函数来生成投影矩阵。
如果你把顶点乘以一行中的几个矩阵,那么把它们合并成一个矩阵,然后把顶点乘以合并后的矩阵会更有效--因此你经常会看到MVP、MV和VP矩阵的使用。(M =模型矩阵--我想这和你所说的世界矩阵是一样的)

相关问题