Я имею опыт работы в строительстве и регулярно выполняю гидравлический и гидрологический анализ. Они продают дипломы за подобные вещи, но на самом деле это не ракетостроение. Недавно я решил реализовать весь гидрологический и гидравлический процесс для местности на графическом процессоре. Я изучил вычислительные шейдеры только недавно, поэтому в настоящее время я застрял в лучшем инженерном деле, чем в разработке параллельных рабочих процессов графического процессора.
Вы можете рассчитать количество воды, образованной во время дождя, используя формулу:
Q (CF/S) = c * I (in/hr) * A (acres)
Мне трудно выйти за рамки расчета «площади» даже первой области.
Обзор текущей реализации:
- Ландшафт представляет собой правильную сетку вершин с интервалом в 1 единицу.
- Карта высот содержит одно значение высоты R32 для каждой вершины
- В настоящее время я разрешаю поток только в 4 кардинальных направлениях (без диагоналей)
- Я использую Texture2D [int] как трафарет для вершин, которые я уже проанализировал
Текущий алгоритм:
- Когда инструмент ландшафта был активен и сейчас не ....
- Очистить «трафарет».
- Просканируйте всю местность для наименьшей высоты.
- Эта единственная точка является начальным входом в CS_Flood.
- CS_Flood делает проход по оси X.
- Каждая входная вершина проецируется в направлениях X и X + до 2048 раз.
- Поиск соседней вершины с координатой OOB указывает край местности в этом направлении. CurrentPoint добавляется в буфер BoundaryPoints, и цикл проецирования для этого направления прерывается. Это было легко и прекрасно работает каждый раз.
- Соседние вершины с высотой> = высота текущей вершины отмечены в трафарете и добавлены в буфер NextPass.
- Соседние вершины с высотой <высота текущей вершины указывает на пик гребня и завершает цикл проекции. Будущая итерация заливки может обтекать основание гребня, подниматься по его «задней» стороне и обнаруживать тот же гребень во второй раз.
- Для этой цели любые пиковые / ребристые точки, обнаруженные более одного раза, не будут BoundaryPoint.
- Любые пиковые / ребристые точки, обнаруженные ровно один раз, добавляются к BoundaryPoints, и цикл проецирования в этом направлении прерывается.
- CS_Flood делает проход по оси Z с тем же кодом, используя точки, сгенерированные проходом по оси X, в качестве входных данных.
- Прямо сейчас CS_Flood продолжает чередоваться между двумя направлениями бесконечно. В конце концов, я завершу весь цикл всякий раз, когда завершается CS_Flood и буфер NextPass пуст.
В идеале, в этой точке BoundaryPoints должны содержать каждую вершину, которая встречается на границе естественного дренажа. Капли воды, падающие в пределах границы, в конечном итоге текут к тому же низкому месту Капли воды приземляются за границей и уходят «куда-то еще».
Потом:
- Не очищая трафарет, повторно просмотрите местность на предмет самой низкой вершины без трафарета.
- Итерация CS_Flood.
- Повторяйте, пока трафарет не заполнится (или что-то подобное).
3D трудно воспринимать с этими цветами; это показывает линии контура на интегральных возвышениях:
(отверстие, окруженное бермой около края)
Существует около 10 уникальных способов стока через вершину; придание каждому из них уникального цвета выглядит следующим образом:
(видимые круглые следы инструмента, хорошо видны «гребни»)
Это показывает каждую точку, сгенерированную CS_Flood, границей или иным образом, как POINTLIST:
Алгоритм почти всегда работает . Иногда это даже работает правильно. В других случаях алгоритм явно содержит правильную форму, но будет продолжать выводить точки бесконечно долго. Как видно на третьем скриншоте, иногда это запутывается. Должна быть другая ситуация / фактор, который я упустил из виду. Я был бы признателен за любую помощь в поиске моего контроля или предложений о более простых и / или более изящных способах решения проблемы.
MissingPoint! может быть включен путем ленточной поддержки алгоритма для добавления каждого нового обнаруженного BoundaryPoint в буфер NextPass. Во время следующего прохода, 99% очков, сгенерированных этим лейкопластырем, будут тратить небольшое количество времени на GPU, определяя, что они никуда не денутся и ничего не делают. Во время первого прохода отправка LowestPoint вместе с другими точками NextPass также будет обрабатывать этот конкретный сценарий.
Я знаю, что это правдоподобно, и, если у меня будет достаточно времени, я смогу помочь ему достаточно, чтобы делать то, что я хочу. Я хотел бы сделать это лучше, умнее, быстрее, если это возможно, и у меня пока недостаточно опыта, чтобы знать лучше.
Ответы:
Когда капля «пыталась» посетить вершину, трафарет был помечен с
InterlockedExchange
использованием «исходного значения», чтобы определить, был ли он уже нанесен по трафарету (хотя я просто переписал его).Лучший алгоритм, который я придумал, дал наводнению «блокнот» и единственное правило: «не течь вниз по склону» (высота равна или больше). Это устранило почти все сложные тесты. Хотя он обычно не течет по пикам / гребням, он течет вдоль них, потому что смежные вершины «плоские». Это иногда позволяет каплям пробираться мимо хребтов.
Каждая из «слишком далеких» точек, таким образом, «течет» и будет течь «в» зону дренажа (останавливается на 1) или нет (останавливается на 0). «Ноты» отбрасываются, а исправленная блокнотная копия копируется в «финал». Если финал уже нанесен по трафарету, блокнот будет удален. (Будущее: эти столкновения должны все вместе представлять внешнюю границу текущей области дренажа.)
На 10FPS:
«Ноты» отображаются красным цветом, как только большая область копируется в финал и становится зеленой, тогда алгоритм повторяется для оставшихся нестандартных областей.
источник