2010-04-07 39 views
5

Theo như tôi biết, chúng tôi không thể đọc giá trị Z (chiều sâu) trong OpenGL ES 2.0. Vì vậy, tôi tự hỏi làm thế nào chúng ta có thể có được tọa độ thế giới 3D từ một điểm trên màn hình 2D?OpenGL es 2.0 Đọc bộ đệm sâu

Thực ra tôi có một số suy nghĩ ngẫu nhiên có thể hoạt động. Vì chúng ta có thể đọc giá trị RGBA bằng cách sử dụng glReadPixels, làm thế nào chúng ta sao chép bộ đệm độ sâu và lưu trữ nó trong một bộ đệm màu (nói ColorforDepth). Tất nhiên cần phải có một số quy ước tốt đẹp để chúng tôi không mất bất kỳ thông tin nào về bộ đệm độ sâu. Và sau đó khi chúng ta cần tọa độ thế giới của một điểm, chúng tôi đính kèm bộ đệm màu ColorforDepth này vào bộ đệm khung và sau đó hiển thị nó. Vì vậy, khi chúng tôi sử dụng glReadPixels để đọc thông tin chi tiết tại khung này.

Tuy nhiên, điều này sẽ dẫn đến 1 khung hình flash vì bộ đệm màu là một bộ đệm lạ được dịch từ bộ đệm độ sâu. Tôi vẫn tự hỏi nếu có một số cách tiêu chuẩn để có được chiều sâu trong OpenGL es 2.0?

Thx trước! :)

Trả lời

7

Sử dụng FBO, bạn có thể hiển thị mà không hiển thị kết quả. Nếu bạn đang ở ES 2.0, trình đổ bóng phân mảnh của bạn có thể truy cập độ sâu của đoạn hiện tại (trong các tọa độ cửa sổ) như một phần của gl_FragCoord, vì vậy bạn có thể viết nó vào bộ đệm màu, sử dụng glReadPixels để lấy lại kết quả và tiến hành. Ngoài ra, bạn có thể tải z không gian thế giới dưới dạng khác nhau và viết từ trình đổ bóng phân đoạn của bạn, trong trường hợp đó là cách dễ dàng hơn.

Để thuyết phục bản thân, hãy thử viết một trình đổ bóng nhanh chóng đặt gl_FragCoord.z ​​ra nhanh chóng với độ chính xác thấp, ví dụ: chỉ

gl_FragColor = vec4(vec3(gl_FragCoord.z), 1.0); 

Bạn sẽ nhận được thang độ xám với cường độ màu đại diện cho độ sâu. Bởi vì bạn đang ở trong các tọa độ cửa sổ, cường độ sẽ dao động từ 0,0 (gần nhất có thể không được cắt đoạn) đến 1.0 (xa nhất có thể chưa được tách mảnh). Để không mất khá nhiều độ chính xác, có lẽ sẽ hữu ích hơn nếu chia nhỏ giá trị giữa các thành phần, vì nhà cung cấp của bạn gần như chắc chắn không hỗ trợ bộ đệm mục tiêu dấu phẩy động.

+0

Tommy, bạn có thể nói thêm một chút về việc tách gl_FragCoord.z ​​giữa các thành phần hay không. Không tuân theo. Chúc mừng. – dugla

+1

@dugla Nếu chiều sâu là một số nguyên 32 bit, bạn có thể nhưng 8 bit của nó trong mỗi R, G, B và A. Vì vậy, trong thực tế những gì bạn muốn làm là một cái gì đó giống như nhân vectơ '(1, 256 , 65536, 16777216) ', sau đó lưu trữ mỗi thành phần của vectơ mod 1.0 đó vào các kênh liên quan. Bạn có thể kết hợp lại sau bằng cách chia cho các thành phần liên quan và cộng lại với nhau. – Tommy

0

Tôi sử dụng phép đúc tia cơ bản để chọn đối tượng 3D từ màn hình cảm ứng. Trên thực tế tôi tính toán giao điểm giữa màn hình bình thường tại điểm tiếp xúc và hình cầu chứa đối tượng của tôi. Đối với một chọn rất chính xác hoặc hình dạng phức tạp, bạn phải sử dụng một số hình cầu.

Bạn cũng có thể chiếu một số điểm chính của đối tượng trong không gian 2D của màn hình (nhân số điểm 3D của bạn với ma trận chuyển đổi) và sau đó thực hiện so sánh 2D (khoảng cách) với điểm tiếp xúc.

0

tôi cũng muốn có thể đọc các giá trị trong bộ đệm độ sâu, nhưng nghiên cứu chỉ ra rằng không thể thực hiện được.

như vincent gợi ý, nếu bạn có hình dạng đơn giản như hình cầu, việc đúc bằng ray có lẽ tốt hơn.

cho hình dạng phức tạp hơn tho, Tôi đang nghĩ đến việc vẽ các đối tượng đến một (có khả năng nhỏ hơn) offscreen đệm, tự gán một trong những thành phần màu sắc của mỗi đỉnh là độ sâu của đỉnh đó, và sau đó đọc các giá trị màu. điều này hơi khó chịu và phiền phức, và đòi hỏi bạn phải có khả năng chuyển đổi không gian đối tượng thành không gian màn hình (tôi đang sử dụng quaternions của riêng tôi để điều khiển các ma trận, do đó sẽ đảm nhiệm điều đó). có thể có một cách với shaders để ghi các thông tin chiều sâu vào bộ đệm màu hoặc stencil (hiện GL ES thậm chí có một bộ đệm stencil?)

nếu ai có cách tiếp cận sạch hơn tôi muốn nghe nó.

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