ЗАСТОСУВАННЯ СУЧАСНИХ ЗАСОБІВ OPENGL В QT



Розглянуто спосіб поєднання функціоналу OpenGL з засобами Qt–фреймворка для досягнення найвищої швидкодії при обробці великої кількості графічних об’єктів.

APPLICATIONOF MODERN OPENGL Tools IN QT

Tumanov Vladyslav Valeriyovych, NTUU “KPI”

Ukraine, Kyiv

Overviewingthe way of combining functionality of OpenGL with Qt–framework to achieve the highest performance when processing large amounts of graphic objects.

Keywords: Qt-framework, OpenGL, shader, VertexBuffer Object, performance

Вступ

Qt–фреймворк [1] широко відомий завдяки зручним та легким у використанні інструментам для розробки інтерфейсу користувача. Також він надає різноманітні засоби для роботи з графікою та растровими зображеннями. Головним інструментом для малювання в робочій області вікна є клас QPainter, який забезпечує оптимізовані функції для виконання більшої частини графічних операцій. Він може намалювати все: від простих ліній до складних форм, таких як сектори і криві Безьє. Він також може відображати вирівняний текст і растрові зображення. QPainter може працювати на будь-якому об'єкті, який успадковує клас QPaintDevice.

Проте такий спосіб відображення має один суттєвий недолік – низьку швидкодію. Справа в тому, що QPainter взаємодіє з API операційної системи, який в свою чергу використовує процесор для виконання графічних операцій на найнижчому рівні без застосування апаратного прискорення, яке може надати GPU (відео карта). Врезультаті, маємо значне сповільнення при малюванні вже порядку 105 таких примітивів як прості лінії. Така проблема небуде фігурувати при статичному відображенні об’єктів, проте гостро стане коли потрібно буде постійно перемальовувати вид для, наприклад, обертання всієї графіки навколо довільної вісі.

Підхід представлений у даній роботі базується на використанні можливості Qt суміщати в собі найпотужніші засоби OpenGL [2] для обробки графіки на апаратному рівні що в результаті приносить майже миттєву швидкодію, яка є критичним показником для програм, призначення яких полягає в обробці великої кількості графіки. Особливо це стосується різних САПР, таких як AutoCAD, OrCAD,Graphite та інші.

Програмна основа

Для роботи з OpenGL, Qt пропонує спеціальний набір класів, головним з яких є QGLWidget, що надає функціональні можливості для відображення OpenGL графіки, вбудовані в додаток Qt. Все що вам необхідно, це відкрито (public) успадкувати від нього свій власний клас, і надалі використовувати його як і будь-який інший об’єкт класу QWidget з урахуванням того, що тепер ви можете виконувати графічні операції як за допомогою QPainter, так і використовуючи засоби OpenGL.

QGLWidget надає три зручні віртуальні функції, які користувач бібліотеки може перевизначити в підкласі для виконання типових завдань OpenGL:

paintGL() – призначений для опрацювання графіки засобами OpenGL. Викликається щоразу, коли віджет повинен бути оновлений;

resizeGL() - встановлює параметри виду екрана, проекції на екран і т.д. Викликається щоразу, коли віджет змінює розміри (а також, коли він показаний в перший раз, тому що всі новостворені віджети автоматично отримують подію зміни розміру);

initializeGL() - встановлює контекст відображення OpenGL, визначає списки відображення і т. д. Викликається один раз, під час ініціалізації вікна.

Іншим важливим класом є QGLFunctions, який надає крос-платформенний доступ до OpenGL API. Він пропонує функціонал, який доступний для більшості настільних або вбудованих реалізацій OpenGL. Найдоцільніше використовувати цей клас в формі захищеного (protected) наслідування.

Програмна реалізація

Розроблюваний клас має бути наслідуваний від QGLWidget відкрито та від QGLFunctions захищено. Використання апаратного прискорення означає малювання всієї графіки за допомогою шейдерів [3] (програми, які компілюються в інструкції безпосередньо для GPU), та представлення великих кількостей об’єктів уформі Vertex Buffer Object (VBO). Отже, клас повинен містити наступні групи полів:

· об’єкти QGLShaderProgram (програм шейдерів) для всіх примітивів та текстур з якими працюватиме програма;

· поля атрибутів для кожної програми шейдерів (тип GLuint);

· поля для збереження матриць виду та проекції, які будуть використовуватись при малюванні примітивів шейдерами (тип QMatrix4x4);

· поля для збереження uniform–індексів, що зв’язують матрицями програми та матрицями шедерів(тип GLint);

· поля для збереження ідентифікаторів VBO для кожного буфера (тип GLuint);

· інші поля, такі як масиви для зберігання буферів,тексту програм шейдерів, координат текстур і т. ін.

Перевизначений метод initializeGL() повинен починатись з виклику initializeGLFunctions(), який ініціює спеціальні функції OpenGL, в контексті поточного вікна. Після цього можна створювати буфери та об’єкти програм шейдерів, супроводжуючи їх перевіркою результату зв’язування, яка покаже чи підтримуються такі шейдери конкретною системою, та чи нема синтаксичних помилок в коді шейдерів. З вже скомпільованих шейдерів отримуються атрибути та юніформи (глобальні змінні в шейдерах) для їх подальшого використання в якості прив’язки до буферів.

Перевизначення методу resizeGL() полягає в отриманні відповідної до поточних розмірів вікна матриці проекції за допомогою стандартних засобів OpenGL, а також, надає можливість легко створити фонове зображення відповідних розмірів:

  1. спершу створюється порожня картинка QPixmap з розмірами вікна;

  2. за допомогою QPainter на ній малюється те що маєбути фоном фікна;

  3. за допомогою методу bindTexture() на основі об’єкта Qpixmap створюється текстура, яку тепер можна намалювати відповідним шейдером як статичне фонове зображення.

Так можливості стандартних класів Qt органічно доповнюють можливості OpenGL.

І, врешті-решт, в методі paintGL() має бути реалізовано малювання буферів об’єктів на клієнтській області вікна за допомогою відповідних програм шейдерів.

Порівняння швидкодії

Для демонстрації переваг засобів OpenGL над стандартними методами Qt мною було розроблено експериментальну програму, в якій реалізовано два вікна, які малюють задану кількість ліній на робочій області. Одне вікно використовує для цього об’єкти QPainter та QPainterPath. Інше – використовує метод, описаний в даній статі. Програма заміряє час, витрачений на малювання змісту вікна. Експеримент проведений з використанням процесора AMD E–450 APU with Radeon HD Graphics. Заміри проводились для 105,106, та 107 ліній. Усереднені результати наведені в таблиці 1.

Табл. 1. Результати замірів

Висновки

Отримані в результаті експерименту результати цілковито підтверджують переваги засобів OpenGL над стандартними класами Qt–ферймворка, які б оптимізовані їх методи не були. Єдиною значною перевагою готових класів є їх зручність та простота, адже використання сучасних засобів OpenGL потребує значного досвіду та знань. Написання складних шейдерів або, так званого, «ренедерера» графіки (модуля, який відповідає за правильну та впорядковану роботу засобів OpenGL в межах програми) не є тривіальними завданнями, тож якщо швидкодія не є приорітетом, то краще і простіше використати стандартні методи Qt.

Перелік посилань

  1. QtDocumentation [Електронний ресурс] – Режим доступу: https://doc.qt.io

  2. OpenGLintroduction [Електронний ресурс] – Режим доступу: https://open.gl

  3. OpenGL ESShading Language Reference [Електронний ресурс] – Режим доступу:http://www.shaderific.com/glsl/
  • Рецензент: к.т.н., доц. каф. АУТС Катін П.Ю.
May 24, 2016