Войти
ПрограммированиеФорум2D графика и изометрия

Рисование карандаша

#0
13:19, 1 дек. 2016

Доброго вам дня Форумчане. Передо мной стоит простая но в тоже время не очень простая задача. Отрисовка карандаша. То есть, пользователь зажал мышь, начал таскать по экрану и рисуется некая кривая линия. Казалось бы все просто, пока не начал погружаться в дебри.

Первая проблема с которой я столкнулся это толщина линии. Так как пользователей приложения уже достаточно много использовать просто  GL_LINE_STRIP не получится, ибо на некоторых карточках это реально линия, с максимальной шириной пикселей в 10ть, а у некоторых OpenGL вообще софтверный и там толщина линии в 1 пиксель рисуется, что не задавай. Стало быть было решено каждую линию рисовать из двух треугольников, что бы можно было задавать толщину.

Вторая проблема, это сглаживание. Мультиалиасинг работает не везде, при том же софтверном OpenGL и линия выглядит ну уж очень страшно. Было решено добавить границы у линии, свехру и снизу  вот эта картинка хорошо описывает как сделано сглаживание

https://farm3.staticflickr.com/2904/14407050753_468309807d_o.png

того уже на каждую линию приходится по 8мь вертексов.

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

И то что меня волнует больше всего, не будет ли тормозить рисование такого рода, на достаточно больших линиях, тысяча или две точек. Тысяча точек это минимум 8к вертексов.


#1
15:15, 1 дек. 2016

а зечем линия в 2д должна геометрией рисоваться?

#2
15:20, 1 дек. 2016

Это связано с новыми компонентами Qt для рисования. Теперь если мы хотим нарисовать что то на QQuicKItem необходимо использовать компоненты QSG*. Насколько я понимаю компоненты QSG* преобразовывают вызовы в opengl и получается что по сути теперь весь qml отрисовывается через видеокарту, либо через софтверный opengl. У них есть конечно замена в виде QQuickPainterItem, но он по сути рисует поверх opengl окна и сильно начинает тормозить, так как у этого окна частота вызовов обновления выше.

#3
15:21, 1 дек. 2016

Почему бы не рисовать на текстуре?

#4
15:25, 1 дек. 2016

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

#5
18:52, 1 дек. 2016

1) Почему не разделить рендер на софтверный и хардверный? Определить по железу и рисовать для хардверных нормальную линию через GL_LINE_STRIP, а софтверным в опциях оставить либо линию (пускаем 5 линий из центра окружности и из 4 рандомных точек на границе), либо текстуру. Да, это расовая сегрегация, почему нет? Вы же не правозащитник, надеюсь?
2) "карандаш" и "рисовать линию" - немного разные задачи. Чуть-чуть, ага. Вы определитесь, какая именно задача стоит.
3) Если есть много клиентов без графения, почему не перейти на QPainter? Он, вроде, выбирает для отрисовки самый скоростной из доступных рендеров: GDI+, X11, OpenGL, DirectX. Ну да. не самая кошерная маца, но таки что поделать? Если стоит выбор между грехом и смертью, можно и свинного сала в шаббат таанита отведать.

#6
19:20, 1 дек. 2016

iLoled, разделение будет обязательно, данное решение как раз для софтверного рендера. Рисовать нужно карандаш, с этим большие сложности. Просто в моем понимании карандаш состоит из отдельных линий, но видимо я ошибался.

Раньше и рисовали через QPainter. Но рисовать нужно в рамках qml, а в последней версии Qt через QPainter в qml можно только в QQuickPainterItem который достаточно медленный.

#7
20:31, 1 дек. 2016
Не даром я qml не доверял! Нельзя просто взять и использовать javascript, не огребая за это.

Если быть занудой, то карандаш не оставляет широких сглаженных линий, это делает перо. Но да ладно.
Лично я бы попробовал QPainter'ом рисовать в текстуру и рендерил её, но для этого всё рисование придётся пробросить в плюсы, что может быть не айс.
По софтверным рендерам скажу так, любой комп, на котором поползёт Qt 5.6 может отрендерить 50к вершин на камне без особых лагов. К тому же после каждой набранной 1000 вершин можно делать рендер в текстуру и брать её подложкой.
#8
22:04, 1 дек. 2016

iLoled, все классы рисования и так в плюсах. Про QPainter и текстуру писал выше, это в крайнем случае. Сейчас хотелось бы найти алгоритмы или описание того как реализовать "перо" с помощью геометрии.

#9
10:40, 2 дек. 2016

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

#10
12:02, 2 дек. 2016

leonardo98, как я уже говорил это запасной вариант. Насколько понимаю, он уберет все достоинства использования компонентов QSG :-)

#11
22:58, 2 дек. 2016

ecspertiza
Погодите, какой QSG на программном геле? Какие перделки в софте для сапёров?

#12
11:43, 3 дек. 2016

ecspertiza
> Насколько понимаю, он уберет все достоинства использования компонентов QSG :-)
может стоит получше разобраться? чтобы быть уверенным, я вот никакой проблемы не вижу

#13
12:27, 4 дек. 2016

iLoled, я не понял ни слова :-)

leonardo98, как минимум появляется дополнительная прослойка в виде текстуры. Если бы я использовал декларатив и рисовал на прямую на итеме, то это было бы весьма приемлемо. Сейчас же мало того что мне нужно выполнить ту же операцию в QImage, но после этого загрузить\обновить текстуру, а после этого еще и отобразить текстуру.

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

ПрограммированиеФорум2D графика и изометрия

Тема в архиве.