LINUX.ORG.RU

[C][openGL] адаптивная триангуляция (для LOD)

 ,


0

2

Замучился уже гуглить, ткните меня, пожалуйста, носом, кто с этим делом сталкивался...

Задача у меня такая: хочу отобразить изображение 3000х3000 в виде трехмерной карты высот (для наглядности), т.е. наибольшей интенсивности соответствует наивысшая точка поверхности, нулю - нулевая. Проблема с «тупой» отрисовкой при помощи GL_TRIANGLE_STRIP по всем точкам заключается в сильных тормозах и жутких требованиях к объему памяти (опорные точки, нормали, да еще и цветовая карта, если хочется и цвет добавить).

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

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

☆☆☆☆☆

на современной видеокарте такая сетка не должна особо тормозить, если тебе просто визуализировать надо.

нужный тебе алгоритм называется ROAM. он не gpu-friendly (хотя может на современных GPU и его можно делать). я щас немного отстал от современных тенденций в realtime-3d, но последний раз когда интересовался — просто заранее били на блоки одинакового размера, и генерировали для них несколько LODs (geomipmaps).

waker ★★★★★
()

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

pacify ★★★★★
()
Ответ на: комментарий от waker

Про ROAM как раз сейчас читаю, но он тормознутый какой-то...

Разбивать на блоки тоже не получится: придется держать в оперативке целое дерево блоков с разным разрешением и комбинировать их, исходя из текущего положения «наблюдателя». По-моему, это будет намного более расточительным, чем вычислять триангуляцию в реальном времени (точнее - для каждого перемещения «наблюдателя») на GPU...

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от pacify

Я уже думал было хранить вейвлет-образ изображения и восстанавливать новое путем обратного вейвлет-преобразования «урезанного» образа (т.е. с обнулением ненужных деталей). Но вот как бы триангуляцию считать на GPU, чтобы хотя бы десяток fps получить...

Eddy_Em ☆☆☆☆☆
() автор топика

Самый простейший вариант - реализовать geomipmapping (легко загугливается).

Cовременный Ъ вариант с использоваением GPU - geometry clipmaps.

Raving_Zealot ★★
()
Ответ на: комментарий от Eddy_Em

ну можно делать выборку из карты высот по расстоянию от камеры, и генерировать несколько сеток разной детальности. например, в радиусе [0,20] от наблюдателя максимальная детализация, в (20,50] понижай разрешение сетки, и т.д.

тогда адаптивность не понадобится. стыки, правда, могут быть видны. зависит от того что у тебя за карта высот..

waker ★★★★★
()
Ответ на: комментарий от Raving_Zealot

Cовременный Ъ вариант с использоваением GPU - geometry clipmaps.

Что-то не гуглится ничего под линукс...

Raving_Zealot

Полезный линк по теме: http://vterrain.org/

Спасибо за ссылку, но скомпилировать не смог: куча ошибок и непонятных зависимостей (про которые ничего не говорится...)

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от waker

ну можно делать выборку из карты высот по расстоянию от камеры, и генерировать несколько сеток разной детальности. например, в радиусе [0,20] от наблюдателя максимальная детализация, в (20,50] понижай разрешение сетки, и т.д.

тогда адаптивность не понадобится. стыки, правда, могут быть видны. зависит от того что у тебя за карта высот..

Это оно и есть, только непонятно, как этот алгоритм оптимально реализовать...

Eddy_Em ☆☆☆☆☆
() автор топика

Все-таки считаю надо спросить.
Как отрисовка выполняется? glBegin? VBO?
На каком оборудовании, какие драйвера?

Warbozz
()
Ответ на: комментарий от Raving_Zealot

На http://vterrain.org/LOD/Implementations/ был, ничего интересного не нашел (точнее, там много интересного, но либо по ссылкам черт те сколько кода, а не библиотека + пример использования, либо по ссылке ничего не компилируется)...

На http://vterrain.org/LOD/Papers/ тоже заходил. Но ленивый я, не хочу с нуля писать - вдруг что готовое есть...

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Warbozz

Как отрисовка выполняется? glBegin? VBO? На каком оборудовании, какие драйвера?

Да, обычные glBegin(GL_TRIANGLE_STRIP), оборудование - nVidia 9800GT. CUDA-SDK установлен.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

Тогда ты проиграл.
Это примерно в 1000 раз медленнее VBO.

В супербиблии OpenGL это (на тот момент GL1.5 расширение) объясняли забавно следующим образом:
glBegin/glEnd - вы по одной координате паравозом отправляете в соседний город. Причем ждете когда придет ответ, что координата добралась успешно.
VBO - сразу всех грузите в паравоз.

От себя добавлю, что Vertex Buffer Objects - своего рода кусок памяти, который заливается в ОЗУ видеокарты с подсказкой, как этот кусок с данными будет использоваться. На моей FX5900 (пыль по сравнению с 9800) прирост увеличивался в 800-1000 раз.

Warbozz
()
Ответ на: комментарий от Eddy_Em

хехе, неудивительно что тормозит тогда :)

даже простой glDrawElements/Arrays из system memory без vbo во много раз быстрее.

waker ★★★★★
()
Ответ на: комментарий от Warbozz

Да, еще забыл...
Если ты постоянно обновляешь сцену (какая-нибудь анимация), то по факту ты много раз выполняешь кусок glBegin()...glEnd(), т.е. вновь и вновь передаешь координаты.
С помощью VBO или (вроде бы) Vertex Pointer (предок VBO) ты можешь залить координаты любых вершин (нормали, текстуры, цвета) в память один раз и изменять в дальнейшем только куски без необходимости заливать заново.

А вообще, поищи на сайте dev нвидии документ «Batch, batch, batch!» (точно из этих 3х слов, но пунктуацию не помню) - он о введении VBO.

Warbozz
()
Ответ на: комментарий от Warbozz

Спасибо, про VBO не знал. Поищу рабочие примеры - может, можно будет и без извращений обойтись...

Eddy_Em ☆☆☆☆☆
() автор топика

Попробовал буферы VBO. Не то, что надо: для работы с ними нужно по крайней мере гигабайт 16 основной ОЗУ + хотя бы гигабайта 4 оперативки видеокарты. Попробовал заполнять простенькие массивы синусоидой, нормали еще даже не добавлял. В итоге для несчастной картинки 3000х3000 требуется на одни только буферы вершин и цветов больше сотни мегабайт выделить. Думаю, если нормали добавить, вообще получится супертормоз... И это еще при использовании GL_TRIANGLE_STRIP для рисования поверхностей... А уж если попробовать GL_TRIANGLES, вообще придется в полтора раза больше памяти выделять...

Так что, продолжу искать оптимальные алгоритмы триангуляции и построения изображения «на лету» (считать будет CUDA, так что со скоростью больших проблем быть не должно).

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

ты что-то попутал.
предположим такой формат вершин:
float pos[3]
float normal[3]
uint32 color;
28 байт

3000*3000=9млн
это 252M памяти

+ индексный массив, предположим что ты побьешь сетку на куски, чтобы 16битных индексов хватило.
грубо говоря, 18млн треугольников, это 36М на индексы.

с накладными расходами получаем около 300М на все. в 512 метровой видюхе вполне вмещается. но можно и в оперативе хранить.

waker ★★★★★
()
Ответ на: комментарий от waker

с накладными расходами получаем около 300М на все. в 512 метровой видюхе вполне вмещается. но можно и в оперативе хранить.

Тормоза при этом жесточайшие - т.е. надо либо «родной» openGL подключать (который данные в оперативке видеокарты хранит и не гоняет их туда-сюда), либо, все-таки, придумывать более оптимальный подход.

И да, 3000х3000 - довольно маленькая картинка. В планах до 100К х 100К.

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

> т.е. надо либо «родной» openGL подключать

а, так у тебя видеокарта без аппаратно-ускоренного opengl-драйвера? с этого было начинать..

В планах до 100К х 100К.

и это тоже надо было сразу говорить. тут тебе явно надо делать geomipmaps, хранить их на диске, и подгружать по мере надобности, выгружая ненужное.

тут даже на байтовую карту высот надо 10 гигабайт.

вообще, все решаемо, но без аппаратного ускорения opengl далеко не уедешь..

waker ★★★★★
()
Ответ на: комментарий от waker

а, так у тебя видеокарта без аппаратно-ускоренного opengl-драйвера? с этого было начинать..

У меня nvidia 9800GT.

Про «родной» openGL я имел в виду библиотеки, идущие в комплекте с CUDA...

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

> Тормоза при этом жесточайшие

Подождите, в первом сообщение Вы написали «отобразить изображение», т.е. речи о интерактивности не шло. Задача изменилась? Не могли бы Вы в терминах графики сказать что нужно?

И да, 3000х3000 - довольно маленькая картинка. В планах до 100К х 100К.


Смотрите, Вы пишите, что требуются огромных размеров память для записи координат всех вершин. Однако, если нет речи об интерактивности и нужно получить именно изображение, то тогда Вы можете заливать вершины кусками - например:
1) разбить Ваши 100к х 100к на 10000 квадратов
2) залить все вершины i-го квадрата
3) отрендирить - получили изображение - дампите его на диск в tga (простой формат - не составит труда написать алгоритм)
4) переходите к следующему квадрату

Сборку сдампленных изображений написать не составит труда

Warbozz
()
Ответ на: комментарий от Warbozz

Поясню: мне хочется отображать большие изображения (16 бит серого) в виде карт поверхностей. Причем интерактивно, чтобы можно было двигать туда-сюда, приближать/удалять, двигать освещение... Вообще, для 3000х3000 вполне хватит места в оперативке (вершины + нормали, если все в один цвет окрасить), но тормозит отрисовка...

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

Давайте, если это возможно, зальёте исходники куда-нибудь.

Если нет - расставьте счетчики (gettimeofday) на генерации данных, закачке и отрисовке, чтобы определиться, что это она тормозит.

Warbozz
()
Ответ на: комментарий от Warbozz

Давайте, если это возможно, зальёте исходники куда-нибудь.

Вот. Я нашел какой-то пример (он на SDL, но т.к. пока все равно экспериментирую, оставил как есть), на его основе попытался что-нибудь простенькое нарисовать...

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

я правильно понимаю, что тебе надо отображать эти карты в виде сверху в ортогональной проекции?

если так — то можно обойтись без полигонов. грузишь свою карту (видимую ее часть) в текстуру размером с экран, и считаешь освещение в fragment shader. возможно, придется карту преобразовать в normal map.

waker ★★★★★
()
Ответ на: комментарий от waker

я правильно понимаю, что тебе надо отображать эти карты в виде сверху в ортогональной проекции?

В том то и дело, что нет: должна быть возможность «перемещать» наблюдателя, т.е. как будто он «пролетает» над заданной поверхностью и имеет возможность вертеть головой :)

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от Eddy_Em

ок. значит тебе обычный рендер ландшафта нужен.. какие делают в играх, например. не пробовал искать готовые движки для этого дела, где-нибудь на http://www.devmaster.net/engines/ например?

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

а нормальные 3д движки это должны уметь из коробки (хотя вот насчет 100Kx100K не уверен).

waker ★★★★★
()
Ответ на: комментарий от waker

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

Eddy_Em ☆☆☆☆☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.