Программа реализует пример инициализации SDL2 для создания окна и обработки событий окна на изменения размеров окна, закрытия окна по нажатию клавиши ESC. Инициализация dglOpenGL.
Рисунок 1. Демонстрация работы программы. Вращающийся треугольник.
Код проекта:
program ogl_p4;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes,
sysutils,
sdl2lib,
dglOpenGL;
const
WINDOW_WIDTH = 800;
WINDOW_HEIGHT = 600;
var
Window: PSDL_Window = nil;
GLContext: TSDL_GLContext = nil;
Event: TSDL_Event;
Running: Boolean = True;
RotateAngle: Single = 0.0;
procedure InitSystem;
begin
// Загружаем SDL2 library из системных путей Debian 13 напрямую
if Not SDL2LIB_Initialize(SDL_LibName) then
begin
raise Exception.Create('Не удалось динамически загрузить libSDL2.so через SDL2LIB_Initialize');
end;
// Инициализируем видеосистему SDL2
if SDL_Init( SDL_INIT_VIDEO ) < 0 then
begin
WriteLn('Ошибка инициализации SDL2: ', SDL_GetError());
Halt(1);
end;
// Настраиваем параметры OpenGL перед созданием окна
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
// Создаем окно через SDL2
Window := SDL_CreateWindow(
'SDL2 + dglOpenGL + Lazarus (Debian 13)',
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
WINDOW_WIDTH, WINDOW_HEIGHT,
SDL_WINDOW_OPENGL or SDL_WINDOW_SHOWN
or SDL_WINDOW_RESIZABLE
);
if Window = nil then
raise Exception.Create('Не удалось создать окно SDL2');
// Создаем контекст OpenGL
GLContext := SDL_GL_CreateContext(Window);
if GLContext = nil then
raise Exception.Create('Не удалось создать контекст OpenGL');
// Загружаем внутренние указатели OpenGL (dglOpenGL подхватит контекст SDL2)
if not InitOpenGL then
raise Exception.Create('Не удалось инициализировать dglOpenGL через контекст SDL2');
// Читаем расширения
ReadExtensions;
// Строку ReadImplementationProperties; лучше убрать, в некоторых версиях dglOpenGL под Linux она падает
ReadImplementationProperties;
// Базовая настройка сцены (Матрицы и проекция)
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, WINDOW_WIDTH / WINDOW_HEIGHT, 0.1, 100.0);
glMatrixMode(GL_MODELVIEW);
glClearColor(0.1, 0.1, 0.15, 1.0);
end;
procedure HandleResize(Width, Height: Integer);
begin
// Защита от деления на ноль, если окно свернули
if Height = 0 then Height := 1;
// Обновляем область вывода OpenGL на весь экран окна
glViewport(0, 0, Width, Height);
// Переключаемся на матрицу проекции для ее обновления
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Задаем перспективную или ортогональную проекцию
// Пример для Перспективы (3D): fov = 45 градусов, ближний отсекатель = 0.1, дальний = 100.0
gluPerspective(45.0, Width / Height, 0.1, 100.0);
// Возвращаем матрицу модели для обычного рендеринга объектов
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
end;
procedure HandleEvents;
begin
// Обрабатываем очередь сообщений SDL2
while SDL_PollEvent(@Event) <> 0 do
begin
case Event.type_ of
// Событие закрытия окна
SDL_QUITEV:
Running := False;
SDL_WINDOWEVENT:
begin
// Проверяем конкретный подтип события
case Event.window.event of
SDL_WINDOWEVENT_RESIZED,SDL_WINDOWEVENT_SIZE_CHANGED:
begin
// Извлекаем новые параметры ширины и высоты из события
// и обновляем матрицы
HandleResize(Event.window.data1, Event.window.data2);
end;
end;
end;
SDL_KEYDOWN:
begin
if Event.key.keysym.sym = SDLK_ESCAPE then
Running := False;
end;
end;
end;
end;
procedure UpdateFrame;
begin
RotateAngle := RotateAngle + 0.5;
if RotateAngle >= 360.0 then
RotateAngle := RotateAngle - 360.0;
end;
procedure RenderFrame;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// Отодвигаем камеру назад на 3 единицы по оси Z (объект окажется перед камерой)
glTranslatef(0.0, 0.0, -3.0);
glRotatef(RotateAngle, 0.0, 0.0, 1.0);
// Рисуем простой треугольник
glBegin(GL_TRIANGLES);
glColor3f(1.0, 0.0, 0.0); glVertex2f(0.0, 1.0);
glColor3f(0.0, 1.0, 0.0); glVertex2f(-1.0, -1.0);
glColor3f(0.0, 0.0, 1.0); glVertex2f(1.0, -1.0);
glEnd();
SDL_GL_SwapWindow(Window);
end;
procedure CleanUp;
begin
if GLContext <> nil then
SDL_GL_DeleteContext(GLContext);
if Window <> nil then
SDL_DestroyWindow(Window);
SDL_Quit();
end;
begin
try
InitSystem;
// Главный цикл программы
while Running do
begin
HandleEvents;
UpdateFrame;
RenderFrame;
SDL_Delay(16);
end;
except
on E: Exception do
Writeln('Ошибка: ', E.Message);
end;
CleanUp;
end.

Комментариев нет:
Отправить комментарий