Po zmianie mojego bieżącego rendereru odroczonego na użycie logarithmic depth buffer, nie mogę wyłuskać, na życie mnie, jak zrekonstruować głębokość przestrzeni świata z wartości bufora głębi.Pozycja w przestrzeni globalnej z logarytmicznego bufora głębi
Gdy miałem domyślną głębokość Z/W OpenGL, mogłem łatwo obliczyć tę wartość poprzez przekształcenie z przestrzeni okna na przestrzeń NDC, a następnie wykonać odwrotną transformację perspektywy.
Zrobiłem wszystko to w drugim przejściu fragment shadera:
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;
}
i dostałem wynik, który wyglądał całkiem poprawne:
Ale teraz droga do prostego z
wartości jest nie tak łatwo (nie wydaje się, że powinno być tak trudno).
Moja vertex shader dla mojego pierwszego przejścia z głębi dziennika:
#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;
}
A mój fragment shader:
#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;
}
Próbowałem kilka różnych podejść, aby wrócić z-pozycji poprawnie, wszystko zawiedzie.
Gdybym przedefiniować mój reconstruct_pos
w drugim przejściu być:
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;
}
To moja obecna próba rekonstrukcji 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;
}
wyjaśnił:
log2logz_FC_2
: wartość napisane do bufora głębokości, więc log2(1.0 + gl_Position.w) * (FC/2)
logz
: wystarczy 1.0 + gl_Position.w
pos_z
: wartość gl_Position.z
przed perspektywicznym podzielić
Wartość zwracana: gl_Position.z
Oczywiście, to tylko moja robocza. Nie jestem pewien, co te wartości faktycznie trzymają w końcu, ponieważ myślę, że spieprzyłem trochę matematyki lub nie zrozumiałem poprawnie transformacji.
Jaki jest poprawny sposób na uzyskanie mojej pozycji w przestrzeni światowej z tego logarytmicznego bufora głębi?