转换为 NDC,计算并转换回世界空间

Transform to NDC, calculate and transform back to worldspace

我在将世界坐标移动到 ndc 坐标时遇到问题,而不是用它计算一些东西并将其移回着色器中。

代码如下所示:

vec3 testFunc(vec3 pos, vec3 dir){
    //pos and dir are in worldspace, convert to NDC
    vec4 NDC_dir = MVP * vec4(dir,0);
    vec4 NDC_pos = MVP * vec4(pos,1);
    NDC_dir /= NDC_dir.w;
    NDC_pos /= NDC_pos.w;

    //... do some caclulations => get newPos in NDC 

    //Transform newPos back to worldspace
    vec4 WS_newPos = inverse(MVP) * vec4(newPos,1);
    return WS_newPos.xyz / Ws_newPos.w;
}

我在测试时发现,虽然 NDC_dir.x 和 NDC_dir.y 似乎是合理的,但 NDC_dir.w 和 NDC_dir.z 总是几乎相等。因此,当除以 "w" 时,z 值始终约为 1。我认为这不应该是正确的? (与 NDC_pos 相同)。

另一方面,当我将 "pos" 转换为 NDC,然后将其转换回世界空间(无需任何计算)时,它似乎得到了原始点,这实际上意味着转换是正确的。

谁能告诉我我是否做错了什么,如果没有,为什么 z 值总是 1?

更新: 这有点尴尬。我有两个问题:1.一个是@Arne指出的方向问题。另一个只是我这边的缩放问题。我有一个非常小的近端夹子和一个大的远端夹子。由于该值是对数的,我只是迈出了两大步来实现 z 值实际上确实从 -1 变为 1。

What I found when testing is, that whilte the NDC_dir.x and NDC_dir.y seem to be reasonable, the NDC_dir.w and NDC_dir.z are always almost equal. Therefor when dividing by "w" the z-Value is always about 1. I dont think this is how it should be right? (Same for NDC_pos).

其实是的,应该是这样的。如果您的输入格式为 {x,y,z,0},那么它将被解释为在 {x,y,z} 方向上无限远的一个点。因此深度分量应该总是最远的,如果可见的话。顺便说一句,无限远的点仍然是平移不变的

但是你应该知道,无限远的点在NDC中可能不是你想要的。

3D 中的矢量 space 对于平移是不变的,它只是保持相同的矢量,因为矢量只有方向,没有位置。这在扭曲的NDC中是不可能的。

如果要变换一个向量,最好变换两个点,然后再在NDC中取差。但是你应该知道你的结果取决于位置。