【问题标题】:How to unproject a point on screen to object space coordinates in vulkan?如何在vulkan中将屏幕上的点取消投影到对象空间坐标?
【发布时间】:2019-08-04 04:23:34
【问题描述】:

我需要能够使用 Vulkan 将屏幕像素取消投影到对象空间中,但是我的数学在某个地方出错了。

这是今天的着色器供参考:

void main()
{
    //the depth of this pixel is between 0 and 1
    vec4 obj_space = vec4( float(gl_FragCoord.x)/ubo.screen_width, float(gl_FragCoord.y)/ubo.screen_height, gl_FragCoord.z, 1.0f);
    //this puts us in normalized device coordinates [-1,1 ] range
    obj_space.xy = ( obj_space.xy * 2.0f ) -1.0f;

    //this two lines will put is in object space coordinates
    //mvp_inverse is derived from this in the c++ side: 
    //glm::inverse(app.three_d_camera->get_projection_matrix() * app.three_d_camera->view_matrix * model);

    obj_space = ubo.mvp_inverse * obj_space;
    obj_space.xyz /= obj_space.w;


    //the resulting position here is wrong
    out_color = obj_space;
}

当我用颜色输出位置时,颜色是关闭的。我知道我可以简单地将对象空间位置从顶点着色器传递到片段着色器,但我想了解为什么我的数学不起作用,这将帮助我理解 Vulkan,也许自己也学一点数学。

谢谢!

【问题讨论】:

  • box_space_pos 应该是 obj_space 变量,这是一个错字。对不起,伙计们,问题还是一样。
  • 您可以编辑问题。
  • 数学基本上与 API 无关。您是否在普通的 C 代码中尝试过(更容易调试)?还是(上帝保佑)在纸上?您是否还测试过 MVP 矩阵是否合理?

标签: projection vulkan


【解决方案1】:

我不完全确定您的问题是什么,但让我们看看潜在的问题。

记住,vulkan 剪辑空间是:

  • 正 y = 向下
  • 正 x = 右,
  • 正 z = out,
  • 位于屏幕中间。

此外,尽管 OpenGL 的 GLSL 文档说它在 vulkan gl_FragCoord is centered at the top left corner 中位于左下角居中。

在这一步:

obj_space.xy = ( obj_space.xy * 2.0f ) -1.0f;

obj_space 现在是:

  • 左x:-1.0
  • 右 x : 1.0
  • 顶部 y = -1.0
  • 底部 y = 1.0
  • 出 z = 1.0
  • 后z = 0

我几乎完全确定您并不是说您的对象空间的顶部 Y 为负数。 y 从上到下增加的原因是图像和纹理,它们在 CPU 上的排序方式相同,现在在 vulkan 中排序。

其他一些注意事项:

你声称你的逆是从 glm::inverse 派生的:

glm::inverse(app.three_d_camera->get_projection_matrix() * app.three_d_camera->view_matrix * model);

但是 GLM 使用 OpenGL 表示法来表示矩阵尺寸和惯用手,除非您强制它使用正确的坐标系,否则它将假定右手正 Y 向上,z 负向外。您需要包含以下 #defines 才能正常工作(或物理更改您的计算以适应此情况)。

#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#define GLM_FORCE_LEFT_HANDED

此外,您还需要修改矩阵以考虑负 Y 方向。这是我过去如何处理此问题的示例(直接修改透视矩阵):

ubo.model = glm::translate(glm::mat4(1.0f), glm::vec3(pos_x,pos_y,pos_z));
ubo.model *= glm::rotate(glm::mat4(1.0f), time * glm::radians(0.0f), glm::vec3(0.0f, 0.0f, 1.0f));
ubo.view = glm::lookAt(glm::vec3(0.0f, 0.0f, -10.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
ubo.proj = glm::perspective(glm::radians(45.0f), swapChainExtent.width / (float) swapChainExtent.height, 0.1f, 100.0f);
ubo.proj[1][1] *= -1; // makes the y axis projected to the same as vulkans

【讨论】:

  • "后 z = -1.0"。他不修改z。应该是0。也不确定y=-1 top 会有什么问题。如果他的原始矩阵首先是正确的,那么它应该考虑到他选择的任何类型的世界空间,不是吗?
  • @krOoze 我们不知道他的原始矩阵是否正确,如果是 -y 的东西不会有问题,我假设这个人甚至可能不知道这是一个问题需要在某个时候解决。
  • @krOoze 另外我的意图是显示方向,而不是真正的界限,但我可以看到这是多么令人困惑,所以我将其替换为零。
  • 当然,因此我在 cmets 中提出了问题。尽管可能发生的更糟糕的情况是东西会颠倒过来。但无论如何都应该取消投影回原始向量。
  • @krOoze 请记住,这个人甚至没有在屏幕上绘制对象,它们的“颜色”是错误的,倒置的 y 轴肯定会导致“不正确”的颜色。我的意思是,一切都可能是正确的,他们只是不明白如何解释他们自己的配色方案,但至少有人认为这是一个好问题,所以我已经尽我所能回答了他们情况。
猜你喜欢
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
  • 2016-07-18
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多