ВНИМАНИЕ! Конкурс по программированию!

Проект Programmers.kz и школа hotPen3D2D предлагает Вам курсы по веб-дизайну, веб-программированию и компьютерной графике. Подробности здесь.

 
Информация к новости
 (голосов: 0)

Работа с OpenGL

Категория: Программирование » Delphi » Уроки Delphi

В этой вводной статье, я хочу рассказать программистам, которые достаточно хорошо знают Delphi, а так же саму теорию программирования и математику. Во – первых, что такое OpenGL?

OpenGL – Это специальная библиотека, созданная несколькими корпорациями, для создания 3d – приложений. Дело в том, что OpenGL, расшифровывается как Open Graphics Library, и по названию, сразу видно, что она открытая, а значит, что она встроена во ВСЕ OC Windows начиная с 95 версии, не включая её саму, а также Linux. Кстати, поскольку у OpenGL, клиент – серверная схема, взаимодействия с программами, то её можно использовать на любых языках. Кстати, я видел OpenGL – программы на ассемблере.

И так, что же делать с ней в первую очередь? Инициализировать!!!

Инициализация.

Для начала, договоримся, что при использовании OpenGL, мы не будем использовать функции вывода GDI. Ну, начнем! Создаём процедуру, которая будет задавать у нас формат пикселя.

Procedure TForm.SetMyPixelForOGL(DC:HDC);
Var
MyPFD: TPixelFormatDescriptor;
MyPixelFormat: Integer;
Begin
 ZeroMemory(@MyPFD,SizeOf(MyPFD);
 //Тут можно изменять MyPFD по мере нужд.
 MyPixelFormat:=ChoosePixelFormat(DC,@MyPFD);
 SetPixelFormat(DC,MyPixelFormat,@MyPFD);
End;
Наверное, все из программистов знают, что такое DC. Если всё же, кто – то не знает, то попробую объяснить доступным языком:

DC - Device Context, или короче ссылка на устройство, просто у Винды есть драйвера, для устройств, а DC, содержит в себе HWND, которая будет использовать эти драйвера. Короче HWND в Windows, ID окна, а DC существует для того, что бы этот HWND мог пользоваться графикой Windows GDI. Это я всё к тому, что у OpenGL, есть величина, типа HGLRC, это как у GDI: Device Context, так и у OpenGL, Render Context.

Поэтому в разделе Private описываем переменную:
MyRC:HGLRC;
Если, что – то не понятно, то попытайтесь рассказать об этом на форуме, тогда я напишу статью и про это. Ну, а вот собственно и разбор процедуры.

TPixelFormatDescriptor – Тип который содержит в себе информацию, для OGL, как он будет обращаться с пикселом, например: Будет ли он использовать 2 – ую буферизацию и т.д….

MyPixelFormat: Вспомогательная переменная, которая будет хранить ID.
ZeroMemory – Обнуляет указанную область памяти, это для того, что бы если до создания переменной, по указанному адресу, были другие значения, кроме 0, то после обнуления, они нам не изменять наших настроек, так принять делать в DirectX и OpenGL. В ней первый аргумент – это указатель на память, которую мы будем собственно очищать.
Процедура ChoosePixel, возвращает ID.
Первый её аргумент – это величина типа HDC, а второй указатель на TPixelFormatDescriptor. Процедура SetPixelFormat, устанавливает все те настройки с пикселом, что мы сотворили.

Первый её аргумент – это величина типа HDC, вторая типа Integer, с присвоенным ID, от ф – ции ChoosePixel, описываемой выше, а третий аргумент – это ссылка на величину типа TPixelFormatDescriptor. Ну вот и всё с описанием пиксела разобрались. Теперь в раздел Private класса TForm1, ставим нашу процедуру и работа над ней пока закончена.

Теперь в обработку OnPaint формы вписываем следующий текст.
glClear(GL_COLOR_BUFFER_BIT);
    SwapBuffers(DC);
Что обозначает, что OpenGL должен стереть, что мы нарисовали, если этого не далать перед каждым кадром, то изображение, будет накладываться одно на другое, такое например бывает, когда Windows зависает. Ну, а вторая процедура, говорит нам о выводе буферов на экран, а соответственно, того что мы нарисовали(Ведь сохраняется всё это в буферах).

А в обработчике OnCreate формы пишем:
DC:=GetDC(Form1.handle);
//Получаем вместо величины типа HWND, величину 
//типа HDC, для этой формы

RC:=wglCreateContext(DC);
//С помощью Windows GL(WGL) преобразовываем её HDC, в 
//HGLRC, с помощью которой будем рисовать.

wglMakeCurrent(DC,RC);
//Сам не знаю, но без ней ничего не рисуется, но 
переводиться 
//как поток, судя по всему это наверное 3d пространство.
Я думаю, что из комментариев всё понятно! На событие OnClose пишем:

wglMakeCurrent(0,0);
//Создаём нулевое пространство, то есть удаляем старое.
wglDeleteContext(RC);//Уничтожаем наш RenderContext
DeleteDC(DC);//Уничтожаем DC
Там, где надо было определять формат пиксела, я говорил, о том, что процедура SetPixelFormat, сохраняет изменения сделанные нами, но ведь мы НИЧЕГО НЕ ИЗМЕНЯЛИ!!! Так давайте это исправим! В принципе, можно обойтись и без этого, но тогда окно будет тормозить при перетаскивании, и иногда мерцать.

Как с эти справиться? Спросите вы! Да очень просто у типа TPixelFormatDescriptor eсть поле dwFlags вот мы, что и пишем вместо комментариев!!!:

  MyPFD.dwFlags:=PFD_DOUBLEBUFFER or PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW;
PFD_DOUBLEBUFFER. Это даёт нам двойную буферизацию, то есть после вызова ф-ции swapBuffers, будет не просто вывод на экран, а ещё и копирование, в специальную память, а вот только потом из этой памяти, будет копирование на экран!

PFD_SUPPORT_OPENGL. Это говорит, OpenGL, о том, что вывод будет осуществляться с помощью её ф-цй, а не GDI, в принципе ради пробы вы можете вместо этого поставить PFD_SUPPORT_GDI, но это вряд – ли вас удовлетворит…

PFD_DRAW_TO_WINDOW. Угадайте сами, но если вы не знаете английского языка, то скажу, что эта константа говорит о том, что вывод будет осуществляться в окно.

Всё, что вы рисуете, в OpenGL, лучше ставить на событие перерисовки окна, это для того, как вы наверное уже догадались, что бы рисунок не стирался. Рассмотрим следующие 2 – е команды: glBegin(аргумент); и glEnd;

Что же надо вводить в процедуре glBegin() вместо аргумент? Для начала, для этого надо определиться, что делает сама процедура. Ну и так, вот она ничего не делает, но между этими двумя командами, мы и будем рисовать. Сначала мы поставим glBegin(GL_POINTS), не в коем случае не перепутайте с командой glBegin(GL_POINT). Это обозначает, то что мы будем рисовать лишь точки. Если мы зададим команду:

glBegin(GL_LINES), то каждые две точки будут соединяться отдельной линией.
glBegin(GL_LINES_STRIP), обозначает, что точки будут соеденяться линиями, последовательно!
glBegin(GL_POLYGON) обозначает, что каждые четыре точки образуют между собой плоскость.
glBegin(GL_TRIANGLES), говорит OpenGL о том, что каждые три точки, будут соединяться плоскостью.
glBegin(GL_TRIANGLE_STRIP), говорит OpenGL, о том, что они будут соединены как и прошлой командой, но только в порядке 1+2+3,3+4+5,5+6+7. И тем самым треугольники будут связаны.

Ну вы наверное сейчас думаете, что вон я сколько настрочил о соединении точек, хотя о их создании ещё ничего не сказал, сейчас всё исправлю!

Команда glVertex3f(X,Y,Z); cтавит точку в координате X,Y,Z.

Учтите, что если специальным образом ничего не переменить(Об этом я расскажу в последующих статьях), то координата (0;0;0) , будет находиться в центре окна, причем всегда, независимо, от его (Окна) размеров. А также, если ничего не переменить, то окно будет всё время в рамках координаты 1. Например: Левая, верхняя точка окна = (-1,-1). А правая нижняя =(1,1).

Сразу, говорю, что я линии не поддерживаю, так как с ними редко приходится оперировать, поэтому буду использовать, только полигоны, точки, и связанные треугольники. Я забыл упомянуть процедуру glClearColor(R,G,B,A:single); Эта процедура, определяет цвет очистки окна, сейчас у Вас окно окрашивается в черный цвет(Если вы конечно читали мою прошлую статью, и делали всё как надо), а эта процедура позволяет задавать другой.

Тут всё как обычно, за исключением четвёртого параметра, это коэффициент прозрачности, но т.к. это фон то прозрачность для него будем делать, 1. Ах, да и ещё здесь цвета задаются не от 0 и до 255, а от 0 и до 1, сами понимаете число дробное.

Процедура glColor3f (R,G,B:Single).

Задает цвет точки, всё, как и в предыдущей функции, за исключением отсутствия альфы. Ну давайте, что - нибудь нарисуем, только не забудьте, поставить этот код поставить между SwapBuffers и GlClear из предыдущего урока..

Вот собственно код:

glBegin(GL_TRIANGLES);//Точки будут соединяться треугольниками.

glColor3f(1,0,0);//Задаём цвет первой точки.

glVertex3f(-1,-1,0);//Задаём 1 – ую точку.

glColor3f(0,1,0);// Цвет 2 – ой точки

glVertex3f(-1,1,0);//А вот и она сама

glColor3f(0,0,1);//Догадайтесь сами

glVertex3f(1,0,0);//Тоже самое

glEnd;
Запускаем!!!

Красивый пример ничего не скажешь! Я не знаю, встретитесь ли вы с такой же проблемой как у меня, работает нормально, при закрытии Delphi глюк выдаёт, а если запускать не из Delphi, а сначала откомпилировать, а потом запустить, то всё ОК!

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

Просто ради того, что бы эта тема вас более заинтересовала, я вам скажу, что процедура эта – glRotated(angle,X,Y,Z: Double); Angle – Угол поворота, а x,y,z: соответствующие оси, в любое место перерисовки окна, между SwapBuffres и glClear поставьте:

glRotated(1,0,1,0).
Это ещё красивее.

Автор: petya-kurochkin
Источник: web-brodilka.ru
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Добавление комментария

Имя:*
E-Mail:
Комментарий:
Введите два слова, показанных на изображении: *