Разработка под Apple iOS / Cocos2D вода на основе SPH

в 4:21, , рубрики: cocos 2d, вода, шейдеры, метки: , ,


Если необходимо реализовать воду, которая работает, как контроллер уровня, и тела попав на неё, всплывают, то SPH (Smoothed Particle Hydrodynamics) нам не поможет. Реализация подобного типа воды хорошо, например, описана здесь.
Стояла задача реализовать воду именно на основе гидродинамики сглаженных частиц.
Реализацию можно разбить на две, в общем-то, абсолютно не связанные подзадачи:

  • Физика (Model)
  • Графика (View)

Физический мир

Для реализации был выбран физический движок Box2D.
На самом деле тут всё очень просто: необходимо создать много одинаковых маленьких частиц, которые обладают следующими параметрами:

  1. Частицы гладкие, т. е. Friction=0;
  2. Частицы круглые;
  3. Частицы друг с другом взаимодействуют.

Количество подсчетов скорости и позиции (velocityIterations & positionIterations) можно задать 3 и 1 соответственно. Этого вполне достаточно, для обеспечения нормальной работы.
Результат можно посмотреть на краткой видео демонстрации.

Как видно в физическом мире всё прекрасно «живёт» так, как нужно.

Графика

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

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

Другой способ: рисовать частицы воды кружочками большего диаметра, чем физические объекты. Это очень простой способ, но для того, чтобы вода была похожа на воду, необходимо сделать ее прозрачной, и применить ряд других спецэффектов.
Для начала был испробован способ наложения маски на рисуемый слой с использований возможностей openGL ES 1.0 по следующему методу.

В результате использования пяти CCRenderTexture была получена неплохая в общем-то вода с эффектом motion blur и искажением просвечивающего через воду изображения.

Оптимизация

К великому огорчению всё это ужасно тормозило на iPad1, хорошо работая на iPad2 и iPhone 4S.
Конечно считать такой результат удовлетворительным было нельзя.
Была проделана огромная работа по оптимизации кода, однако это почти ничего не изменило.
После изысканий на тему кто работает быстрее Chimpmunk или Box2D было выяснено, что действительно Chimpmunk работает быстрее.
Тем не менее результат всё равно продолжал тормозить. Можно было использовать до 100 частиц, на iPad1 чего в общем-то маловато.
Был сделан вывод, что графическая реализация тормозит, тогда как физическая часть работает вполне удовлетворительно.

Cocos2d 2.0 Brunch, шейдеры

Очевидным решением проблемы являются шейдеры и использование OGL ES 2.0.
Хорошо что существует Cocos2d 2.0 Brunch c OGL ES 2.0. Перенос на который из Cocos2d оказался абсолютно безболезненным, и простым.
Использование маскирующего и искажающего шейдера позволило сделать воду с 300 частицами на iPad 1 и FPS 30.
Видео результата в начале топика.

Автор: Alexey_Bespaly

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js