Урок 2 - Простые примитивы
В прошлом уроке мы рассмотрели инициализацию OpenGL. Этот урок будет посвящён рисованию и раскрашиванию простых примитивов: точка, линия, треугольник и квадрат.
В нашем прошлом примере изменим формат пиксела.
После строки
FillChar (pfd, SizeOf (pfd), 0);Допишем:
pfd.dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;Мы сообщили системе, что будет использоваться двойная буферизация. Это необходимо для того чтоб изображение не мерцало.
В процедуре создания Формы напишите:
glEnable(GL_DEPTH_TEST); // включаем проверку разрешения фигур (впереди стоящая закрывает фигуру за ней) glDepthFunc(GL_LEQUAL); //тип проверкиДалее в обработчике события Form1 OnResize создадим процедуру перерисовки нашего окна.
glViewport(0, 0, ClientWidth, ClientHeight); //выделяем область куда будет выводиться наш буфер glMatrixMode ( GL_PROJECTION ); //переходим в матрицу проекции glLoadIdentity; //Сбрасываем текущую матрицу glFrustum ( -1 , 1 , -1 , 1 , 1.25 , 100.0 ); //Область видимости glMatrixMode ( GL_MODELVIEW ); // переходим в модельную матрицу glLoadIdentity; //Сбрасываем текущую матрицу gluLookAt(5,5,5,0,0,0,0,0,1); //позиция наблюдателя InvalidateRect ( Handle,nil,False ); //перерисовка формыФункция glFrustum имеет 6 параметров, первые 4 из них, это границы отсечения: верхняя, правая, нижняя, левая. Последние 2 параметра – это передняя и задняя граница отсечения.
Функция gluLookAt имеет 9 параметров, первые 3 из них - позиция наблюдателя (x, y, z), следующие 3 параметра – точка наблюдения (x, y, z) и последние 3 параметра – вектор верха.
InvalidateRect ( Handle,nil,False ); перерисовывает форму гораздо быстрее, чем Form1.Repaint.
Для того, чтобы наше окно обновлялось надо вызвать процедуру FormResize до отрисовки примитивов.
FormResize(Sender); //процедура обновленияВсё, с приготовлением мы закончили, Теперь давайте приступим к рисованию примитивов и начнём мы с точки. Все фигуры рисуются в логических скобках glBegin(param); и glEnd; где param – тип рисуемого примитива.
glBegin() может иметь один из следующих параметров:
- GL_PONTS - точка
- GL_LINES - линия
- GL_TRIANGLES - треугольник
- GL_QUADS - квадрат
- GL_POLYGON – многоугольник
Теперь нарисуем точку, в процедуре FormPaint после очистки буфера цвета запишем следующий код:
glPointSize(20); // размер точки glBegin(GL_POINTS); glVertex3f(-2,5,1); glEnd;

Вот мы и получили очень большую точку в 20 пикселов :). Теперь давайте изменим цвет точки функцией glColor3f(R,G,B);
Эту функцию следует вызывать перед заданием позиции каждой вершины.
Раскрасим в красный цвет:
glPointSize(20); // размер точки glBegin(GL_POINTS); glColor3f(1,0,0); glVertex3f(-2,5,1); glEnd;

Точку мы нарисовали. Теперь нарисуем линию. Делается это точно так же как и точку. Т.к. линия состоит из 2 вершин то функцию glVertex3f(x, y ,z) будем вызывать 2 раза:
glBegin(GL_LINES); //рисуем линию glColor3f(1,0,0); {раскрасим первую вершину} glVertex3f(-1,0,1); //позиция первой вершины glColor3f(0,1,0); {раскрасим вторую вершину} glVertex3f(-4,5,1); //позиция второй вершины glEnd;Допишем этот код и получим:

OpenGL сам делает плавное перетекание цвета между вершинами. Поучается довольно красиво.
Не хватает квадрата и треугольника. Давайте нарисуем!
glBegin(GL_TRIANGLES); //рисуем треугольник glColor3f(1,0,0); glVertex3f(0,5,1); //первая вершина glColor3f(0,1,0); glVertex3f(1,4,1); //вторая вершина glColor3f(0,1,0); glVertex3f(-1,4,1); //третья вершина glEnd; glBegin(GL_QUADS); //рисуем квадрат glColor3f(1,0,0); glVertex3i(-1,1,0); //первая вершина glColor3f(0,1,0); glVertex3f(1,1,-0); //вторая вершина glColor3f(0,1,1); glVertex3f(1,-1,-0); //третья вершина glColor3f(0,0,1); glVertex3f(-1,-1,0); //четвёртая вершина glEnd;

Вроде бы получилось.
В примере данного урока я сделал небольшое дополнение: при нажатии стрелки вправо вся система координат поворачивается вправо функцией glRotatef(угол, x, y, z) где x, y, z – координаты оси поворота, а при нажатии на стрелку влево, то вся система координат поворачивается влево.
Можете поэкспериментировать и нарисовать что-нибудь другое.
В следующем уроке мы будем работать с освещением и нарисуем объёмные геометрические фигуры с падающим на них светом.
Добавил(а): Drimer | Дата: 2012-12-05 | |
в примере одно ))) а тут другоє))))
![]() |
Добавил(а): Doggy | Дата: 2013-01-11 | |
не пойму зачем FormResize(Sender). Рисунок с ней рябит при перетаскивании формы, а без нее все норм (рисунок сохраняется).
И еще - что это за wglMakeCurrent(0,0); - в первом уроке он есть а во втором он тупо мешает (с этой строкой не работает прога)
|
Добавил(а): Doggy | Дата: 2013-01-11 | |
а, и еще - что такое SwapBuffers(Canvas.Handle);
в первом уроке его небыло
|
Добавил(а): Doggy | Дата: 2013-01-12 | |
![]() ![]() ![]() ![]() |
Добавил(а): Klesh | Дата: 2013-01-12 | |
wglMakeCurrent(0,0); - удаляет созданный контекст воспроизведения. В первом уроке мы просто инициализировали OpenGL ничего не рисуя, поэтому контекст нам был не нужен. В этом уроке используется двойная буферизация, чтобы не было мерцания, сначала сцена отрисовывается в задний буфер, а затем разом выводится в передний, то есть на форму. Эту процедуру выполняет функция SwapBuffers(Canvas.Handle);
|
Добавил(а): Doggy | Дата: 2013-01-12 | |
ясно. спасибо. я правда пока еще плохо понимаю что такое контекст воспроизведения, но будем постепенно разбираться.
![]() |
Добавил(а): susczanski | Дата: 2013-04-04 | |
і, все-таки, для чого FormResize? Чому не можна той код прописувати відразу в FormPaint?
![]() |
Добавил(а): susczanski | Дата: 2013-04-05 | |
Переведу, наверно так понятнее.
В Ваших в уроках все основные действия (оброботка клавиатуры, мыши, прорисовка и т.д.) выполняются в процедуре formpaint. Мне же в проэкте надо создать цыкл, в конце которого должна выполняться прорисовка 3-д. Пробовал вызывать с цыкла formpaint, что-то не так. Пробовал всю прорисовку всунуть всам ц
жикл но тогда глючит formresize. Подскажите, пожалуйста, что делат?
|
Добавил(а): Klesh | Дата: 2013-04-07 | |
Конечно можно и засунуть код FormResize в FormPaint, это я так сделал чтоб было удобнее и за одно обрабатывалось сжатие/растяжение формы, оно и так обработается но это будет не синхронно . Здесь замкнутый цыкл сначала при создании формы она перерисовывается, выполняется FromPaint, следовательно выполнится FormResize, а там есть функция InvalidateRect ( Handle,nil,False ); которая опять все сотрёт с формы и её придется снова перерисовывается (FormPaint) и так по кругу. Вам надо стереть InvalidateRect и вставить в конец вашего цикла тогда форма перересуется 1 раз.
|
Добавил(а): Klesh | Дата: 2013-04-07 | |
и еще цыкл который вы хотите сделать не должен быть в FormPaint или FornResize, например в обработчике нажатия на кнопку.
![]() |
Добавил(а): susczanski | Дата: 2013-04-08 | |
Супер, спасибо
![]() |
Добавил(а): susczanski | Дата: 2013-04-08 | |
А как сделать так, чтоб вместо формы графика была на Image? Просто заменить Handle на Image1.Canvas.Handle не получаеться...
![]() |
Добавил(а): Klesh | Дата: 2013-04-10 | |
Да можно передавать вещественные числа, у вас скорее всего ошибка в типе переменной которую вы передаёте или или используете функцию которая принимает только целый тип(glVertex3i(x,y,z: integer)). Последняя буква в названии функции говорит о типе передаваемых данных: i - integer, f - Single и все вещественные типы (Double тоже), fv - ссылка(Pointer). Попробуйте glVertex3f(x,y,z: Single).
![]() |
Добавил(а): Klesh | Дата: 2013-04-10 | |
На Image выводить не получится, не знаю почему
![]() ![]() |
Добавил(а): почти человек | Дата: 2014-04-14 | |
не знаю почему, но у меня выводится только пустая форма, хотя выполнял всё по инструкции.
|
Добавил(а): kuza2011zaika | Дата: 2015-04-19 | |
У меня форма вся пустая. Почему так?
|
Добавил(а): R1D16ST29 | Дата: 2015-08-06 | |
glutSolidCube(1); почему то не знает как оператор, а другие (от opengl) знает
![]() ![]() |
Добавил(а): Nesf | Дата: 2017-03-14 | |
Если у вас выводится пустая форма, то у вас включился режим двойной буферизации, поэтому в конце обработчика события OnPaint следует написать команду SwapBuffers;
|
Добавил(а): dimonsky | Дата: 2017-07-03 | |
GetDC(handle) вместо canvas.handle, и убрать вызов FormResize. Тогда получается конфетка.
|
-
У меня постоянно выходит экран формы с её цветом, и ничего не могу сделать, файл с примером не скачивается походу его нет на сервере, так же я не знаю куда мне написать "FormResize(Sender); //процедура обновления", сможете ответить на мои вопросы?