Чи можна дізнатися, скільки фрагментів зробили це за допомогою трафаретного тесту?


11

У мене є програма OpenGL, яка досить широко використовує трафаретні тести, щоб надати неправильні форми (трохи як простий 2-D CSG ). Якби я міг дізнатися, скільки фрагментів пройшло тест трафарету і насправді було винесено, це було б дуже корисно для спрощення деяких обчислень вниз. Зокрема, це дозволить мені безкоштовно визначити площу наданої форми замість того, щоб згодом її наближати за допомогою моделювання Монте-Карло.

Я знаю, що існує подібна концепція для примітивів, що викидаються з геометрії шейдера, і називається зворотним зв'язком трансформації . Мені хотілося б знати, чи існує подібна концепція для фрагментів та тесту трафарету.


Сирим рішенням буде просто намалювати один контрастний колір на інший через трафарет, зберегти цей буфер і порахувати кількість пікселів, які були змінені.
TheBuzzSaw

Гм, специфікація говорить, що запити окуляції підраховують кількість фрагментів, які проходять тест на глибину , але вгорі голови я не впевнений, як це взаємодіє з тестом трафарету зараз.
Кріс каже, що відбудеться Моніка

@ChristianRau Схоже, що будуть враховані лише фрагменти, які проходять глибинні тести, але трафарет, відкидання та альфа-тести ігноруються.
Моріс Лаво

2
@ChristianRau та Maurice, оригінальна специфікація ARB_occlusion_query чітко говорить, що він підраховує проби, які проходять і тести на глибину, і на трафарет. Дивіться також це питання StackOverflow .
Натан Рід

@NathanReed Здається, що ви збираєтесь написати відповідь.
Кріс каже, що повернеться до Моніки

Відповіді:


10

Одним із можливих підходів може бути використання Запиту на апаратне оклюзія.

Ви можете використовувати факти, що за специфікацією тест трафарету виконується перед випробуванням на глибину, і лише фрагменти, які проходять тест на глибину, підраховуються за запитом оклюзії.

Простий приклад (не перевірений):

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

Зауважте, що виклик для отримання кількості зразків буде примусово викликати промивання трубопроводу та чекати, коли запит завершиться. Якщо вам потрібен більш асинхронний підхід, ви можете запитувати, чи робиться запит оклюзії чи ні, використовуючи:

    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

Якщо вас цікавить область, ви можете зменшити розмір буфера трафарету, поки не досягнете одного пікселя і виведете цю область з її кольору.

Кроки будуть:

  • Скопіюйте трафарет на текстуру, використовуючи формат з достатньою точністю.
  • Завантажте шейдер, який виводить колір, пропорційний кількості текселів із заданим кольором.
  • Пінг-понг між фреймбуферами, щоб зменшити розмір вдвічі, поки не досягне одного пікселя.
  • Колір пікселя - це відсоток перегляду області, який охоплює область: просто помножте його на площу вікна перегляду.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.