Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Unity: альтернатива OnRenderImage и Graphics.Blit - проблема с DrawMeshNow - fullscreen quad и render texture (2 стр)

Unity: альтернатива OnRenderImage и Graphics.Blit - проблема с DrawMeshNow - fullscreen quad и render texture (2 стр)

Поделиться

Страницы: 1 2

KumoKairoПостоялецwww18 окт. 201710:46#15
В общем зерно истины, посеянное Leopotam, заработало.
Я правда не стал добавлять другие слои и прочие вещи, но идея с двумя камерами оказалась выигрышной.
Логика такая - на основной камере (которую мы хотим задаунсемплить и применить к ней постэффекты) висит скрипт, который ловит события LateUpdate, OnPreCull, OnPostRender и OnRenderObject. В cамом начале делаем копию этой основной камеры, делаем таргет в нужную текстуру и выключаем её (камеру).

в LateUpdate вызываем Camera.Render() на копии нашей камеры, которая выключена и рендерит в текстуру.
в OnPreCull выключаем все слои основной камеры (cullingMask = 0) чтобы основная камера сама ничего не рендерила.
в OnPostRender возвращаем cullingMask в исходное состояние
в OnRenderObject проверяем какая камера только что дорендерилась, и если это наша основная камера (активная, с которой мы сняли копию), то делаем Graphics.DrawMeshNow с той текстурой, которая отрендерилась копией камеры в LateUpdate.

Всё работает, всем спасибо

Правка: 18 окт. 2017 11:06

LeopotamПостоялецwww18 окт. 201712:58#16
KumoKairo, просто описано очень много телодвижений - в моем случае один раз настроил на старте и дальше оно само. Для экономии полосы пропускания на второй камере убираем очистку вообще, в шейдере блиттинга указываем игнорирование zbuffer - должно работать.
BonusПостоялецwww18 окт. 201713:47#17
В Unity есть несколько особенностей связанных с пост-процессом на мобилках:
1. Если у камеры нет TargetRenderTexture, то OnRenderImage тормозит, потому что копирует бэкбуфер (backbuffer.Resolve())
2. Если в сцене нет ни одной камеры, которая БЕЗ TargetRenderTexture, движок думает что вообще рисовать не надо, потому что никто не рисует в бэкбуфер.

Поэтому обычно делают следующее:
- основная камера рисует сцену в TargetRenderTexture
- вспомогательная ничего не рисует, но в методе OnPostRender (НИ В КОЕМ СЛУЧАЕ НЕ OnRenderImage) делает постпроцесс и в конце выполняет финальный Blit из TargetRenderTexture основной камеры в бэкбуфер.

Основую камеру не надо выключать и не надо руками вызывать Camera.Render()

boolПостоялецwww18 окт. 201714:19#18
Bonus
но тут надо еще учитывать тот момент, что если вспомогательная камера ничего не рисует, то у нее и пост рендер не вызовется. по-крайней мере так было в юнити 5 начальных, и приходилось где-нибудь на краю экрана вешать маленький объект, который камера видит и понимает, что надо рисовать и вызывать все события.
KumoKairoПостоялецwww18 окт. 201715:26#19
просто описано очень много телодвижений - в моем случае один раз настроил на старте и дальше оно само

в вашем варианте мне не очень понравилась ручная настройка новых слоёв, для меня это больше телодвижений чем оставлять настройку на начальном уровне без доп слоёв (если выносить это решение в отдельный пакет, то придётся шарить ProjectSettings, а это всегда глючно и косячно)
Если в сцене нет ни одной камеры, которая БЕЗ TargetRenderTexture, движок думает что вообще рисовать не надо, потому что никто не рисует в бэкбуфер

Да, я только под самый конец это понял. Основная камера, которая копируется дополнительной, несёт именно нагрузку "хоть какой-то камеры"
Поэтому обычно делают следующее:
- основная камера рисует сцену в TargetRenderTexture
- вспомогательная ничего не рисует, но в методе OnPostRender (НИ В КОЕМ СЛУЧАЕ НЕ OnRenderImage) делает постпроцесс

По сути у меня то же самое, только камеры задом наперёд. Основная рендерит пустоту, а мы цепляемся к ней ради активного OnPostRender
и в конце выполняет финальный Blit из TargetRenderTexture основной камеры в бэкбуфер.

Обычный Blit, а не DrawMeshNow мне не подходит по причине того, что ему нельзя подсунуть тесселированый квад для эффектов типа Distortion Wave. DrawMeshNow мне нужен только для этого
что если вспомогательная камера ничего не рисует, то у нее и пост рендер не вызовется

Всё верно, OnPreCull, OnPreRender и OnPostRender вызываются на монобехе с камерой по факту рендеринга этой камеры. Трюк с "маленькой камерой только для событий" мне тоже не очень нравится потому что можно явно обойтись без него просто подцепившись хуком к интересующей активной камере

Правка: 18 окт. 2017 15:37

KumoKairoПостоялецwww18 окт. 201715:32#20
Для экономии полосы пропускания на второй камере убираем очистку вообще

На тайловых GPU (почти все мобилки тайловые) полная очистка чаще всего наоборот улучшает производительность. Сорс - http://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-T… itectures.pdf пункт 23.3
On a tile-based architecture, avoiding clears can be disasterous for performance: since the frame is built up in frame data, clearing all buffers will simply free up the existing frame data. In other words, not only is glClear very cheap, it actually improves performance by allowing unneeded frame data to be discarded.

Для экономии bandwidth лучше всего вырубить depth buffer (в нашем случае он пока не используется), а основной таргет рендер держать в формате RGB565, как вы уже выше уточняли.

Правка: 18 окт. 2017 15:39

LeopotamПостоялецwww18 окт. 201715:46#21
На тайловых GPU (почти все мобилки тайловые) полная очистка чаще всего наоборот улучшает производительность.

Интересно как, выше был разговор про тегру X1 и уход от темы, а тут уже "почти все тайловые" :) Вообще, это скорее не тайловые, а тайловые с отложенным рендером, типа powervr - особенность реализации драйверов, драйвер помечает буферы как чистые - что-то типа "быстрой очистки". Это все устройства от apple (android-ов мало), но новые уже будут на своем чипе. По теме - нужно пробовать на целевых устройствах, информация часто устаревает, верить можно только своим измерениям.

Правка: 18 окт. 2017 15:47

KumoKairoПостоялецwww18 окт. 201715:49#22
По теме - нужно пробовать на целевых устройствах, информация часто устаревает, верить можно только своим измерения

Полностью согласен, нативные профилировщики графики никто не отменял :)
BonusПостоялецwww18 окт. 201717:33#23
KumoKairo
> Обычный Blit, а не DrawMeshNow мне не подходит по причине того, что ему нельзя
> подсунуть тесселированый квад для эффектов типа Distortion Wave. DrawMeshNow
> мне нужен только для этого
Можно и DrawMeshNow, это тоже сработает. Т.е. отрисовать все основной камерой в текстуру, а потом во вспомогательной камере сделать DrawMeshNow с тесселированным квадом. Рендеринг же будет происходить в бэкбуфер, это самое главное.
KumoKairo
> если вспомогательная камера ничего не рисует, то у нее и пост рендер не
> вызовется
>
> Всё верно, OnPreCull, OnPreRender и OnPostRender вызываются на монобехе с
> камерой по факту рендеринга этой камеры. Трюк с "маленькой камерой только для
> событий" мне тоже не очень нравится потому что можно явно обойтись без него
> просто подцепившись хуком к интересующей активной камере

Ну тут либо шашечки, либо ехать. Так движок устроен. По-моему самое простое - это настроить лейеры. Тупо завести лейер, в котором нет ни одного объекта, а вспомогательная камера рисует только этот лейер.

LeopotamПостоялецwww18 окт. 201718:32#24
И тут я начал беспокоиться... Проверил, нет, вроде я не Bonus, почему он говорит про слои то, что я говорил? :D
BonusПостоялецwww19 окт. 20179:55#25
Leopotam
> И тут я начал беспокоиться... Проверил, нет, вроде я не Bonus, почему он
> говорит про слои то, что я говорил? :D
Просто я сформулировал "вспомогательная [камера] ничего не рисует", и тут понеслось... Решил пояснить, что добиться этого можно через слои. Иначе, если ее просто выключить, то ее события (OnPostRender и т.п.) не будут вызываться.

Страницы: 1 2

/ Форум / Программирование игр / Графика

2001—2017 © GameDev.ru — Разработка игр