2016-11-02 19 views
7

Sau khi thay đổi bộ hiển thị trả lại hiện tại của tôi để sử dụng logarithmic depth buffer Tôi không thể làm việc được, trong cuộc đời của tôi, cách tái tạo chiều sâu không gian thế giới từ các giá trị bộ đệm độ sâu.Vị trí không gian thế giới từ bộ đệm độ sâu logarit

Khi tôi có độ sâu z/w mặc định OpenGL được viết, tôi có thể dễ dàng tính toán giá trị này bằng cách chuyển từ không gian cửa sổ sang không gian NDC rồi thực hiện phép biến đổi phối cảnh nghịch đảo.

tôi đã làm tất cả điều này trong lần thứ hai vượt qua đoạn đổ bóng:

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; 
} 

và nhận một kết quả trông khá chính xác:

Cube rendered with correct world-space position reconstruction

Nhưng bây giờ con đường dẫn đến một giá trị đơn giản z là không dễ dàng như vậy (dường như không quá khó).

shader My đỉnh cho pass đầu tiên của tôi với độ sâu log:

#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; 
} 

Và shader mảnh của tôi:

#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; 
} 

Tôi đã thử một vài phương pháp khác nhau để lấy lại z-position một cách chính xác, tất cả đều thất bại.

Nếu tôi xác định lại tôi reconstruct_pos ở đèo thứ hai là:

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; 
} 

Đây là nỗ lực hiện tại của tôi ở xây dựng lại 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; 
} 

Giải thích:

log2logz_FC_2: giá trị bằng văn bản vào bộ đệm độ sâu, do đó, log2(1.0 + gl_Position.w) * (FC/2)

logz: chỉ cần 1.0 + gl_Position.w

pos_z: giá trị của gl_Position.z trước viễn cảnh chia

giá trị trả về: gl_Position.z

Tất nhiên, đó chỉ là làm việc của tôi. Tôi không chắc chắn những gì các giá trị này thực sự giữ cuối cùng, bởi vì tôi nghĩ rằng tôi đã screwed lên một số các toán học hoặc không chính xác hiểu các biến đổi đang xảy ra.

Cách chính xác để có được vị trí Z không gian thế giới của tôi từ bộ đệm độ sâu logarit này là gì?

Trả lời

0

Cuối cùng tôi đã đi về tất cả điều này sai. Cách để có được vị trí không gian thế giới lại sử dụng một bộ đệm log là:

  1. Lấy độ sâu từ kết cấu
  2. tái tạo lại gl_Position.w
  3. linearize sâu xây dựng lại
  4. dịch để không gian thế giới

Dưới đây là thực hiện của tôi trong 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; 
} 

nào mang lại cho tôi những kết quả tương tự (nhưng với độ chính xác tốt hơn) như khi tôi đã sử dụng bộ đệm độ sâu OpenGL mặc định.

Các vấn đề liên quan