Можно ли узнать, сколько фрагментов было сделано с помощью теста трафарета?


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.