Pull to refresh

Comments 16

Дальше потребностей художника автор явно не пошел.
Благодаря кэшу вершин можно отрисовать два полигона почти так же быстро, как один, если они имеют общие вершины.

Чтобы кэш работал данные должны быть правильно сгруппированы. Однако
Они имеют абсолютно одинаковое количество полигонов и пикселей, но так как поверхность левого имеет более длинные, узкие полигоны, чем у правого, его рендеринг будет более медленным.
Для более эффективного использования кэша полигоны обычно группируют в полосы, что и видно на левом примере. В правом кэш частично идёт лесом (или совсем, зависит от порядка расположения вершин в памяти)
Эта геометрия со сглаженным затенением состоит из 18 треугольников и имеет 16 общих вершин. Для плоского затенения 18 треугольников нужно 54 (18 x 3) вершины, потому что ни одна из вершин не является общей
Неверно. Плоское затенение в общем случае не требует дублирования вершины. Как минимум OpenGL при включении плоского затенения просто дублирует нормаль первой вершины на все, Т.е. количество вершин должно быть лишь не меньше, чем количество полигонов, т.е. 18 в данном случае.
Неверно. Плоское затенение в общем случае не требует дублирования вершины. Как минимум OpenGL при включении плоского затенения просто дублирует нормаль первой вершины на все, Т.е. количество вершин должно быть лишь не меньше, чем количество полигонов, т.е. 18 в данном случае.

Это как? В старом конвейере мы делаем glShadeModel(GL_FLAT) и он каким-то образом может «дублировать» нормаль (не имею представления каким, но пусть умеет). Допустим у нас есть два соединенных треугольника в одной вершине, которые лежат в разных плоскастях. И пусть эта вершина ялвяется первой для каждого из двух треугольников. Получается, что как минимум в общих точках нормали будут разных при flat shading, и соответственно вершины будут разными. То есть если взять сферу, то ничего «дублироваться» вообще не будет. Об этом и написано в примере.

Как сделать «дублирование» в нефиксированном конвейере я вообще не имею представления, да еще и так, чтобы данные о нормали были только в одном экземпляре (не кладется такой вариант на архитектуру GPU). Может Metal, Vulkan, DirectX12 и позволяет такое провернуть — не знаком я сними достаточно близко — но если смотреть с архитектуры GPU, то все равно нужно иметь копии данных для каждой вершины.
«Плоский» атрибут дублируется из вершины, назначенной «главной» (provoking vertex), значения атрибута в остальных вершинах игнорируются. «Главные» вершины назначаются по своему номеру в примитиве (обычно самая первая вершина, но можно выбрать и другой индекс). Конкретно в случае нормалей при плоском шейдинге их легче считать в геометрической стадии шейдера, а не хранить в данных.
Геометрический шейдер жутко тормозная штука, я их вообще предпочитаю обходить стороной. Для плоских нормалей в шейдере используются спецификатор интерполирования flat , который делает как раз то что вы сказази: The value will not be interpolated. The value given to the fragment shader is the value from the Provoking Vertex for that primitive.

Таким образом чтобы сделать плоский шейдинг достаточно добавить спецификатор. В моем случае я перенес рассчет освещения в вершинный шейдер, значительно освободив фрагментный.
Неверно. Плоское затенение в общем случае не требует дублирования вершины. Как минимум OpenGL при включении плоского затенения просто дублирует нормаль первой вершины на все, Т.е. количество вершин должно быть лишь не меньше, чем количество полигонов, т.е. 18 в данном случае.

А если в вертексном шейдере сделать оффсет вдоль нормали? Полигоны разойдутся? Или останутся слитными? По идее, если вертексы не дублируются, а дублируются только нормали, ничего не выйдет.
Проверил на кубе в юнити — полигоны разошлись. Значит кроме нормалей еще и позиции разнятся.
В вертексном можно переместить вершину, а не сдублировать (для расхождения нужно 2 вершины). Для того, чтобы разошлись — нужен геом шейдер, который может по оригинальному мешу сгенерить новый, с новым комплектом вершин.

Тут вопрос не о возможности, а о том, как конкретно юнити работает с вершинами. Возможность такая есть, а вот использовать её или нет — дело конкретного движка. Если у него полностью отдельные полигоны — то их можно и в вершинном раздвинуть.
Что есть «оффсет нормали»? С таким не сталкивался. Вы это точно в вершинном шейдере делали?

«Оффсет вдоль нормали». В вертексном шейдере прибавить нормаль вершины к ее позиции.
image
Да, возможно Юнити и не использует то, что вы описали. Но она использует OpenGL. Все может быть.
Да, чуть позже сообразил.
На самом деле скорее всего базовые примитивы с плоским шейдингом имеют отдельные полигоны просто по тому, что так проще генерить. Собственно, вероятнее всего, выходные модели программ 3D моделеров так-же, поскольку модель должна быть универсальной. Но вот перед использованием модели её можно обработать под конкретное использование, в частности чтобы сократить количество вершин.
базовые примитивы с плоским шейдингом имеют отдельные полигоны просто по тому, что так проще генерить. Собственно, вероятнее всего, выходные модели программ 3D моделеров так-же

На самом деле в моделях используют оба подхода.
Причем длаже в пределах одной модели это может встречатся.

Используют это для того, чтобы при сглаживании у модели оставались острые углы (где вешины общие для полигонов там сработает сглаживание, а где вершины разные, но просто располагаются по одним координатам, оставляя полигоны фактически изолированными — там останется острый угол).
Например острые шипы на доспехах — сам доспех будет сглаженным изображаться, а четырехугольные шипы остануться острыми.
Альтернатива — разбивать модель на разные меши и отображать не просто модель, а разные части с разными настройками, что никак не выйдет быстрее.
Это понятно. Тут речь про общий подход. Плоский шейдинг требует определённой доводки меша, так что найти готовую модель такую, вероятно, будет сложно.

А кто-то из знающих подскажите пожалуйста почему для рисования 3д-моделей принято использовать полигоны а не кривые? Ведь кривые позволят на порядки сократить объем передаваемой на видеокарту информации — для сплайна из десятка контрольных точек потребуется передать от сотен до тысяч точек полигона в зависимости от детализации. А ведь gpu вполне себе умеет рисовать кривые просто выполняя проверку попадания по формуле во фрагментном шейдере, без всяких там циклов (вот например статья про формулу для квадратичной кривой Безье) и по производительности получится ничем не медленней какого-нибудь стандартного освещения во фрагментном шейдере.

Метод в gpugems работает для плоских фигур со сплайновыми границами. Для сплайновых поверхностей можно использовать патчи, тесселируемые в геометрической части конвеера, но там только прямоугольные патчи и это в итоге все равно получается триангуляция, просто динамически создаваемая (ну и геометрические шейдеры не слишком дешевые). Трехмерный BREP с произвольными сплайновыми патчами растеризовать без триангуляции это уже крайне нетривиальная задача, даже в кадах таким не заморачиваются, разве что если качественный рендеринг потребуется, но там вообще рейтрейс и не реалтайм. Короче, слишком много приседаний ради неочевидного профита. (количество информации сокращается конечно, но все равно текстуры съедят гораздо больше, если говорить об играх, а вычислительная нагрузка возрастет) Но вообще не треугольная растеризация в играх есть, можно в пример привести тот же Claybook, но там идет трассировка SDF, а не brep
Да, объем передаваемый на видеокарту немного уменьшится (именно немного, т.к. зачастую текстуры весят больше чем модели), но будет затрачено время, чтобы преобразовать эти кривые в те-же самые полигоны.

Может поэтому в статье рассмотрена только работа со сплайнами, а не с 3Д объектами, ведь все алгоритмы визуализации, освещения, да того-же наложения текстур требуют полигонов, так что не думаю, что малый выигрыш во времени передачи данных на GPU даст в итоге какойто профит, учитывая что все эти кривые придется преобразовывать в 3д объекты, и все-равно, в итоге в памяти будет храниться не только сам 3Д объект из полигонов, но и кривые, по которым он был построен… т.е. памяти еще больше будет потрачено чем при простой загрузке модели.
А что сплайны разве считать не надо?
По скорости отрисовать готовые полигоны быстрее, чем просчитывать каждый кадр сложный сплайн.
Статье не хватает численных, хотя-бы очень-очень приблизительных результатов оптимизации.

Интересно было бы почитать подобное рассмотрение обработки видеокартами техники Ray tracing

Only those users with full accounts are able to leave comments. Log in, please.