GLGDI+ или «переходим с GDI+ на OpenTK»
Думаю, многим приходилось сталкиваться с проблемой, что GDI+ тормозит, а тормозит, потому что не ускоряется железом.
Вот и я как-то писал редактор уровней
и понял, что GDI+ мне больше не хватает, нужно переходить на что-то ускоренное, причем за минимальное время. Немного погуглив, я решил остановить свой выбор на библиотеке OpenTK.
OpenTK (Open Toolkit) — это низкоуровневая библиотека, которая является враппером для OpenGL, OpenGL ES, OpenCL и OpenAL. Данная библиотека предназначена для игр, научных приложений, а также для любых других приложений, которым требуется 3D-графика, аудио и вычислительная функциональность. OpenTK является кроссплатформенной библиотекой и работает как на Mono, так и на .NET.
Почему выбор пал именно на OpenTK? Во-первых, OpenTK предоставляет класс GLControl (является прямым наследником UserControl), который позволяет упростить переход на данную библиотеку. Во-вторых, в комплекте идет класс TextPrinter, который позволяет довольно просто выводить текст на экран. В-третьих во время гугления я нашел небольшой архив «Engine.zip» с набором классов для 2D-отрисовки, инициализации OpenGL и прочими приятностями.
Сначала я планировал описать какие подводные камни встретились мне при переходе на OpenTK, но, вспомнив, что вопрос перехода с GDI+ на что-то быстрое является довольно популярным, решил написать небольшую библиотеку, которая мимикрирует под GDI+ и выложить ее в открытом доступе. Назвал я ее GLGDI+. Помните, что это легковесная библиотека и содержит только самый необходимый минимум и не пытается полностью копировать API GDI+. Она содержит классы GLGraphics, GLImage и GLMultiImage. GLGraphics содержит следующие методы:
- DrawString — выводит текст
- DrawImage — рисует GLImage
- DrawLine — рисует линию
- DrawRectangle — рисует прямоугольник
- FillRectangle — рисует закрашенный прямоугольник
- DrawPoint — рисует точку
- DrawPoints — рисует несколько точек
- DrawMultiImage — рисует GLMultiImage (для отрисовки нескольких одинаковых изображений разом — это гораздо быстрее, нежели рисовать по одному, если таких изображений много)
Некоторые моменты
Я все же опишу некоторые моменты, с которыми мне пришлось столкнуться при использовании OpenTK. На сайте OpenTK есть хорошие туториалы, которые я, конечно же, не читал, ознакомься я с ними, и парой проблем было бы меньше. Но, что было, то было:
- Первое с чем я столкнулся: контрол вообще не перерисовывался при запуске, решилось просто, нужно не забыть вызвать метод SwapBuffers в конце OnPaint, GLControl уже имеет встроенную функциональность DoubleBuffer, нужно только переключить буфер
- Следующий момент, о который я споткнулся — это черные прямоугольники вместо изображений. Решалось вызовом image.SetBlending() перед отрисовкой, сейчас в библиотеке все изображения рисуются с блендингом, поэтому с этим проблем быть не должно
- Когда я второй контрол перевел на рельсы OpenTK, то оказалось, что первый контрол после этого перестал выполнять свои функции, решилось вызовом метода MakeCurrent в OnPaint перед отрисовкой элементов
- TextPrinter (основа для DrawString) иногда падает при выводе текста, тут ничего не поделаешь — класс глючный и на определенных сочетаниях качества отрисовки, шрифта и размера шрифта он падает, пришлось подбирать шрифт и размер
- Еще нужно отслеживать, что контрол загрузился и только после этого работать с OpenTK/GLGraphics, а также проверять, что контрол не в режиме дизайнера форм
- При изменении размеров контрола нужно не забыть вызвать GLGraphics.Resize(Width, Height)
Заключение
Библиотека лежит на GoogleCode, под BSD лицензией. Если кому понадобится — пользуйтесь на здоровье. Чтобы понять как работать с библиотекой — посмотрите исходный текст сэмпла, который идет в комплекте, он очень простой:
Все описанные выше «моменты» в нем учтены.
Данную библиотеку я пока не рекомендовал бы использовать для продуктов, нацеленных на массового пользователя — она слишком молода для этого, но в утилитах вполне пригодна к использованию.
На данный момент планов по развитию библиотеки у меня нет — мне ее функционала хватает. Но багфиксы и патчи приветствуются :)
Судя по тому, что я прочитал на OpenTK форуме, TextPrinter (используется для вывода текста) в будущем будет исключен из библиотеки, но, возможно, в отдельный проект. Так что его судьба пока что туманна. Сейчас он в состоянии Deprecated, поэтому дает warnings при компиляции библиотеки.
Вот теперь редактор карт работает значительно быстрее и ничего не тормозит, чего и вам желаю!
UPD: забыл указать ссылку на сайт OpenTK
UPD2: исправил баг с путями в исходниках сэмпла (как в архиве, так и в SVN)