Russian Qt Forum

Программирование => Общий => Тема начата: Igors от Декабрь 17, 2014, 10:32



Название: Архитектура VBO
Отправлено: Igors от Декабрь 17, 2014, 10:32
Добрый день

VBO (vertex buffer object) - это данные хранящиеся на видеокарте (напр вертексы, нормали, полигоны, цвет).  Использование VBO заметно ускоряет рисование. Приложение оперирует с индексами этих данных (фактически это хендлы).

Сделал просто - храню хендл вместе с массивом данных. Напр контейнер вертексов имеет хендл VBO и.т.д. Это кажется очевидным - ведь исходная геометрия не меняется. А если вертексы изменились - тогда и данные VBO пере-создаются.

Однако вылезла неприятная деталь - в одном из окон пользователь может указать так называемый "flat shading", в то время как в других должен показываться gourand, phong и др. К сожалению, для "flat" нужна др геометрия подаваемая в OpenGL, т.е. др полигоны, вертексы. Эту дыру я просто заткнул, для режима "flat" не использую VBO, а рисую по-старинке glBegin/glEnd. Это конечно позорно медленно, зато у меня нет никаких доп данных и минимум кода. Поскольку flat используется редко, в году раз - проконало.

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

И почему-то вспомнилось: "кривая архитектура", "изменить архитектуру приложения" и.т.п. не раз звучавшие на этом форуме :)  Поэтому внимательно слушаю Ваши рекомендации.

Спасибо


Название: Re: Архитектура VBO
Отправлено: __Heaven__ от Декабрь 17, 2014, 11:40
Буфер с продублированными нормалями так и не появилось желание использовать?


Название: Re: Архитектура VBO
Отправлено: __Heaven__ от Декабрь 17, 2014, 11:47
Ни разу не пробовал, но, возможно, прокатит следующее:
Хранить нормали к каждому треугольнику в текстуре. В вершинном шейдере смотреть id выводимой вершины, делить её на 3, тем самым получая id нормали в текстуре. Передавать этот id (нормали) в фрагментный шейдер. А в том извлекать нормаль и применять к цвету фрагмента.


Название: Re: Архитектура VBO
Отправлено: Igors от Декабрь 17, 2014, 12:26
Буфер с продублированными нормалями так и не появилось желание использовать?
Ну вот за это меня точно выгонят и больше не возьмут  :)

Ни разу не пробовал, но, возможно, прокатит следующее:
Хранить нормали к каждому треугольнику в текстуре. В вершинном шейдере смотреть id выводимой вершины, делить её на 3, тем самым получая id нормали в текстуре. Передавать этот id (нормали) в фрагментный шейдер. А в том извлекать нормаль и применять к цвету фрагмента.
Утопия хотя бы потому что каждый фейсет может иметь любое вертексов от 1 до 4 включительно.

Не надо сваливаться с специфику OpenGL (все равно без толку), а посмотрим с точки зрения пресловутой архитектуры. Примерная схема

Исходные данные (RAM) ---> данные для "прямого" рисования (VBO)
-----------------------------> данные для "фейсетного" рисования (???)
-----------------------------> данные для "детального" рисования (должны быть в VBO)

Понятно что я должен создать нужные буфера VBO, но где хранить их хендлы и как ими управлять?


Название: Re: Архитектура VBO
Отправлено: __Heaven__ от Декабрь 17, 2014, 13:51
У вас имеются точки и линии, которые нужно освещать?
Разбивать квадратики на треугольники тоже не вариант? (В 3.0 GL_QUADS deprecated).
Передавать id нормали в текстуре для каждой вершины через VBO? Но тут мало что сэкономим.

Буфер с продублированными нормалями так и не появилось желание использовать?
Ну вот за это меня точно выгонят и больше не возьмут  :)

А чем это хуже, чем рисовать phong? Там такое же количество нормалей необходимо. Кстати, их можно подсчитать/продублировать налету (при включении режима flat) и засунуть в vbo, оставив только хэндл - данные из RAM можно удалить. Ну или рассчитывать нормали при каждой прорисовке и выводить их без участия VBO, по завершению прорисовки затирать.


Название: Re: Архитектура VBO
Отправлено: Igors от Декабрь 17, 2014, 16:18
У вас имеются точки и линии, которые нужно освещать?
Точки и линии могут освещаться, как и wireframe (аттач).

А чем это хуже, чем рисовать phong? Там такое же количество нормалей необходимо.
Возьмем грубую модель сферы, она имеет напр 144 полигона (для простоты - все треугольники) и 74 вертекса. Теперь мы хотим рисовать с фейсетными нормалями. Значит у каждого треугольника "свои" 3 вертекса, итого 144 * 3 = 432. Что Вы скажете о программисте который увеличил число базовых данных в 432 / 74 = 5.83 раза?  :)

Не надо искать какие-то "железячные" решения, лезть в шейдеры, id и.т.п - все это мелко. Вопрос был об архитектуре. Поверьте, она есть даже с OpenGL  :)


Название: Re: Архитектура VBO
Отправлено: __Heaven__ от Декабрь 17, 2014, 17:07
Может gl_InstanceID (https://www.opengl.org/sdk/docs/man/html/gl_InstanceID.xhtml) чем-то поможет. Только он доступен с OpenGL 3.1.


Название: Re: Архитектура VBO
Отправлено: __Heaven__ от Январь 31, 2016, 12:18
Нашлось ли решение?


Название: Re: Архитектура VBO
Отправлено: Igors от Январь 31, 2016, 12:35
Нашлось ли решение?
Для режима "flat" нет, так и рисую glBegin/glEnd. Для показа деталированной модели - да


Название: Re: Архитектура VBO
Отправлено: Racheengel от Январь 31, 2016, 15:31
Нашлось ли решение?
Для режима "flat" нет, так и рисую glBegin/glEnd. Для показа деталированной модели - да

вместо glBegin/glEnd можно хотя бы glDrawArrays заюзать, будет заметно быстее.


Название: Re: Архитектура VBO
Отправлено: Igors от Январь 31, 2016, 15:54
вместо glBegin/glEnd можно хотя бы glDrawArrays заюзать, будет заметно быстее.
Ну вот такой я неграмотный, про glDrawArrays/glDrawElements мне ничего не известно  :'(
Вы тему-то читайте


Название: Re: Архитектура VBO
Отправлено: Racheengel от Январь 31, 2016, 23:48
Так а что надо пользователю? Видеть либо модель с текстурой, либо wireframe? Какая тогда разница в организации полигонов?


Название: Re: Архитектура VBO
Отправлено: __Heaven__ от Февраль 01, 2016, 06:54
Racheengel, там проблема в нормалях. Требуется задавать нормаль для примитива, а не вершины. А opengl такого не позволяет сделать при glDrawArrays/glDrawElements не дублируя координаты, нормали.


Название: Re: Архитектура VBO
Отправлено: Racheengel от Февраль 01, 2016, 11:36
Racheengel, там проблема в нормалях. Требуется задавать нормаль для примитива, а не вершины. А opengl такого не позволяет сделать при glDrawArrays/glDrawElements не дублируя координаты, нормали.

То есть полигоны (их координаты) не меняются? Если да, то нормали я бы генерировал/хранил отдельно для каждого случая и переключался бы на нужные данные при смене view. Как вариант.


Название: Re: Архитектура VBO
Отправлено: Igors от Февраль 01, 2016, 12:03
То есть полигоны (их координаты) не меняются? Если да, то нормали я бы генерировал/хранил отдельно для каждого случая и переключался бы на нужные данные при смене view. Как вариант.
Ладно, начнем "от печки". Сколько вертексов имеет простейший кубик? Человек знакомый с OpenGL ответит 24 (а не 8 как начинающий). Зачем 24 если углов-то всего 8? Потому что OpenGL рисует "по вертескам" (а не "по фейсам"). Один вертекс = одна нормаль и одна текстурная координата, счетчики должны совпадать во всех подаваемых рисованию массивах. Разные фейсы могут использовать разные вертексы, но при этом будут использовать и их нормали.  Если мы хотим видеть "грани" (как у кубика) то вынуждены создать вертексы для каждой фейсы (грани). Итого 6 * 4 = 24. В каждом углу будут 3 вертекса с разными нормалями. Как говорят "все расшарено"


Название: Re: Архитектура VBO
Отправлено: Racheengel от Февраль 01, 2016, 12:39
Сколько вертексов имеет простейший кубик? Человек знакомый с OpenGL ответит 24 (а не 8 как начинающий).

Сам по себе кубик имеет 8 вертексов, остальное - это представление модели, которая визуализируется. Зависит от того, как рисовать. Если квадами - то 24, если треугольниками - то, считаем, 36 (по 6 точек на грань, если без стрипов). А если индексами, то зададите вы все те же 8 вертексов, плюс массивы индексов.

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


Название: Re: Архитектура VBO
Отправлено: Igors от Февраль 01, 2016, 13:28
Зависит от того, как рисовать. Если квадами - то 24, если треугольниками - то, считаем, 36 (по 6 точек на грань, если без стрипов). А если индексами, то зададите вы все те же 8 вертексов, плюс массивы индексов.
Кубик из тр-ков имеет 12 фейсов и те же самые 24 вертекса. Тут уже одни вертексы шарятся, другие нет. Просто берем квады и каждый бьем на 2 тр-ка, никакие новые вертексы не нужны. Создать 36 можно но бессмысленно.

Сам по себе кубик имеет 8 вертексов, остальное - это представление модели, которая визуализируется.
Рендерится конкретное представление, а не что там "само по себе/существу"

Но количество вертексов то у вас не изменяется.
Для кубика нет, у него и так все "расщарено", а в общем случае меняется (аттач)

Что ж так плаваете в азах? Это же на уровне "популярных знаний"  :'(


Название: Re: Архитектура VBO
Отправлено: Racheengel от Февраль 01, 2016, 14:05
Для кубика нет, у него и так все "расщарено", а в общем случае меняется (аттач)

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

О каких объемах данных идет речь? Играет ли роль скорость визуализации? Ну т.е. это live preview или пользователю пара секунд не критична при свитче отображений?

В общем случае вам все равно нужно для каждого случая генерировать разные данные. Вопрос только в том, чем мы будем жертвовать - памятью или производительностью?


Название: Re: Архитектура VBO
Отправлено: Igors от Февраль 01, 2016, 14:53
Так я про это и спрашивал - что меняется для каждого из представлений?
Ну, теперь понятно, что "меняется все" - и нормали, и полигоны.
Полигоны никто не трогал, меняются только нормали. Оба варианта нормалей у меня в памяти всегда есть, они по-любому нужны. Но с гребаным OpenGL мне никак не удается просто "заменить нормали".

О каких объемах данных идет речь? Играет ли роль скорость визуализации? Ну т.е. это live preview или пользователю пара секунд не критична при свитче отображений?

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

[OFF]К сожалению, Вы взяли на вооружение стиль Верес'а, по-простому говоря "на шару".
Цитировать
Напишу-ка так. Не, я конечно не уверен, да и занимался этим немного и хз когда. Ну а вдруг прокатит? А если нет - не беда, вот мне и растолкуют почему. Так я и буду получать знания через ля-ля на форуме, без всяких усилий.
Это не очень корректно по отношению к ТС - мне нетрудно разжевать, но не для чисто праздного любопытства. А главное - минимум 5-летний опыт Верес'а показывает что такой метод ничего не дает. Результаты ужасны, причем все хуже и хуже  :'(
[/OFF]
 


Название: Re: Архитектура VBO
Отправлено: Racheengel от Февраль 01, 2016, 15:51
Полигоны никто не трогал, меняются только нормали. Оба варианта нормалей у меня в памяти всегда есть, они по-любому нужны. Но с гребаным OpenGL мне никак не удается просто "заменить нормали".

У Вас на скриншоте 2 модели шара - высокополигональная слева и низкополигональная справа.
Каким образом тогда Ваша цитата связана с Вашим скриншотом?
Они взаимоисключающие.
Либо Вы делаете higl-poly & low-poly model для разных случаев (естественно, и нормали в этом случае разные)...
Либо, если меняются ТОЛЬКО нормали - то рисуйте через glDraw[Arrays|Elements], тогда у Вас будет возможность безболезненно переключаться между массивами нормалей :)

Оффтоп: а при чем тут Верес и его стиль ???


Название: Re: Архитектура VBO
Отправлено: __Heaven__ от Февраль 01, 2016, 16:06
Racheengel, в обоих вариантах одинаковое количество полигонов. Меняются только нормали. Это обман зрения.


Название: Re: Архитектура VBO
Отправлено: Racheengel от Февраль 01, 2016, 16:29
Racheengel, в обоих вариантах одинаковое количество полигонов. Меняются только нормали. Это обман зрения.

Да, но:

Цитировать
Но появилась новая фича - пользователь хочет иметь возможность показа измельченной (грубо говоря триангулированной) модели

Я так понимаю, что тут не только в нормалях разница, а имеется в виду высокополигональная модель, которую Игорь не хочет хранить в памяти, а хочет запузырить на видеокарту через VBO :)

Или опять не так?


Название: Re: Архитектура VBO
Отправлено: Igors от Февраль 02, 2016, 10:51
Либо, если меняются ТОЛЬКО нормали - то рисуйте через glDraw[Arrays|Elements], тогда у Вас будет возможность безболезненно переключаться между массивами нормалей :)
2 полигона модели сферы что выше

1-й ссылается на вертексы (0, 1, 2, 3)
2-й ссылается на вертексы (4, 5, 1, 0)  // т.е. вертексы 0 и 1 шарятся этими полигонами

Все вертексы имеют нормали для левой картинки выше.  Также меня есть предвычисленные нормали для обоих полигонов. Ну и как я их "подменю"?


Название: Re: Архитектура VBO
Отправлено: Racheengel от Февраль 02, 2016, 13:19
А как Вы нормали для каждой из сфер храните?
Я бы ожидал массивы такой же длины, как и для вертексов, с 4 нормалями на полигон.

Т.е. для варианта 1 было бы:
V = [v0, v1, v2, v3] [v4, v5, v1, v0]
N1 = [n0, n1, n2, n3] [n4, n5, n6, n7]

А для варианта 2:
V = [v0, v1, v2, v3] [v4, v5, v1, v0]
N2 = [m0, m1, m2, m3] [m4, m5, m6, m7]

где n - нормали, рассчитанные для "модели 1", а m - нормали, рассчитанные для "модели 2".
Далее с помощью glNormalPointer(N1) или glNormalPointer(N2) переключаетесь между ними.

Надеюсь, написал понятно (Вы же используете glNormalPointer и glVertexPointer в коде?)


Название: Re: Архитектура VBO
Отправлено: Igors от Февраль 02, 2016, 13:35
Вы же используете glNormalPointer и glVertexPointer в коде?
Вот как раз для них и не выходит

А для варианта 2:
V = [v0, v1, v2, v3] [v4, v5, v1, v0]
N2 = [m0, m1, m2, m3] [m4, m5, m6, m7]
Счетчики V и N(N2) должны быть одинаковы. Если 6 вертексов (v0..v5) то и нормалей будет использоваться 6 (а не 8 ). И если подаются одни и те же индексы v0, v1 для 2 полигонов, то и нормали будут юзаться одни и те же. Др словами у OpenGL ОДЫН индекс на все - про все.

Пробовали учить человека играть в преферанс "на практике"?
Цитировать
.. а самая старшая черва ?
.. а 6 пик - вистовать обязательно ?
.. а мизер - это когда не брать взяток?  
...
...
Как это ужасно  :)


Название: Re: Архитектура VBO
Отправлено: Racheengel от Февраль 02, 2016, 13:54
Ок. Вроде я понял проблему. Похоже, ничего не остается, как дублировать вертексы. Имхо всяко лучше, чем тормозные glBegin/glEnd. Да, с одной стороны возрастет расход памяти на координаты вертексов, но с другой Вы можете тогда отказаться от массива индексов и использовать glDrawArrays.

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

Но Вы так и не сказали, о каких объемах данных идет речь, насколько велики модели? Иногда лучше пожертвовать памятью ради производительности, перейти на 64-бит архитектуру, например.


Название: Re: Архитектура VBO
Отправлено: __Heaven__ от Февраль 02, 2016, 14:07
Я дополню. Если использовать буферы, то жертвовать придётся памятью GPU. Тем самым можно освободить ОЗУ.


Название: Re: Архитектура VBO
Отправлено: Igors от Февраль 02, 2016, 15:11
Похоже, ничего не остается, как дублировать вертексы...
Ну как-то Ваш вывод не блещет оригинальностью и/или свежими идеями  :) И кроме банального "альтернатива скорость - расход памяти" напомню еще фактор "объем кода". Паршивенький glBegin/glEnd = один маленький метод, а вот "еще одно представление данных" - ой нет

Но Вы так и не сказали, о каких объемах данных идет речь,
"Общий случай" - юзер решает какие модели грузить и сколько. В общем мульены - дело давно рядовое.

Возможно, извращениями с шейдерами можно добиться лучших результатов, но тут я не советчик. Не юзал шейдеры ни разу.
В шейдере заставить использовать фейсетную нормаль - неск строк (если не одна). Но тут есть страшное НО - я не могу ограничиться только этим. Связавшись с фрагментным шейдером я должен выполнить ВСЕ операции (найти и отмапить все текстуры, обсчитать все источники света и.т.п.) и в конце-концов выдать на гора цвет (суб)пикселя. Др словами нормальной pipeline эта железяка не имеет, можно только перекрыть шейдинг целиком. Спрашивал на др форумах можно ли как-то найти дырочку чтобы туда вклиниться - ну пока без успеха :'(



Название: Re: Архитектура VBO
Отправлено: Igors от Февраль 02, 2016, 15:22
Я дополню. Если использовать буферы, то жертвовать придётся памятью GPU. Тем самым можно освободить ОЗУ.
Так это собсно и есть тема для обсуждения. "Flat" рисование (правая сфера) было просто к слову (просто ситуевина принципиально та же). Обсуждение "кого же освобождать" лишено смысла - ясно что данные надо хранить на GPU.

Итак вот у нас появилось "другое/альтернативное представление", в случае деталированной модели оно неизбежно, тут уже не заткнуть. И мы хотим "запузырить ее на видеокарту через VBO" :). Ваши действия?


Название: Re: Архитектура VBO
Отправлено: Racheengel от Февраль 02, 2016, 15:30
И кроме банального "альтернатива скорость - расход памяти" напомню еще фактор "объем кода". Паршивенький glBegin/glEnd = один маленький метод, а вот "еще одно представление данных" - ой нет

Да ну, какой там объем то :) Пара вызовов glNormalPointer, glVertexPointer, да еще glDrawArrays в конце)
Но если памяти жалко, можно фрагментами рендерить.
Сгенерили часть данных в вектора - отрендерили - повторили.
Других решений пока не вижу, тем более все равно у Вас нормали заранее просчитываются.

А шейдеры, конечно, слишком уж узкоспециальное решение, согласен.


Название: Re: Архитектура VBO
Отправлено: Igors от Февраль 02, 2016, 16:01
Да ну, какой там объем то :)
У Вас что там, Верес под капотом?  :)

Пара вызовов glNormalPointer, glVertexPointer, да еще glDrawArrays в конце)
Ну да, ну да. А всю этажерку векторов позиция+нормаль+color+UV1+UV2..+UV8 папа Карло будет создавать и хранить?  

Но если памяти жалко, можно фрагментами рендерить.
Сгенерили часть данных в вектора - отрендерили - повторили.
А не будет ли тогда glBegin/glEnd пошустрее?


Название: Re: Архитектура VBO
Отправлено: Racheengel от Февраль 02, 2016, 16:26
А всю этажерку векторов позиция+нормаль+color+UV1+UV2..+UV8 папа Карло будет создавать и хранить? 

Но ведь между glBegin/glEnd у Вас тоже не пусто сейчас? :)

А не будет ли тогда glBegin/glEnd пошустрее?

Не уверен :) Когда мы от них на glDrawArrays переключились, получили как минимум 2х прироста.
И это с создаванием этажерок в памяти и т.д. :)


Название: Re: Архитектура VBO
Отправлено: __Heaven__ от Февраль 02, 2016, 16:40
А вы случаем не тестили glDrawArrays против glDrawElements? По памяти второй экономичнее, а как по скорости отрисовки?


Название: Re: Архитектура VBO
Отправлено: Igors от Февраль 02, 2016, 16:52
Но ведь между glBegin/glEnd у Вас тоже не пусто сейчас? :)
Менее 50 строк, там никаких новых данных создавать не нужно

А вы случаем не тестили glDrawArrays против glDrawElements? По памяти второй экономичнее, а как по скорости отрисовки?
glDrawArrays побыстрее