Vulkan深度缓冲位置重建

时间:2017-03-19 05:54:55

标签: graphics rendering shader vulkan

我正在为模板灯着色器重建位置。 这意味着我有光的球面近似的顶点,我可以从中获得世界空间视图矢量(vertexPos - cameraPos)。代码如下所示:

vec3 construct_pos_ws(float depthBufferZ)
{
    vec3 viewRay = normalize(gInVert.vRayWs);
    float viewZDist = dot(gInFrame.eyeZAxis, viewRay);
    vec3 relPoint = viewRay * linearDepth(depthBufferZ) / viewZDist;
    return gInFrame.eye + relPoint;
}

vRayWs:世界空间视图光线(插入vertexPos - vertexshader中的cameraPos) eyeZAxis:眼睛的世界空间z轴(摄像机方向)
viewZDist:深度缓冲区保持与摄像机表面平行的距离,但是我们需要一个距离,这可以解释我们查看对象的角度。

问题在于我使用的线性化功能,基于wikipedia: z-buffering: (我省略了S = 2 ^ d-1,这部分似乎不适用)。

float linearDepth(float z_b) {
    float f = z_far;
    float n = z_near;
    return (-f * n / (z_b (f - n) - f));
}

这不起作用,但使用float n = z_near * 2代替(看似)正确的结果(我只是随机尝试,因为上一个答案看起来接近正确)。

我也尝试过其他线性化,使用维基百科页面上的所有树变体的反转(下面的3),但都没有效果。

1 2 3

实际问题: 那么发生了什么?为什么乘以2似乎给出正确的答案?什么公式用来写入深度缓冲区,因为它似乎没有使用维基百科上的任何公式?

最后,为了完整性,投影矩阵结构如下:

float yScale = 1.0f / tan(fov / 2.0f);
float xScale = yScale / aspect;
float nearmfar = z_near - z_far;
Matrix m = {
    xScale, 0, 0, 0,
    0, yScale, 0, 0,
    0, 0, (z_far + z_near) / nearmfar, -1,
    0, 0, 2 * z_far * z_near / nearmfar, 0
};

另外,我怎么知道它是正确的:

使用更改,并渲染"位置mod 1"给出第一张图像(移动相机时稳定),而原始功能给出第二张图片(移动相机时非常不稳定)。

enter image description here enter image description here

1 个答案:

答案 0 :(得分:1)

Vulkan使用深度范围[0,1](实际上也翻转Y轴),而不是OpenGL' s [-1,1]。您有两种方法可以获得类似OpenGL的行为:

  • 修复着色器中的NDC Z以符合OpenGL方式,就像你现在乘以2一样
  • 或预乘您的投影矩阵与矩阵 #!/usr/bin/env python import sys # function returning compute results def fun_compute(num): return num * num # For writing in a file. # Opened the file in w+ mode with open("./files/sample.txt", "w+") as sys.stdout: print("I am printing fun stuff!") # writing standard string num = 5 for n in range(num): print("fun_compute for - %s" % fun_compute(n))

有关详细信息,请查看https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/。 Vulkan规范(https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/html/vkspec.html#vertexpostproc-clipping)也有更多细节,但没有明确说明。