Поскольку собственный OpenGL.pas Delphi имеет версию 1.0, а то, что фактически используется сейчас, - это как минимум версия 1.1, а метод моделирования чистого программного обеспечения Windows также имеет версию 1.1, поэтому вам придется импортировать некоторые необходимые функции самостоятельно. Также доступны некоторые бесплатные модули с открытым исходным кодом, такие как OpenGL12.pas Майка Лишке. Конечно, написание его самостоятельно может сделать проект более лаконичным, и вам не придется находить ошибки в огромном, слишком сложном и полном коде.
Сначала введем необходимые модули Windows, Messages, OpenGL.
Чтобы добавить некоторые необходимые расширения.
константа
//GL_EXT_bgra
GL_BGR_EXT = $80E0;
GL_BGRA_EXT = $80E1;
// смещение полигона
GL_POLYGON_OFFSET_UNITS = 2A00$;
GL_POLYGON_OFFSET_POINT = $2A01;
GL_POLYGON_OFFSET_LINE = $2A02;
GL_POLYGON_OFFSET_FILL = $8037;
GL_POLYGON_OFFSET_FACTOR = 8038 долларов США;
PROcedure glBindTexture (цель: GLEnum; текстура: GLuint); stdcall; внешний opengl32;
процедура glDeleteTextures (n: GLsizei; текстуры: PGLuint); stdcall внешний opengl32;
процедура glGenTextures (n: GLsizei; текстуры: PGLuint); stdcall внешний opengl32;
функция glIsTexture (текстура: GLuint): GLboolean; внешний stdcall;
процедура glPolygonOffset (фактор, единицы: GLfloat); stdcall внешний opengl32;
// Этот оператор используется для исправления ошибки в OpenGL.pas
функция gluBuild2DMipmaps (цель: GLEnum; компоненты, ширина, высота: GLint; формат, тип: GLEnum; Данные: указатель): GLint external opengl32;
Сейчас интерфейс практически обновлен до версии 1.1. Если необходимы другие расширения, их можно добавить аналогичным образом.
Далее вам необходимо создать контекст рисования OpenGL RC, для чего вам понадобится контекст устройства DC окна GDI. Свойство TForm.Handle или другие свойства Handle TWinControl являются DC. Вы можете использовать следующую функцию для создания RC из DC, а возвращаемое значение — это дескриптор RC. Затем вы можете рисовать, используя OpenGL. Обычно может использоваться в событии OnCreate формы. Параметры этой функции означают буфер глубины, буфер шаблона, буфер накопления и генерацию значения альфа-канала.
тип
TRCOptions = набор (roDepth, roStencil, roAccum, roAlpha);
функция CreateRC(dc: HDC; опция: TRCOptions): HGLRC;
вар
ПФдескриптор: TPixelFormatDescriptor;
Формат пикселей: целое число;
начинать
FillChar(PFDescriptor, SizeOf(PFDescriptor), 0);
с PPFDescriptor сделать
начинать
nSize := SizeOf(PFDescriptor);
нВерсия: = 1;
dwFlags:= PFD_SUPPORT_OPENGL или PFD_DRAW_TO_WINDOW или PFD_DOUBLEBUFFER;
iPixelType:= PFD_TYPE_RGBA;
cColorBits := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES);
если roDepth в opt, то cDepthBits := 24;
если roStencil в опции, то cStencilBits := 8;
если roAccum в opt, то cAccumBits := 64;
iLayerType: = PFD_MAIN_PLANE;
конец;
PixelFormat := ChoosePixelFormat(DC, @PFDescriptor);
Утверждать (PixelFormat <> 0);
Assert(SetPixelFormat(DC, PixelFormat, @PFDescriptor));
Результат: = wglCreateContext(DC);
Утверждать (Результат <> 0);
wglMakeCurrent (DC, Результат);
конец;
Нарисуйте событие OnPaint формы. Помните, что после завершения рисования вам необходимо использовать SwapBuffers (dc: HDC) для обмена буфером рисования и буфером отображения, чтобы изображение отображалось. Также не забудьте вызвать glViewport(0, 0, ClientWidth, ClientHeight); в событии OnResize формы, чтобы можно было синхронизировать RC и DC.
Уничтожьте RC в событии OnDestroy формы.
процедура DestroyRC(rc: HGLRC);
начинать
если rc = 0, то Выход;
wglMakeCurrent (0, 0);
wglDeleteContext (RC);
конец;
На этом этапе структура программы OpenGL примерно сформировалась. Но есть еще проблемы, которые предстоит решить.
Во-первых, не позволяйте Windows стирать фон и влиять на скорость. Добавьте функции-члены в форму
частный
процедура WMEraseBkgnd (вар Сообщение: TWmEraseBkgnd); сообщение WM_ERASEBKGND;
процедура TGLWindow.WMERaseBkgnd(сообщение var: TWmEraseBkgnd);
начинать
Сообщение.Результат:= 1;
конец;
Во-вторых, чтобы быть безопаснее. Добавьте следующие функции-члены.
защищенный
процедура CreateParams (var Params: TCreateParams override);
процедура TGLWindow.CreateParams(var Params: TCreateParams);
начинать
унаследованный;
с параметрами сделать
начинать
Стиль := Стиль или WS_CLIPCHILDREN или WS_CLIPSIBLINGS;
WindowClass.Style := CS_VREDRAW или CS_HREDRAW или CS_OWNDC;
конец;
конец;
Ладно, теперь можно забыть об этих хлопотных вещах и написать свой замечательный 3D-дисплей :)
Должен сказать несколько слов: не создавайте несколько RC в одном потоке, так как это серьезно повлияет на производительность. В некоторых демонстрациях управления окном OpenGL в форме размещается несколько элементов управления, что на самом деле не очень хорошая идея. Несколько представлений должны отображаться в одном окне OpenGL. Кроме того, не обращайтесь к функциям OpenGL в нескольких потоках.
Кроме того, когда Windows автоматически устанавливает драйвер видеокарты, аппаратное ускорение OpenGL не устанавливается. Вам необходимо установить драйвер производителя видеокарты самостоятельно!
Кроме того, предусмотрена бесплатная функция полноэкранного отображения :)
функция FullScreen (win: TWinControl; ширина, высота, разрядность: целое число): логическое значение;
вар displaymode: DEVMODE;
начинать
FillChar (режим отображения, sizeof (режим отображения), 0);
с режимом отображения сделать
начинать
dmSize := sizeof(режим отображения);
dmPelsWidth:= ширина;
dmPelsHeight: = высота;
dmBitsPerPel := разрядность;
dmFields := DM_BITSPERPEL или DM_PELSWIDTH или DM_PELSHEIGHT;
конец;
если ChangeDisplaySettings(displaymode, CDS_FULLSCREEN) = DISP_CHANGE_SUCCESSFUL
тогда начни
ShowWindow(win.Handle, WS_MAXIMIZE);
результат: = правда;
конец
иначе результат: = ложь;
конец;
процедура RestoreDisplay (победа: TWinControl);
начинать
ChangeDisplaySettings(PDEVMODE(0)^, 0);
ShowWindow(win.Handle, SW_RESTORE);
конец;