1

我在世界空间中有几对点,每对点都有不同的深度。我想将这些点投影在视锥体的近平面上,然后重新计算它们的新世界位置。

注意:我要保持透视效果

为此,我将点在 NDC 空间中的位置进行转换。我认为 NDC 空间上具有相同 z 值的每一对点都位于同一平面上,平行于观察方向。因此,如果我将它们的 z 值设置为 -1,它们应该位于近平面上。

现在我有了新的 NDC 位置,我需要它们的世界位置,我通过改变深度丢失了 w 分量,我需要重新计算它。

我找到了这个链接:unproject ndc

它说:

wclip * inverse(mvp) * vec4(ndc.xyz, 1.0f) = 1.0f
wclip = 1.0f / (inverse(mvp) * vec4(ndc.xyz, 1.0f))

我的完整代码:

glm::vec4 homogeneousClipSpaceLeft  = mvp * leftAnchor;
glm::vec4 homogeneousClipSpaceRight = mvp * rightAnchor;

glm::vec3 ndc_left  = homogeneousClipSpaceLeft.xyz() / homogeneousClipSpaceLeft.w;
glm::vec3 ndc_right = homogeneousClipSpaceRight.xyz() / homogeneousClipSpaceRight.w;

ndc_left.z  = -1.0f;
ndc_right.z = -1.0f;

float clipWLeft  = (1.0f / (inverseMVP * glm::vec4(ndc_left, 1.0f)).w);
float clipWRight = (1.0f / (inverseMVP * glm::vec4(ndc_right, 1.0f)).w);

glm::vec3 worldPositionLeft  = clipWLeft * inverseMVP * (glm::vec4(ndc_left, 1.0f));
glm::vec3 worldPositionRight = clipWRight * inverseMVP * (glm::vec4(ndc_right, 1.0f));

它应该在实践中起作用,但我得到了奇怪的结果,我从世界空间中的 2 点开始:

left world position:  -116.463 15.6386 -167.327
right world position: 271.014 15.6386 -167.327
left NDC position: -0.59719 0.0790622 -1
right NDC position: 0.722784 0.0790622 -1
final left position:  31.4092 -9.22973 1251.16
final right position: 31.6823 -9.22981 1251.17
mvp
4.83644 0 0 0
0 4.51071 0 0
0 0 -1.0002 -1
-284.584 41.706 1250.66 1252.41

难道我做错了什么 ?

您是否会推荐这种方式将一对点投影到近平面,透视?

4

1 回答 1

1

如果glm::vec3 ndc_leftglm::vec3 ndc_right是归一化设备坐标,则以下将坐标投影到归一化设备空间中的近平面:

ndc_left.z  = -1.0f;
ndc_right.z = -1.0f;

如果要在笛卡尔坐标中获得归一化设备空间中某个点的模型位置,则必须通过逆模型视图投影矩阵对该点进行变换xyz通过w结果的分量来划分 和分量。不是变换 byinverseMVP给出一个齐次坐标

glm::vec4 wlh = inverseMVP * glm::vec4(ndc_left, 1.0f);
glm::vec4 wrh = inverseMVP * glm::vec4(ndc_right, 1.0f);

glm::vec3 worldPositionLeft  = glm::vec3( wlh.x, wlh.y, wlh.z ) / wlh.w;
glm::vec3 worldPositionRight = glm::vec3( wrh.x, wrh.y, wrh.z ) / wrh.w;


请注意,OpenGL 数学 (GLM)库提供“unproject”操作。见glm::unProject

于 2018-06-07T05:11:00.990 回答