Graphics Vulkan深度缓冲区位置重建

Graphics Vulkan深度缓冲区位置重建,graphics,rendering,shader,vulkan,Graphics,Rendering,Shader,Vulkan,我正在重建模具灯光着色器的位置。 这意味着我有灯光的球形近似顶点,从中我可以得到世界空间视图向量(Vertexos-cameraPos)。代码如下所示: vec3 construct_pos_ws(float depthBufferZ) { vec3 viewRay = normalize(gInVert.vRayWs); float viewZDist = dot(gInFrame.eyeZAxis, viewRay); vec3 relPoint = viewRay

我正在重建模具灯光着色器的位置。 这意味着我有灯光的球形近似顶点,从中我可以得到世界空间视图向量(Vertexos-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;
}
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
};
vRayWs:世界空间视图光线(在vertexshader中插值顶点曝光-cameraPos) eyeZAxis:眼睛的世界空间z轴(相机方向)
viewZDist:深度缓冲区保持平行于相机表面的距离,但我们需要一个距离,这说明了我们查看对象的角度


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

这不起作用,但使用
float n=z_near*2
会给出(似乎)正确的结果(我只是随机尝试了一下,因为前面的答案看起来几乎正确)


我也尝试过其他线性化,使用维基百科页面上所有树变量的倒数(下面的3个),但没有一个有效


实际问题: 那么到底发生了什么?为什么2的乘法似乎给出了正确的答案?vulkan使用什么公式写入深度缓冲区,因为它似乎没有使用wikipedia上的任何公式


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

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;
}
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
};
此外,我如何知道它是正确的:

使用更改并渲染“position mod 1”将生成第一张图像(移动相机时稳定),而原始功能将生成第二张图像(移动相机时非常不稳定)


Vulkan使用[0,1]的深度范围(实际上还翻转了Y轴),而不是OpenGL的[-1,1]。要获得类似OpenGL的行为,有两个选项:

  • 修复着色器中的NDC Z,使其符合OpenGL的方式,就像您现在通过乘以2所做的那样
  • 或者将投影矩阵与矩阵预乘
    
    1.0   0.0   0.0   0.0
    0.0   -1.0  0.0   0.0
    0.0   0.0   0.5   0.5
    0.0   0.0   0.0   1.0
    

请查看以了解更多详细信息。Vulkan规范()也有更多的细节,尽管没有明确说明。

我必须再次检查,但我猜这是因为NDC的Z从0到1,而不是从-1到1。谢谢,他的说明帮助了很多,但仍然存在一些奇怪的问题。在[1,1]处使用该矩阵而不求反确实有效,但随后会得到倒y。然而,由于这种否定,我无法产生任何结果,屏幕保持黑色,好像所有东西都被丢弃了。那么你的相机可能只是朝向错误的方向吗?另外,有点相关,baldurk的renderdoc()是调试此类问题的一个非常棒的工具。也许它能帮你弄清楚到底发生了什么。我来看看,在我弄清楚颠倒的问题之前,我可以把上方向向量指向下,然后它也能工作。