2009-03-06 4 views
0

У меня есть код OpenGL, который ведет себя непоследовательно в разных аппаратных средствах . У меня есть некоторый код, который:Self-Referencing Renderbuffers в OpenGL

  1. Создает буфер визуализации и связывает текстуру его буфер цвета (текстура)
  2. Устанавливает этот буфер визуализации в качестве активных и регулирует видовой экран, и т.д.
  3. Активирует пиксельный шейдер (гауссовское размытие, в данном случае).
  4. Рисует квадрат на весь экран, с текстурой A на нем.
  5. отвязывает renderbuffer и т.д.

На моей машине развития это работает отлично, и имеет намеченную эффект размытия текстуры «на месте», однако на других аппаратных это не похоже на работу.

Я получил это до двух возможностей.

A) Изготовление рендеринга буфера для себя не должно работать, и работает только на моей машине разработки из-за какой-то случайности.

Или

B) Этот подход должен работать, но что-то еще происходит не так.

Любые идеи? Честно говоря, мне было трудно найти особенности этой проблемы.

ответ

2

A) - правильный ответ. Рендеринг в тот же буфер при чтении из него не определен. Это может сработать, возможно, это не так - это именно то, что происходит.

В случае OpenGL framebuffer_object extension имеет раздел «4.4.3. Оказание, когда изображение связанного объекта текстуры также прикрепляется к Framebuffer», в котором говорится, что происходит (в основном, неопределенно). В Direct3D9 отладочная среда исполнения жалуется громко, если вы используете эту настройку (но она может работать в зависимости от аппаратного/драйвера). Я думаю, в D3D10 время выполнения всегда отбрасывает цель, которая используется как пункт назначения.

Почему это не определено? Одна из причин, по которой графические процессоры настолько быстры, что они могут сделать много предположений. Например, они могут предположить, что устройствам, которые берут пиксели, не нужно связываться с единицами, которые пишут пиксели. Таким образом, поверхность может быть прочитана, N циклов позже, когда чтение завершено, N циклов позже, пиксельный шейдер завершает его выполнение, затем он помещается в некоторые буферы вывода на GPU и, наконец, в какой-то момент он записывается в память. Кроме того, графические процессоры растеризуются в «неопределенном» порядке (один GPU может растрироваться в строках, другой - в некотором кэшированном порядке, другой - в совершенно другом порядке), поэтому вы не знаете, какие части поверхности будут записаны в первую очередь.

Так что вам нужно сделать несколько буферов. В случае размытия/свечения обычно достаточно двух - сначала отрисовывается, затем читается &, что при записи во второй. Повторите этот процесс, если необходимо, в режиме пинг-понга.

+0

Спасибо, я склонялся к этому в своих исследованиях, хотя я не мог получить конкретный ответ. – Brandorf

+0

@brandorf: Я добавил ссылку на спецификацию объекта framebuffer, где говорится, что результат не определен. – NeARAZ

0

В некоторых особых случаях даже бэкбуфера может быть достаточно. Вы просто не делаете glClear, и то, что вы нарисовали ранее, все еще существует. Оговорка, конечно, заключается в том, что вы не можете читать из буфера. Но для таких эффектов, как угасание и выход, это работает.