Самоссылающиеся буферы рендеринга в OpenGL
Вопрос
У меня есть какой -то код OpenGL, который ведет себя непоследовательно для разных оборудования.У меня есть код, который:
- Создает буфер рендеринга и привязывает текстуру к ее цветовому буферу (Текстура A).
- Устанавливает этот буфер рендеринга как активный, настраивает область просмотра и т. д.
- Активирует пиксельный шейдер (в данном случае размытие по Гауссу).
- Рисует четырехугольник на весь экран с текстурой A на нем.
- Отвязывает рендербуфер и т.д.
На моей машине разработки это работает нормально, и имеет предполагаемый эффект размытия текстуры «на месте», однако на других оборудовании это, похоже, не работает.
Я свел это к двум возможностям.
А) Предполагается, что приготовление рендеринга для себя не должно работать, и работает только на моей машине разработки из -за какой -то случайности.
Или
Б) Этот подход должен работать, но что-то еще идет не так.
Есть идеи?Честно говоря, мне было трудно найти конкретику по этому вопросу.
Решение
А) правильный ответ.Рендеринг в тот же буфер при чтении из него не определен.Это может сработать, а может и нет – именно это и происходит.
В случае OpenGL расширение Framebuffer_object есть раздел «4.4.3 Рендеринг, когда изображение привязанного объекта текстуры также прикреплено к кадровому буферу», в котором рассказывается, что происходит (в основном, неопределенное).В Direct3D9 среда выполнения отладки громко жалуется, если вы используете эту настройку (но она может работать в зависимости от оборудования/драйвера).Я думаю, что в D3D10 среда выполнения всегда отвязывает цель, которая используется в качестве места назначения.
Почему это неопределенно?Одна из причин, по которой графические процессоры такие быстрые, заключается в том, что они могут делать множество предположений.Например, они могут предположить, что устройствам, которые извлекают пиксели, не нужно взаимодействовать с модулями, которые записывают пиксели.Таким образом, поверхность может быть прочитана, через N циклов чтение завершено, через N циклов пиксельный шейдер завершает свое выполнение, затем он помещается в некоторые выходные буферы слияния на графическом процессоре и, наконец, в какой-то момент записывается в память.Вдобавок ко всему, графические процессоры растеризуются в «неопределённом» порядке (один графический процессор может растрировать по строкам, другой — в каком-то удобном для кэша порядке, третий — в совершенно другом порядке), поэтому вы не знаете, какие части поверхности будут записаны. сначала.
Итак, что вам нужно сделать, это создать несколько буферов.В случае размытия/свечения обычно достаточно двух — сначала визуализировать, затем прочитать и размыть во время записи во вторую.При необходимости повторите этот процесс в режиме пинг-понга.
Другие советы
В некоторых особых случаях может быть достаточно даже обратного буфера.Вы просто не выполняете glClear, и то, что вы нарисовали ранее, все еще там.Предостережение, конечно, в том, что вы не можете читать данные из обратного буфера.Но для таких эффектов, как появление и исчезновение, это работает.