2013-04-21 24 views
5

Tôi có một cặp trình tạo bóng GLSL cung cấp cho tôi bản đồ độ sâu của các đối tượng trong cảnh của tôi. Những gì tôi nhận được bây giờ là khoảng cách từ mỗi điểm ảnh đến máy ảnh. Những gì tôi cần là để có được khoảng cách từ điểm ảnh đến mặt phẳng máy ảnh. Hãy để tôi minh họa bằng một bản vẽ nhỏĐộ sâu như khoảng cách đến mặt phẳng máy ảnh trong GLSL

*   |--* 
/   | 
/   | 
C-----*  C-----* 
\   | 
    \   | 
    *   |--* 

3 dấu hoa thị là pixel và C là máy ảnh. Các dòng từ dấu hoa thị là "chiều sâu". Trong trường hợp đầu tiên, tôi nhận được khoảng cách từ điểm ảnh đến máy ảnh. Trong lần thứ hai, tôi muốn lấy khoảng cách từ mỗi điểm ảnh đến mặt phẳng.

Phải có cách để thực hiện việc này bằng cách sử dụng một số ma trận chiếu, nhưng tôi bị chặn lại.

Dưới đây là các trình tạo bóng tôi đang sử dụng. Lưu ý rằng eyePosition là camera_position_object_space.

Vertex Shader:

void main() { 
    position = gl_Vertex.xyz; 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
} 

Pixel Shader:

uniform vec3 eyePosition; 
varying vec3 position; 


void main(void) { 
     vec3 temp = vec3(1.0,1.0,1.0); 
     float depth = (length(eyePosition - position*temp) - 1.0)/49.0; 
     gl_FragColor = vec4(depth, depth, depth, 1.0); 
} 
+0

Loại chiếu bạn đang sử dụng? Nếu bạn sử dụng phép chiếu chính xác khi hiển thị bản đồ độ sâu, bạn sẽ nhận được những gì bạn cần mà không có bất kỳ phép tính nào. – Ani

+0

Tôi đang thực hiện phép chiếu phối cảnh khi hiển thị, nhưng tôi cần các giá trị độ sâu đến từ phép chiếu chính xác. – Lucian

Trả lời

9

Bạn đang thực sự cố gắng làm điều này một cách khó khăn. Đơn giản chỉ cần chuyển đổi mọi thứ sang không gian camera và làm việc từ đó.

varying float distToCamera; 

void main() 
{ 
    vec4 cs_position = glModelViewMatrix * gl_Vertex; 
    distToCamera = -cs_position.z; 
    gl_Position = gl_ProjectionMatrix * cs_position; 
} 

Trong không gian camera (không gian nơi mọi thứ đều tương đối so với vị trí/hướng của máy ảnh), khoảng cách phẳng đến một đỉnh chỉ là tiêu cực của Z tọa độ (cao hơn tiêu cực Z là xa).

Vì vậy, trình đổ bóng phân đoạn của bạn thậm chí không cần eyePosition; "độ sâu" xuất phát trực tiếp từ trình đổ bóng đỉnh.

+0

Bạn nói đúng, tôi đã làm điều đó một cách khó khăn. Ngoài ra, tôi giả sử -cs.z là -cs_position.z. Cảm ơn đoạn mã! – Lucian

1

Những gì bạn đang gián tiếp tại là chiếu chính tả. Bạn hiện đang sử dụng phép chiếu phối cảnh. Trên thực tế, bạn không có khoảng cách thực sự từ pixel đến máy ảnh, mà đúng hơn là vị trí z của pixel trong sự thất vọng. Trên kết cấu render, độ sâu z cuối cùng trong phạm vi [-1,1] được trả về, mô tả thành phần z của nó trong không gian NDC.

Như bạn đã hiểu, tất cả các điểm của bạn được chiếu 'hướng tới' (thực sự lên mặt phẳng gần) camera sử dụng phép chiếu phối cảnh. Những gì bạn muốn là chiếu chúng vào mặt phẳng gần. This link mô tả chi tiết cả hai ma trận chiếu và kết quả cuối cùng của ma trận ở dưới cùng. Trình đổ bóng của bạn sẽ có thể xử lý ma trận chiếu mới tốt. Chỉ cần đảm bảo ma trận MVP của bạn được tính như đề xuất ở trên.

Lưu ý rằng phép chiếu orthographic có thể không đại diện cho độ sâu của cảnh được hiển thị của bạn. Nếu bạn đang hiển thị cảnh của mình trên màn hình với phép chiếu phối cảnh và bạn muốn chiều sâu của mỗi pixel, bạn nên sử dụng cùng một phối cảnh cho phù hợp. Vì vậy, hiển thị chiều sâu của bạn bằng cách sử dụng phép chiếu chính xác sẽ chỉ hữu ích nếu cảnh của bạn sử dụng cùng một phép chiếu hoặc nếu một số thuật toán cần thông tin chi tiết không liên quan đến cảnh như được thấy trên màn hình.

Hơn nữa, tôi khuyên bạn nên xem xét các cấu hình OpenGL cốt lõi (3.x) vì bạn dường như đang sử dụng chức năng không được dùng nữa (gl_Vertex, gl_ModelViewProjectionMatrix và giống nhau). Đó là một chút công việc để thiết lập tất cả các bộ đệm và shaders mình, nhưng nó trả hết vào cuối.

EDIT

Trên thực tế, sau khi bình luận của bạn, tôi hiểu những gì bạn muốn. Không rõ là bạn muốn kết xuất chúng trong cùng một cuộc gọi, vì điều này tôi đề xuất một cái gì đó như thế này trong trình đổ bóng phân đoạn của bạn:

uniform mat4 orthographicMatrix; 
varying vec3 position; 

void main(void) { 
     vec4 clipSpace = orthographicMatrix * vec4(position, 1.0); 
     gl_FragColor = vec4(clipSpace.zzz, 1.0); 
} 

Lưu ý rằng bạn không phải thực hiện w chia làm phép chiếu chính xác tuyến tính đã có (do đó w được đặt thành 1).

+0

Cảm ơn bạn đã phản hồi chi tiết. Tôi _am_ cố gắng để có được chiều sâu tương ứng với chiếu trực giao trong khi rendering theo chiếu phối cảnh. Điều này có vẻ kỳ lạ nhưng đó là những gì tôi phải làm. – Lucian

+0

Ồ tôi hiểu rồi, tôi nghĩ tôi hiểu ý của bạn là gì. Đã chỉnh sửa bài đăng của tôi. – Invalid

1

Thành phần W sau khi chiếu chứa độ sâu trực giao vào cảnh. Bạn không cần phải sử dụng ma trận modelview và chiếu riêng biệt cho điều này:

varying float distToCamera; 

void main() 
{ 
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
    distToCamera = gl_Position.w; 
} 
+0

Có phải không? Không phải là nó 'gl_Position.z/gl_Position.w'? – RecursiveExceptionException