Top.Mail.Ru

Уроки OpenGL. Часть 2. Рисование основных 2D-фигур.

Продолжаем учебный курс по работе с графикой при помощи OpenGL! И сегодня мы займемся рисованием основных 2D-фигур, таких как треугольник, прямоугольник, линия итд. Первый урок, посвященный OpenGL можно найти тут - ссылка. Итак, приступим...

Создадим пустой проект и добавим в него класс MainScene, как в предыдущей статье, а в сам класс - три пустые функции:

void MainScene::initializeGL()
{
}

void MainScene::resizeGL(int nWidth, int nHeight)
{
}

void MainScene::paintGL()
{
}

Напоминаю, что я использую в качестве среды разработки Qt Creator, соответственно при создании класса мне нужно наследоваться от QGLWidget.

Прежде, чем приступать к рисованию графических примитивов, давайте разберемся с конфигурацией OpenGL. Для начала нам необходимо установить цвет фона. Пусть будет белый. Для этого в функцию initializeGL() добавим вызов следующей функции:

glClearColor(1.0, 1.0, 1.0, 1.0);

Первые три параметра соответствуют трем составляющим цвета - красной, зеленой и голубой (rgb). Единица означает максимум составляющей, таким образом, мы получаем чистейший белый цвет (все составляющие в максимуме = белый).

В функции main() добавляем создание сцены (объекта нашего класса) и задаем его размеры:

MainScene scene;
scene.resize(600, 600);
scene.show();

Собираем проект, запускаем и видим... Абсолютно черный экран. В чем же дело? А дело в том, что командой glClearColor() мы только задали цвет очистки экрана, но не произвели непосредственно очистку. Давайте добавим в функцию paintGL():

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

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

Итак, загружаем в матрицу проекции единичную матрицу и вызываем функцию glOrtho(). Эта функция преобразует изображение в соответствии с плоскостями отсечения, которые передаются в функцию в качестве аргументов. Допустим мы хотим, чтобы левая граница экрана соответствовала координате x = 0, а правая - x = 1. В свою очередь верх экрана - y = 1, а низ - y = 0. Ось z в нашем примере будет отвечать за расположение объектов относительно друг друга (чем ближе к нам объект, тем больше координата z, соответственно, ближние к нам объекты будут заслонять дальние). Зададим отображение по z от -1 - до 1:

void MainScene::resizeGL(int nWidth, int nHeight)
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
	glViewport(0, 0, (GLint)nWidth, (GLint)nHeight);
}

Командой glViewport() мы устанавливаем размер сцены равным размеру окна нашего виджета (600 * 600, как мы указали в функции main()). Поскольку весь этот код мы поместили в функцию resizeGL(), теперь при изменениях размеров окна наше изображение также будет изменяться и подстраиваться под новые размеры.

Пришло время перейти к рисованию. Давайте первый делом попробуем нарисовать треугольник. Вот полный код:

void MainScene::paintGL()
{
	glClear(GL_COLOR_BUFFER_BIT);

	glColor3f(0.25, 0.87, 0.81);
	glBegin(GL_TRIANGLES);

	glVertex2f(0.0, 0.0);
	glVertex2f(1.0, 1.0);
	glVertex2f(1.0, 0.0);

	glEnd();
}

Для начала задаем цвет - пусть будет бирюзовый ) Рисование будет производиться при помощи функций glBegin(), glEnd(). В качестве аргумента первой из этих функций мы передаем тип рисуемой фигуры, а все, что содержится между функциями - точки фигуры, в нашем случае - три вершины треугольника. Запускаем программу и вот он результат:

Рисование в OpenGL.

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

void MainScene::paintGL()
{
	glClear(GL_COLOR_BUFFER_BIT);

	glColor3f(0.25, 0.87, 0.81);
	glBegin(GL_TRIANGLES);

	glVertex2f(0.0, 0.0);
	glVertex2f(1.0, 1.0);
	glVertex2f(1.0, 0.0);

	glEnd();

	glColor3f(0.13, 0.56, 0.13);
	glBegin(GL_QUADS);

	glVertex2f(0.0, 0.5);
	glVertex2f(0.0, 1.0);
	glVertex2f(0.5, 1.0);
	glVertex2f(0.5, 0.5);

	glEnd();
}

Получаем квадрат, расположенный в соответствии с заданными нами координатами:

Рисование фигур в OpenGL.

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

void MainScene::paintGL()
{
	glClear(GL_COLOR_BUFFER_BIT);

	glColor3f(0.25, 0.87, 0.81);
	
	glBegin(GL_TRIANGLES);
	glVertex2f(0.0, 0.0);
	glVertex2f(1.0, 1.0);
	glVertex2f(1.0, 0.0);
	glEnd();

	glColor3f(0.13, 0.56, 0.13);
	
	glBegin(GL_QUADS);
	glVertex2f(0.0, 0.5);
	glVertex2f(0.0, 1.0);
	glVertex2f(0.5, 1.0);
	glVertex2f(0.5, 0.5);
	glEnd();

	glLineWidth(2.0);
	glColor3f(0.65, 0.16, 0.16);
	
	glBegin(GL_LINE_STRIP);
	glVertex2f(0.0, 0.5);
	glVertex2f(0.5, 1.0);
	glVertex2f(1.0, 0.5);
	glVertex2f(0.5, 0);
	glVertex2f(0.0, 0.5);
	glEnd();
}

Помимо цвета, также зададим толщину линии, и вот, что в итоге получилось:

Ломаная линия в OpenGL.

Конечно, рисование при помощи glBegin() / glEnd() является очень простым и удобным, но строго говоря с точки зрения быстродействия этот способ не очень оптимален. Гораздо большего можно добиться, используя массивы вершин, массивы индексов и массивы цветов. Именно этому и будет посвящен следующий наш урок, не пропустите и до скорых встреч на нашем сайте!

Полный проект с примером из статьи - OpenGLTest.

Подписаться
Уведомить о
guest

2 комментариев
Старые
Новые
Межтекстовые Отзывы
Посмотреть все комментарии
Руслан
Руслан
5 лет назад

У меня всплывает два окна и два белых

Александр
Александр
3 лет назад

Спасибо за урок!!!

2
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x