Czy można dowiedzieć się, ile fragmentów przeszło przez test szablonu?


11

Mam aplikację OpenGL, która dość szeroko wykorzystuje testy szablonów do renderowania nieregularnych kształtów (trochę jak prosty 2-D CSG ). Gdybym mógł dowiedzieć się, ile fragmentów przeszło test matrycowy i faktycznie zostało zrenderowanych, byłoby to bardzo pomocne w uproszczeniu niektórych obliczeń w dół linii. W szczególności pozwoliłoby mi to określić obszar renderowanego kształtu za darmo zamiast później go przybliżać za pomocą symulacji Monte Carlo.

Wiem, że istnieje podobna koncepcja prymitywów emitowanych z modułu cieniującego geometrię, zwana sprzężeniem zwrotnym transformacji . Chciałbym wiedzieć, czy istnieje podobna koncepcja dla fragmentów i testu szablonu.


Prostym rozwiązaniem byłoby po prostu pomalowanie jednego kontrastującego koloru na inny za pomocą szablonu, zapisanie tego bufora i policzenie liczby zmienionych pikseli.
TheBuzzSaw

Hmm, specyfikacja mówi, że zapytania o okluzję liczą liczbę fragmentów, które przejdą test głębokości , ale poza moją głową nie jestem pewien, jak to teraz wchodzi w interakcję z testem matrycowym.
Chris mówi Przywróć Monikę

@ChristianRau Wygląda na to, że tylko fragmenty, które przejdą testy głębokości, zostaną policzone, ale testy szablonu, odrzucenia i alfa zostaną zignorowane.
Maurice Laveaux,

2
@ChristianRau i Maurice, oryginalna specyfikacja ARB_occlusion_query wyraźnie stwierdza, że ​​zlicza próbki, które przeszły testy zarówno głębokości, jak i wzornika. Zobacz także to pytanie StackOverflow .
Nathan Reed,

@NathanReed Wygląda na to, że masz zamiar napisać odpowiedź.
Chris mówi Przywróć Monikę

Odpowiedzi:


10

Jednym z możliwych podejść może być użycie kwerendy okluzji sprzętu.

Można skorzystać z faktów, że zgodnie ze specyfikacją Test Wzornika jest wykonywany przed testem głębokości, a tylko fragmenty, które przejdą test głębokości, są liczone przez Zapytanie Okluzji.

Prosty przykład (nie przetestowany) mógłby wyglądać następująco:

    GLuint samples_query = 0;
    GLuint samples_passed = 0;
    glGenQueries(1, &samples_query);
    // Initialize your buffers and textures ...
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_STENCIL_TEST);

    // Set up the values on the stencil buffer ...

    // Now we count the fragments that pass the stencil test
    glDepthFunc(GL_ALWAYS); // Set up the depth test to always pass
    glBeginQuery(GL_SAMPLES_PASSED, samples_query);
    // Render your meshes here
    glEndQuery(GL_SAMPLES_PASSED);
    glGetQueryObjectuiv(samples_query, GL_QUERY_RESULT, &samples_passed);
    // samples_passed holds the number of fragments that passed the stencil test (if any)

    // Release your resources ...
    glDeleteQueries(1, &samples_query);

Zauważ, że wywołanie w celu uzyskania liczby próbek wymusi wymuszenie opróżnienia potoku i czeka na zakończenie zapytania. Jeśli potrzebujesz bardziej asynchronicznego podejścia, możesz zapytać, czy zapytanie dotyczące okluzji jest wykonywane, czy nie, przy użyciu:

    GLuint query_done = 0;
    glGetQueryObjectuiv(samples_query, GL_QUERY_RESULT_AVAILABLE, &query_done);
    if (query_done != 0)
        // Your query result is ready
    else
        // Maybe check the next frame?

2

Jeśli interesuje Cię obszar, możesz zmniejszyć rozmiar bufora szablonów, aż osiągniesz jeden piksel i wydedukujesz ten obszar z jego koloru.

Kroki będą:

  • Skopiuj szablon do tekstury, używając formatu z wystarczającą precyzją.
  • Załaduj moduł cieniujący, który wyświetla kolor proporcjonalny do liczby tekstur o danym kolorze.
  • Ping-pong pomiędzy buforami ramki, aby zmniejszyć rozmiar o połowę, aż do osiągnięcia jednego piksela.
  • Kolor piksela to procent rzutni objętej obszarem: wystarczy pomnożyć go przez obszar rzutni.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.