Войти
ПрограммированиеФорумГрафика

Маска подводной части

Страницы: 1 2 Следующая »
#0
(Правка: 4:27) 3:03, 9 сен. 2019

Омг, написал тонну текста и @#$@#$ браузер по нажатию какой-то кнопки перешёл назад и всё сообщение стерто. Удобно.

Добрый день,
Пытаюсь построить маску над водой / под водой как на картинке
Изображение

Использую карту смещения FFT для воды.
Так как вершины ездят по оси XZ, то не возможно построить скринспейс маску подобным псевдокодом

1) преобразуем вершины скринспейс квада в мировые координаты worldPos
2) if (tex2D(FFT_DisplaceTex, worldPos.xz).y + waterLevel < worldPos.y) { под водой} 
else {над водой}
Если добавить смещение по осям XZ, то вершина может уехать куда угодно, даже за камеру. То есть рассчитать позицию уже не возможно.

Бьюсь 2-ой день над решением.

Были идеи:
1) Создать детализированный меш, повесить его на камеру ровно по границе near clip plane.
И сразу проблема, что если смещать вершины по оси перпендикулярно камере, то вершина клипается. То есть надо считать соседние вершины. А их может быть бесконечно много. Вариант отпадает.

2) Создать буфер глубины только меша воды + буфер глубины сцены. Можно получить мировые координаты поверхности воды и сцены. А значит имеем угол между плоскостью воды и сценой.
Но если на сцене объект под водой, то угол инвертируется. Как это фиксить не придумал. В дополнение, ниже и выше уровня воды, нет информации о глубине, а значит и нет информации о мировой позиции и нет корректного угла. Отпадает.

3) Ещё один грязный костыль. Например вода на высоте 2 метра.
Рисуем скринспейс воду (обратную сторону) как маску, например через vertexFace.
Далее расчитываем мировую позицию в другом скринспейс кваде. Проверяем, если текущая мировая высота пикселя ниже чем 2 метра, то заливаем белым. Соединяем 2 постэффекта и это почти похоже на то что нужно. Но всплывают проблемы. На границе под определенным углом видно ровную линию в 2 метра.


Что ещё можно придумать?


ps
Кажется придумал вполне рабочий метод.
Растягиваю огромный квад по размеру far clip, но по высоте не выше уровня воды. Квад всегда смотрит на камеру (по осям XZ) и залочен по Y.
Рисую квад, затем рисую меш воды с обратной стороной через vertexFace. Квад заливает область под водой, которая перекрывается в случае если мы смотрим на поверхность.
Почти что идеально, если не считать некоторые проблемы с тонкой границей на дальней поверхности, буквально в 1 пиксель. Не страшно, но работает.


#1
11:23, 9 сен. 2019
Создать детализированный меш, повесить его на камеру ровно по границе near clip plane.
И сразу проблема, что если смещать вершины по оси перпендикулярно камере, то вершина клипается. То есть надо считать соседние вершины. А их может быть бесконечно много. Вариант отпадает.

почему она будет клипаться если ты перпендикулярно камере ей манипулируешь?

#2
(Правка: 11:35) 11:32, 9 сен. 2019

Polyflow3d
> почему она будет клипаться если ты перпендикулярно камере ей манипулируешь?
Представь, у тебя есть линия из точек (поверхность водная) рядом с границей near plane. Near 0.3 (для примера), а сам квад например в 0.301. 
Ты смещаешь по XY, всё хорошо. Начинаешь смещать по Z в отрицательную сторону, и если Z будет больше чем разница между near plane и квадом, то есть больше чем 0.001, то вершина просто уезжает за камеру.
В реальности же, с максимальным ветром порядка 50 метров (для примера) в секунду, волны достигают нескольких десятков метров, а смещение при этом порядка нескольких метров. Даже взять near clip с запасом не возможно. Маска будет слишком далеко от камеры в таком случае.

#3
(Правка: 12:19) 12:11, 9 сен. 2019

Kripto289
Есть еще техника. Строишь вокруг камеры бокс, верхняя грань искажается идентично воде. Рисуешь отдельным пассом, в качестве профита имеешь маску подводной, надводной поверхности воды и подводного объема.

#4
(Правка: 13:33) 13:32, 9 сен. 2019

Ладно, я че-то прям не поленился сделать в максе демо как я себе представляю это надо делать.
Генерим меш исходя из пересечения near plane и воды. Не обязательно искать пересечения для сотни точек, можно интерполировать полученные результаты, ведь это волны. А так же можно прям там же в меше добавить кромку собственно пересечения. Короче простор для творчества не ограниченный.

#5
(Правка: 16:56) 16:51, 9 сен. 2019

Polyflow3d
> Ладно, я че-то прям не поленился сделать в максе демо как я себе представляю
> это надо делать.
> Генерим меш исходя из пересечения near plane и воды. Не обязательно искать
> пересечения для сотни точек, можно интерполировать полученные результаты, ведь
> это волны. А так же можно прям там же в меше добавить кромку собственно
> пересечения. Короче простор для творчества не ограниченный.
Дак это, у тебя волны просто в виде шума перлина, то есть обычные изменение высоты.
Мой псевдокод как раз работает с обычной высотой по Y

1) преобразуем вершины скринспейс квада в мировые координаты worldPos
2) if (tex2D(FFT_DisplaceTex, worldPos.xz).y + waterLevel < worldPos.y) { под водой} 
else {над водой}

И всё должно поломаться если добавишь смещение по оси XZ.
Для теста сделал карту смещения которую генерирую через FFT. Диапазон от -3 до 3. 
https://drive.google.com/open?id=1uXIawP1Ojswu8FQsTKojuvqvX_A7nnt5

#6
16:55, 9 сен. 2019

Dampire
> Есть еще техника. Строишь вокруг камеры бокс, верхняя грань искажается
> идентично воде. Рисуешь отдельным пассом, в качестве профита имеешь маску
> подводной, надводной поверхности воды и подводного объема.
Мм не совсем понимаю, бокс ограничен поверхностью воды или фруструмом камеры, как AABB box?
Если 1 вариант, то я как раз похожее и сделал, добавив огромный квад на расстоянии дальней плоскости камеры.
А если 2 вариант, то я не пойму как это работает.

#7
17:03, 9 сен. 2019

Kripto289
какая разница шум перлина или любой другой шум.Тебе надо найти пересечение лучей со своей водой в любом случае, а как именно это уже отдельная история.

И всё поломается если добавишь смещение по оси XZ.

смещение чего в оси XZ?
У тебя Y координата нормали воды может быть равна или меньше нуля что ли? 

#8
18:12, 9 сен. 2019

Kripto289
Клетку представь. Помести камеру в клетку с 0 вращением, но на позиции камеры. Вершины трансформируй как воду. Фактически это просто технический пасс, оформляющий тебе маску для последующего построцессинга. Размеры клетки подбирай в зависимости от своих требований по дистанции, на которой тебе нужна инфа о поверхности воды. Можешь хоть пол метра на пол метра, главное чтобы в zNear не соскользнуло и не обрезало картинку.

#9
19:28, 9 сен. 2019

Polyflow3d
> Тебе надо найти пересечение
> лучей со своей водой в любом случае, а как именно это уже отдельная история.
Мне кажется всё непонимание из-за того, что у нас могут быть разные алгоритмы нахождения пересечения. 
Polyflow3d
> какая разница шум перлина или любой другой шум.
Ну смотри. У тебя есть сетка вершин до и после XZ искажений  (вид сверху на воду). И зеленая линия это скрин спейс маска.
Как твой метод определяет какую вершину нужно использовать для зеленой линии?
Изображение

#10
(Правка: 19:47) 19:43, 9 сен. 2019

Dampire
> Клетку представь. Помести камеру в клетку с 0 вращением, но на позиции камеры.
> Вершины трансформируй как воду. Фактически это просто технический пасс,
> оформляющий тебе маску для последующего построцессинга. Размеры клетки подбирай
> в зависимости от своих требований по дистанции, на которой тебе нужна инфа о
> поверхности воды. Можешь хоть пол метра на пол метра, главное чтобы в zNear не
> соскользнуло и не обрезало картинку.
Ну да, это AABB box вроде.
Всё равно не пойму как это работает. Можно схематически нарисовать как это выглядит?
Например, по какому закону мне трансформировать вершины? Просто трансформировать вершины как вершины воды нельзя. Вблизи near plane у меня могут быть совершенно разные данные.
Попробую ещё раз изобразить, но уже вид от камеры.
Изображение
И это я просто их сместил по оси X. А ещё они смещаются по оси Z, то есть вершины могут ещё и клипаться камерой или добавляться новые, которые были клипнуты ранее.

Polyflow3d
> смещение чего в оси XZ?
> У тебя Y координата нормали воды может быть равна или меньше нуля что ли?
И как раз на картинке выше видно о каком смещении речь. Стрелочки не ровно вниз/верх направлены, они могут быть направлены в принципе в любую сторону.

#11
19:50, 9 сен. 2019

Kripto289
Есть меш воды, тебе тупо надо найти лучи пересечения с ней. Всё.



#12
20:05, 9 сен. 2019

Kripto289
Ты замкнуть меш воды можешь? Типа как-то так:

+ Показать

Ну чтобы весь объем воды был некоторым замкнутым куском. Если да - то построить "маску" воды после этого можно элементарно:
1. Выключаем любую работу с буфером глубины. Оставляем только колор буфер
2. Отодвигаем FarPlane так, чтобы FarPlane ничего не клипал
3. Включаем аддитивный блендинг (это тот, который GL_ONE, GL_ONE)
4. Рисуем наш замкнутый меш воды в R8 текстуру цветом 1/255
Все. Теперь в нашей текстуре хранятся чиселки, которые равны числу овердрава пикселей. Там где число овердравов нечетное - под водой. Там где четное - над водой.
#13
(Правка: 21:33) 21:25, 9 сен. 2019

Polyflow3d
> Есть меш воды, тебе тупо надо найти лучи пересечения с ней. Всё.

В юнити, как и любом игровом движке пересечение мешей разве что перебором вершин? Или о чём речь, не понимать.

#14
(Правка: 21:30) 21:29, 9 сен. 2019

MrShoor
> Ты замкнуть меш воды можешь? Типа как-то так:
Да, я как раз это и имел ввиду, когда добавлял квад на границе воды и far plane.
По сути и выходит такой недокубик :)
Правда в случае с таким квадратом, можно просто выводить vface как цвет.
Я остановился на таком методе, ибо у него появился неожиданный для меня плюс. Так как я рендерю воду в отдельный буфер глубины, то параллельно могу записывать и цвет. И в остальных местах расчеты маски уже не нужны, она готова из коробки, в прямом смысле слова :)

Страницы: 1 2 Следующая »
ПрограммированиеФорумГрафика