将递归渲染的场景显示到平面中
Display recursively rendered scene into a plane
我必须分别渲染 2 个场景并将其中一个作为平面嵌入到另一个场景中。渲染为平面的子场景将使用从相对相机位置计算的视图矩阵和考虑距离的透视矩阵和计算的倾斜来渲染子场景,就好像该场景实际放置在点上一样。
为了描述更详细,这是一个描述更简单情况的图。
(在这种情况下,我们在主视锥体的中心线上有子场景)
使用这些参数很容易计算可视化为红色平截头体的透视矩阵。
但是,我很难解决另一个案例。如果在中心线之外有子场景,我应该倾斜投影矩阵以与外面的场景相对应。
我认为这是一种倾斜透视投影。而且这与渲染镜像非常相似。我如何计算这个透视矩阵?
How do I calculate this perspective matrix?
一个非对称透视(列主序)投影矩阵是这样设置的:
m[16] = [
2*n/(r-l), 0, 0, 0,
0, 2*n/(t-b), 0, 0,
(r+l)/(r-l), (t+b)/(t-b), -(f+n)/(f-n), -1,
0, 0, -2*f*n/(f-n), 0];
其中r
、l
、b
和t
是近平面上到平截头平面的左、右、下、上距离。 n
和 f
是到近平面和远平面的距离。
通常,在框架或库中,像这样的投影矩阵是由名为 frustum.
的函数设置的
例如
OpenGL固定函数管线:glFrustum
正如@Rabbid76 已经指出的那样,这只是一个标准的非对称平截头体。为此,您只需要知道要使用的近平面上矩形的坐标,在 eye-space.
中
不过,还有一个选择:也可以修改现有的投影矩阵。如果您知道矩形在 window 坐标或规范化设备坐标中的位置,这种方法会更容易。您可以简单地将缩放和平移矩阵预乘到 select 原始平截头体的任何子区域。
假设您的视口为 w * h
像素宽,并且从 window 中的 (0,0)
开始。你想创建一个截锥体,它只渲染一个子矩形,它从像素 (x,y)
的左下角开始,宽 a
像素,高 b
像素。
转换为 NDC:
x_ndc = (x / w) * 2 - 1
和 y_ndc = (y / h) * 2 - 1
a_ndc = (a / w) * 2
和 b_ndc = (b / h) * 2
创建一个缩放和平移变换,将范围 [x_ndc, x_ndc+a_ndc]
映射到 [-1,1]
,对于 y:
类似
( 2/a_ndc 0 0 -2*x_ndc/a_ndc-1 )
M = ( 0 2/b_ndc 0 -2*y_ndc/b_ndc-1 )
( 0 0 1 0 )
( 0 0 0 1 )
(请注意,因素 2
将被抵消。我们也可以只使用归一化的,而不是在步骤 1 中转到 [-1,1] NDC space [0,1], 我只是想使用标准的 spaces.)
预乘M
到原始投影矩阵P
:
P' = M * P
请注意,即使我们在 NDC space 中定义了变换,并且 P
在除法之前在剪辑 space 中起作用,数学仍然会计算出来。通过使用齐次坐标,M
的平移部分将相应地缩放 w
。结果矩阵将只是一个一般的非对称投影矩阵。
现在这不会调整原始投影的 near
和 far
裁剪平面。但是您可以通过向 z
坐标添加适当的比例和平移以相同的方式调整它们。
另请注意,使用这种方法,您甚至不仅限于 select 一个轴平行的矩形,您还可以任意旋转或倾斜它,所以基本上,您可以 select window space.
中的任意平行四边形
我必须分别渲染 2 个场景并将其中一个作为平面嵌入到另一个场景中。渲染为平面的子场景将使用从相对相机位置计算的视图矩阵和考虑距离的透视矩阵和计算的倾斜来渲染子场景,就好像该场景实际放置在点上一样。
为了描述更详细,这是一个描述更简单情况的图。
(在这种情况下,我们在主视锥体的中心线上有子场景)
使用这些参数很容易计算可视化为红色平截头体的透视矩阵。
但是,我很难解决另一个案例。如果在中心线之外有子场景,我应该倾斜投影矩阵以与外面的场景相对应。
我认为这是一种倾斜透视投影。而且这与渲染镜像非常相似。我如何计算这个透视矩阵?
How do I calculate this perspective matrix?
一个非对称透视(列主序)投影矩阵是这样设置的:
m[16] = [
2*n/(r-l), 0, 0, 0,
0, 2*n/(t-b), 0, 0,
(r+l)/(r-l), (t+b)/(t-b), -(f+n)/(f-n), -1,
0, 0, -2*f*n/(f-n), 0];
其中r
、l
、b
和t
是近平面上到平截头平面的左、右、下、上距离。 n
和 f
是到近平面和远平面的距离。
通常,在框架或库中,像这样的投影矩阵是由名为 frustum.
的函数设置的例如
OpenGL固定函数管线:
glFrustum
正如@Rabbid76 已经指出的那样,这只是一个标准的非对称平截头体。为此,您只需要知道要使用的近平面上矩形的坐标,在 eye-space.
中不过,还有一个选择:也可以修改现有的投影矩阵。如果您知道矩形在 window 坐标或规范化设备坐标中的位置,这种方法会更容易。您可以简单地将缩放和平移矩阵预乘到 select 原始平截头体的任何子区域。
假设您的视口为 w * h
像素宽,并且从 window 中的 (0,0)
开始。你想创建一个截锥体,它只渲染一个子矩形,它从像素 (x,y)
的左下角开始,宽 a
像素,高 b
像素。
转换为 NDC:
x_ndc = (x / w) * 2 - 1
和y_ndc = (y / h) * 2 - 1
a_ndc = (a / w) * 2
和b_ndc = (b / h) * 2
创建一个缩放和平移变换,将范围
类似[x_ndc, x_ndc+a_ndc]
映射到[-1,1]
,对于 y:( 2/a_ndc 0 0 -2*x_ndc/a_ndc-1 ) M = ( 0 2/b_ndc 0 -2*y_ndc/b_ndc-1 ) ( 0 0 1 0 ) ( 0 0 0 1 )
(请注意,因素
2
将被抵消。我们也可以只使用归一化的,而不是在步骤 1 中转到 [-1,1] NDC space [0,1], 我只是想使用标准的 spaces.)预乘
M
到原始投影矩阵P
:P' = M * P
请注意,即使我们在 NDC space 中定义了变换,并且
P
在除法之前在剪辑 space 中起作用,数学仍然会计算出来。通过使用齐次坐标,M
的平移部分将相应地缩放w
。结果矩阵将只是一个一般的非对称投影矩阵。
现在这不会调整原始投影的 near
和 far
裁剪平面。但是您可以通过向 z
坐标添加适当的比例和平移以相同的方式调整它们。
另请注意,使用这种方法,您甚至不仅限于 select 一个轴平行的矩形,您还可以任意旋转或倾斜它,所以基本上,您可以 select window space.
中的任意平行四边形