Как стать автором
Обновить

Комментарии 38

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

Есть ещё один вариант. Он описан здесь, я его реализовывал на OpenGL ES 2.0, писал небольшое приложение-рисовалку для Android, которое принимало по USB данные с графического планшета и определённым образом записывало их в буфер, чтобы отрисовку точек и все расчёты можно было делать прямо на GPU почти без участия CPU.

Давние конспекты по матлогике

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

"Ну если без дураков, то без дураков выполним..." (с) "Фитиль" 1976г

Вот так?

"Просили же 7 красных линий. А у вас их 5. Да ещё и бледные и кривые какие то. Короче, всё переделывай."

И прозрачных там 5, а не 3

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

  2. Можно нарисовать зеленую линию на цветном фоне, которая будет восприниматься красной - особенности человеческого цветовосприятия (точную пару цветов, увы, не вспомню).

  3. Делаем коэффициент отражения чернил комплексным числом - вуаля, можно рисовать красную линию прозрачными чернилами.

    Как видите, ничего невозможного. :)

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

Кто скажет, что это простраство неевклидово, пусть первым бросит в меня котёнка!

они не перпендикулярны

они не перпендикулярны

То есть Вы говорите нам, что не видите точки, в которых эти линии пересекаются под прямым углом? С эти не ко мне, с этим — к окулисту!

Кроме того, в архитектуре термин "красная линия" имеет конкретное значение. Она вроде как обычно красная, но вдруг её цвет можно переопределить, оставив функциональность "красной линии"? Ведь на чёрно-белой печати она чёрная, но называется всё равно красной.

Я именно за этим и пришёл :)

Так и не понял какую задачу вы упорно решали. Как нарисовать прямую линию? Как нарисовать симпатичную линию? Нарисовать линию постоянной толщины? Нарисовать линию максимально быстро? Или это урок по OpenGL?

Всё вместе. Как основная цель - показать, что рисовать линию толще одного пикселя/кегля не так просто как кажется на первый взгляд.

OpenGl был выбран как удобный инструмент, для отображения и демонстрации формул, на урок по нему тут явно не хватает материала

показать, что рисовать линию толще одного пикселя/кегля не так просто как кажется на первый взгляд.

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

Интересно, а почему в "закруглённом соединении" используется Безье, а не круг ? Ведь круг проще и быстрее

Кривую Безье можно задать одним уравнением с одной переменной, что удобно для объяснения и для построения.

С кругом есть два варианта:

  1. Позиционирование и масштабирование круга так, чтобы он соединял две линии

  2. Рисовать два отдельных сегмента

И в обоих способах придётся выполнить куда больше подготовительных вычеслений.

Поэтому и был выбран способ с Безье - проще объяснить, и всего одно уравнение

в пиксельном шейдере дорисовать круг в конце каждой линии, диаметром в её ширину

У вас не выйдет плавный переход из одной линии в другую. Чем толще будут линии, тем лучше сильнее это будет заметно.

что будет заметно?

или соединение двух линий разной толщины?

так оно и с безье коряво (и даже хуже) будет выглядеть если толщины совсем разные.

Проблемы начнутся, когда текстура на линии будет с альфой. Там где треугольники накладываюся, будет косяк.

Да, но это легко решается с помощью glAlphaFunc, glBlendEquation с параметрами GL_MIN либо GL_MAX, или же GL_DEPTH_TEST, что, конечно, намного проще, чем описанное в статье

Только есть нюанс - в статье об этой проблеме не слова.

Ниже я кидал скрины полупрозрачной одноцветной линии - нет артефактов. Думаю что при наличии текстуры эффект будет тот же

Спасибо за статью!

Мне всегда было интересно, так как простые линии, и кривые Безье можно описать уравнениями. Можно ли тогда обойтись лишь фрагментным шейдером, который на вход берет их параметры и растеризует их попиксельно с помощью там sdf…?

Да, и почему линий нет на аппаратном уровне?)

который на вход берет их параметры и растеризует их попиксельно с помощью там sdf…

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

Да, и почему линий нет на аппаратном уровне?)

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

Да, он сломан.
Во-первых макс ширина явно ограничена, это максимум для линии из статьи
Во-вторых места соединение её сегментов не обработаны
В-третьих нельзя использовать как материал ширину линий, а это значит нужно перед каждым вызовом запроса на рисование добавлять эту функцию.( когда через материал можно отрендерить сколько угодно линий за один запрос)(uniform я только для статьи в шейдерах на писал для простоты. По-факту там полноценный SSBO на всё и рендер через glMultiDrawArraysIndirect )

А ещё бы теперь для микроконтроллеров с ручной растеризацией. Чётная толщина становится не таким простым вопросом... А потом вспомнить про антиалиасинг...

Смутило вот это:

>> Метод на основе ортогональности

>> Точки на плоскости можно представить как вектора, показывающие направления и скорость

Какая скорость, при чём тут скорость ? Есть вектор, есть длина вектора aka модуль. Классическая терминология.

И вообще решение задачи реализовано в стиле древней Греции, в лоб через системы трёхэтажных уравнений. Понятно что гимнастика для ума и пр. Второй способ это переизобретение векторной алгебры. Вместо матриц 2x2 используются раздутые развёрнутые формулы. Зачем - непонятно.

Какая скорость, при чём тут скорость ? Есть вектор, есть длина вектора aka модуль. Классическая терминология.

Спасибо, поправил. Я в основном занимаюсь моделированием ветра, а там вектра это именно что скорость и направление. Вот и написал по-привычке.

Понятно что гимнастика для ума и пр.

Я старался ограничится геометрией для 9 класса и не вводить лишних абстракций.

Вместо матриц 2x2 используются раздутые развёрнутые формулы

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

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

А что, если эта кривая должна быть полупрозрачной? :D

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

Тогда уж стоит упомянуть Accumulation Buffer в OpenGL, и 3dfx T-Buffer.

Иногда удивляет, насколько сложные - простые вещи. Не задумываешься об этом

В качестве визуализации процесса будем использовать OpenGL, а именно геометрические шейдеры на языке GLSL. Всё что они делают — это берут на вход точки фигуры, а далее строят из них фигуры.

Геометрические шейдеры медленные и не всегда совместимые. Их используют как крайнюю мерю, когда количество вершин до запуска цепочки шейдеров не известно.

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

Мне нравится https://wwwtyro.net/2019/11/18/instanced-lines.html

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории