gpt4 book ai didi

opengl - 来自对数深度缓冲区的世界空间位置

转载 作者:行者123 更新时间:2023-12-04 08:51:13 24 4
gpt4 key购买 nike

将我当前的延迟渲染器更改为使用 logarithmic depth buffer 后对于我的生活,我无法解决如何从深度缓冲区值重建世界空间深度。

当我编写了 OpenGL 默认 z/w 深度时,我可以通过从窗口空间转换到 NDC 空间然后执行逆透视变换来轻松计算该值。

我在第二遍片段着色器中完成了这一切:

uniform sampler2D depth_tex;

uniform mat4 inv_view_proj_mat;

in vec2 uv_f;

vec3 reconstruct_pos(){
float z = texture(depth_tex, uv_f).r;
vec4 pos = vec4(uv_f, z, 1.0) * 2.0 - 1.0;
pos = inv_view_proj_mat * pos;

return pos.xyz / pos.w;
}

并得到了一个看起来非常正确的结果:

Cube rendered with correct world-space position reconstruction

但现在的道路很简单 z value 并不那么容易(似乎也不应该那么难)。

我的顶点着色器,用于我的第一遍日志深度:
#version 330 core
#extension GL_ARB_shading_language_420pack : require

layout(location = 0) in vec3 pos;
layout(location = 1) in vec2 uv;

uniform mat4 mvp_mat;

uniform float FC;

out vec2 uv_f;
out float logz_f;
out float FC_2_f;

void main(){
gl_Position = mvp_mat * vec4(pos, 1.0);

logz_f = 1.0 + gl_Position.w;

gl_Position.z = (log2(max(1e-6, logz_f)) * FC - 1.0) * gl_Position.w;

FC_2_f = FC * 0.5;
}

还有我的片段着色器:
#version 330 core
#extension GL_ARB_shading_language_420pack : require

// other uniforms and output variables

in vec2 uv_f;
in float FC_2_f;

void main(){
gl_FragDepth = log2(logz_f) * FC_2_f;
}

我尝试了几种不同的方法来正确恢复 z 位置,但都失败了。

如果我重新定义我的 reconstruct_pos在第二遍中:
vec3 reconstruct_pos(){
vec4 pos = vec4(uv_f, get_depth(), 1.0) * 2.0 - 1.0;
pos = inv_view_proj_mat * pos;

return pos.xyz / pos.w;
}

这是我目前重建 Z 的尝试:
uniform float FC;

float get_depth(){
float log2logz_FC_2 = texture(depth_tex, uv_f).r;
float logz = pow(2, log2logz_FC_2 / (FC * 0.5));
float pos_z = log2(max(1e-6, logz)) * FC - 1.0; // pos.z
return pos_z;
}

解释:
log2logz_FC_2 : 写入深度缓冲区的值,所以 log2(1.0 + gl_Position.w) * (FC / 2) logz :简单地 1.0 + gl_Position.w pos_z : gl_Position.z的值在透视之前

返回值: gl_Position.z
当然,这只是我的工作。我不确定这些值最终到底是什么,因为我认为我搞砸了一些数学或没有正确理解正在进行的转换。

从这个对数深度缓冲区获取我的世界空间 Z 位置的正确方法是什么?

最佳答案

最后我把这一切都错了。使用日志缓冲区获取世界空间位置的方法是:

  • 从纹理中检索深度
  • 重建 gl_Position.w
  • 线性化重建深度
  • 转换到世界空间

  • 这是我在 glsl 中的实现:
    in vec2 uv_f;

    uniform float nearz;
    uniform float farz;

    uniform mat4 inv_view_proj_mat;

    float linearize_depth(in float depth){
    float a = farz / (farz - nearz);
    float b = farz * nearz / (nearz - farz);
    return a + b / depth;
    }

    float reconstruct_depth(){
    float depth = texture(depth_tex, uv_f).r;
    return pow(2.0, depth * log2(farz + 1.0)) - 1.0;
    }

    vec3 reconstruct_world_pos(){
    vec4 wpos =
    inv_view_proj_mat *
    (vec4(uv_f, linearize_depth(reconstruct_depth()), 1.0) * 2.0 - 1.0);

    return wpos.xyz / wpos.w;
    }

    这给了我与使用默认 OpenGL 深度缓冲区时相同的结果(但精度更高)。

    关于opengl - 来自对数深度缓冲区的世界空间位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40373184/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com