Lấy số lượng các mảnh đã vượt qua bài kiểm tra chuyên sâu


8

Trong các môi trường "hiện đại", tiện ích mở rộng "Truy vấn loại trừ NV" cung cấp một phương thức để lấy số lượng các đoạn đã vượt qua bài kiểm tra chuyên sâu. Tuy nhiên, trên iPad / iPhone sử dụng OpenGL ES, tiện ích mở rộng không khả dụng.

Cách tiếp cận hiệu quả nhất để thực hiện một hành vi tương tự trong shader mảnh là gì?

Một số ý tưởng của tôi:

  • Kết xuất đối tượng hoàn toàn bằng màu trắng, sau đó đếm tất cả các màu với nhau bằng cách sử dụng trình đổ bóng hai chiều trong đó đầu tiên là một đường thẳng đứng được hiển thị và với mỗi phân đoạn, trình đổ bóng sẽ tính tổng trên toàn bộ hàng. Sau đó, một đỉnh duy nhất được hiển thị có mảnh tổng hợp tất cả các tổng một phần của lần đầu tiên. Có vẻ không hiệu quả lắm.

  • Kết xuất đối tượng hoàn toàn bằng màu trắng trên nền đen. Downsample đệ quy, lạm dụng phép nội suy tuyến tính phần cứng giữa các kết cấu cho đến khi ở độ phân giải hợp lý nhỏ. Điều này dẫn đến các mảnh có mức độ thang độ xám tùy thuộc vào số lượng pixel trắng trong khu vực tương ứng của chúng. Điều này thậm chí đủ chính xác?

  • Sử dụng mipmap và chỉ cần đọc pixel ở cấp độ 1x1. Một lần nữa câu hỏi về độ chính xác và nếu nó thậm chí có thể sử dụng kết cấu không hai sức mạnh.

Vấn đề của các phương pháp này là, đường ống bị đình trệ dẫn đến các vấn đề hiệu suất lớn. Do đó, tôi đang tìm kiếm một cách hiệu quả hơn để thực hiện mục tiêu của mình.

Sử dụng tiện ích mở rộng EXT_OCCLUSION_QUERY_BOOLESE

Apple đã giới thiệu EXT_OCCLUSION_QUERY_BOOLESE trong iOS 5.0 cho iPad 2.

"4.1.6  Occlusion Queries

Occlusion queries use query objects to track the number of fragments or 
samples that pass the depth test. An occlusion query can be started and 
finished by calling BeginQueryEXT and EndQueryEXT, respectively, with a 
target of ANY_SAMPLES_PASSED_EXT or ANY_SAMPLES_PASSED_CONSERVATIVE_EXT.

When an occlusion query is started with the target 
ANY_SAMPLES_PASSED_EXT, the samples-boolean state maintained by the GL is
set to FALSE. While that occlusion query is active, the samples-boolean 
state is set to TRUE if any fragment or sample passes the depth test. When 
the occlusion query finishes, the samples-boolean state of FALSE or TRUE is
written to the corresponding query object as the query result value, and 
the query result for that object is marked as available. If the target of 
the query is ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, an implementation may 
choose to use a less precise version of the test which can additionally set
the samples-boolean state to TRUE in some other implementation dependent 
cases."

Câu đầu tiên gợi ý về một hành vi chính xác là những gì tôi đang tìm kiếm: lấy số pixel vượt qua bài kiểm tra độ sâu một cách không đồng bộ mà không mất nhiều hiệu suất. Tuy nhiên, phần còn lại của tài liệu chỉ mô tả cách nhận kết quả boolean.

Có thể khai thác phần mở rộng này để có được số pixel? Phần cứng có hỗ trợ nó để có thể có API ẩn để có quyền truy cập vào số pixel không?

Các tiện ích mở rộng khác có thể khai thác được sẽ là các tính năng gỡ lỗi như số lần trình tạo bóng mảnh được gọi (PSInvocations trong DirectX - không chắc có gì đó có sẵn simila trong OpenGL ES không). Tuy nhiên, điều này cũng sẽ dẫn đến một gian hàng đường ống.


Hiệu ứng cuối cùng bạn đang cố gắng đạt được là gì?
Tetrad

Tôi cần số pixel không phải cho hiệu ứng kết xuất, mà là để tính toán. Tôi muốn sử dụng nó để tính trọng lượng của các hạt trong bộ lọc hạt.
Etan

Apple có hỗ trợ AMD_performance_monitor không? Nếu có, bạn có thể tìm thấy bộ đếm hiển thị các pixel đã qua. Xin lưu ý rằng đây là thiết bị rất, rất cụ thể ngay cả khi bạn làm cho nó hoạt động.
Jari Komppa

Vấn đề với AMD_performance_monitor là nó không đồng bộ, do đó, mất hiệu năng cũng sẽ xảy ra do tôi phải chờ giữa các khung để biết rằng các lệnh từ khung tiếp theo sẽ không có hiệu lực đối với bộ đếm hiệu suất.
Etan

Ngoài ra, AMD_performance_monitor không có sẵn.
Etan

Câu trả lời:


1

Có thể khai thác phần mở rộng này để có được số pixel? Phần cứng có hỗ trợ nó để có thể có API ẩn để có quyền truy cập vào số pixel không?

Không và không. Chà, tôi nghĩ rằng nếu bạn vẽ một loạt tam giác có kích thước một pixel trong không gian cửa sổ, bạn có thể đếm được bao nhiêu giá trị boolean bạn nhận được. Nhưng điều đó sẽ yêu cầu một truy vấn riêng cho từng pixel. Có lẽ không phải là điều nhanh nhất trên thế giới.

Nếu có "API ẩn", bạn sẽ không có quyền truy cập vào nó (vì nó bị ẩn), vì vậy nó không thành vấn đề. Hơn nữa, bản chất của phần mở rộng đã gợi ý rằng không có. Rốt cuộc, nếu phần cứng có số lượng phân đoạn thực tế, tại sao không chỉ phơi bày trực tiếp, cách OpenGL trên máy tính để bàn? Nếu phần cứng hỗ trợ nó, họ có thể đã lấy ARB_occlusion_query và sử dụng nó.

Nhưng họ đã không làm thế. Điều đó cho thấy mạnh mẽ rằng họ không thể.


Cảm ơn câu trả lời! Cách tiếp cận với các hình tam giác có kích thước một pixel có thể được cải thiện bằng cách chỉ hiển thị các điểm hoặc các đường nhỏ và thậm chí có thể được cải thiện bằng cách chia tỷ lệ logarit trong đó một dòng trả về "true" chỉ đơn giản được phân tách ở giữa và sau đó cả hai phần được kiểm tra lại. Không chắc chắn về hiệu suất nhưng các mô hình sẽ không có hơn 100-200 đỉnh. Lý do cho sự không tồn tại của "API ẩn" cũng hợp lệ. Có cách nào khác để đưa dữ liệu từ GPU trở lại CPU theo cách không đồng bộ mà không có gian hàng đường ống (cũng xin vui lòng cách hack)?
Etan

0

Thật không may, kết quả được trả về trong GLuint, (cũng có thể là GLint cho một cuộc gọi khác), kết quả luôn là 0 hoặc 1, có thể họ sẽ thay đổi nó để đăng ký các đoạn trong tương lai.

Ngoài ra, có vẻ như không một người nào trên toàn bộ internet đã đăng về các tiện ích mở rộng mới này ... vì vậy ở đây chúng được thiết lập đúng cách ... không được ghi lại ở bất cứ đâu xa như tôi có thể nói ... bạn có thể tưởng tượng chúng như thế nào sẽ đi vào mã của bạn từ mã sudo nhỏ này ở đây:

import UIKit/UIKit.h

import GLKit/GLKit.h

import "GLProgram.h"

GLuint testBox,hasBeenTested,theParams;

//...

glGenQueriesEXT(1, &testBox);

glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, testBox);


//... draw an object .......

glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);

glGetQueryObjectuivEXT(testBox, GL_QUERY_RESULT_AVAILABLE_EXT, &hasBeenTested);

if (hasBeenTested) glGetQueryObjectuivEXT(testBox, GL_QUERY_RESULT_EXT, &theParams);

glDeleteQueriesEXT(1, &testBox);

if (!theParams)  object is hidden;  don't draw next time;

Chỉ vì kiểu nói GLintkhông có nghĩa là nó là số nguyên của số lượng các đoạn đi qua. Đặc tả khá rõ ràng rằng QUERY_RESULT_EXTtrạng thái là một giá trị boolean; bạn chỉ cần truy vấn nó như một số nguyên. Đó là GL_FALSEnếu nó thất bại và không GL_FALSEnếu nó vượt qua.
Nicol Bolas

Tôi vừa thực hiện mã và thấy nó chỉ là đúng hoặc sai và đã thay đổi câu trả lời của tôi trước khi tôi thấy nhận xét của bạn ... vì đó là một cái nhìn thoáng qua, có thể họ sẽ thêm các trạng thái trong tương lai.
honjj

Nhân tiện, dường như có một lỗi trong GKKit, trong đó nếu bạn sử dụng self.effect2 = [[GLKBaseEffect alloc] init]; loại mã GLKit để hiển thị một đối tượng, thay vì đường ống GLES2.0 bình thường, các truy vấn sẽ không cung cấp cho bạn câu trả lời chính xác ... (không bao giờ bị ẩn) mặc dù tôi đã kiểm tra một đối tượng đường ống ẩn đối tượng GLKBaseEffect, vì vậy nó có thể có một lỗi chỉ là trộn lẫn cả hai, tôi chưa kiểm tra thêm ...
honjj

Các tiện ích mở rộng được giải thích với các ví dụ trong video WWDC có thể tìm thấy trên trang Táo có tài khoản nhà phát triển đang hoạt động.
Etan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.