Инструменты пользователя

Инструменты сайта


blackbox:3d

Разработка приложений с применением OpenGL

Чтобы разрабатывать в Блэкбоксе приложения с трехмерной графикой, используя программный интерфейс OpenGL, существует расширение Ogl. Это расширение само по себе позволяет рисовать трехмерные объекты на внутренних окнах Блэкбокса, а также содержит некоторое количество примеров, чтобы начать осваивать конвейерный язык OpenGL в операционной системе Windows.

Однако для разработки прикладных кросс-платформенных приложений более практично создавать окна и обрабатывать события ввода данных с клавиатуры и мыши с помощью библиотеки Sdl2. Кросс-платформенная библиотека Sdl2 позволяет создавать приложения, которые не будут зависеть от оконной системы компонентного каркаса Блэкбокс, и будут единообразно работать на различных платформах. Также расширения библиотеки Sdl2 позволяют работать с растровыми изображениями и шрифтами в формате TrueType.

Настройка среды разработки

Файл архива с готовой «сборкой» Блэкбокса включает необходимые расширения и библиотеки:

Готовая сборка Блэкбокса с необходимыми библиотеками для Windows (v.1.7.2.135.1)

Если пока не ориентируетесь в среде разработки Блэкбокс, то мы рекомендуем перед разработкой 3D-приложений освоить необходимые навыки, посмотрев краткие уроки, онлайн учебник или видеоуроки.

Если выбираете готовую сборку и достаточно ориентируетесь в Блэкбоксе, то переходите к следующему разделу заметки.

Для того, чтобы самостоятельно настроить среду необходимо выполнить следующие действия действия:

  1. Скачайте Блэкбокс.
  2. Установите расширение Sdl2, для чего скачайте закодированный файл с сайта.
  3. Откройте скачанный текстовый документ в Блэкбоксе и выберите команду Инструменты/Раскодировать. Файлы модулей и документация будут распакованы в рабочую директорию. Как правило у расширений Блэкбокса есть файл с документацией (Quick-Start). Откройте документ Sdl2/Docu/Quick-Start.odc, в котором найдете документацию на английском, как скомпилировать модули и откуда скачать бинарные файлы библиотек Sdl2.
  4. Перед тем как откомпилировать модули подсистемы Sdl2, необходимо установить также непосредственно само расширение для работы с OpenGL: https://gitlab.molpit.org/bindings/Ogl. Распаковка производится таким же образом через команду Инструменты/Раскодировать.
  5. После того как модули Ogl распакованы, запустите команды для компиляции модулей в зависимости от вашей платформы. Команды запускаются с помощью коммандеров (кружков с восклицательными знаками).
  6. Скачайте и распакуйте в рабочую папку необходимые библиотеки Sdl2. Ссылки для загрузки вы найдете в документе Sdl2/Docu/Quick-Start. Для Windows перезапуск среды не требуется. Для операционных систем на основе GNU/Linux необходимо перезапустить Блэкбокс, указав в переменной окружения `LD_LIBRARY_PATH` путь к файлам библиотек Sdl2 (пример bash-скрипта для запуска Блэкбокса также находится в документации, стоит лишь развернуть складку со знаками «+» в пункте 1.3).

После того, как все действия выполнены, вы сможете ознакомиться с примерами, ссылки на которые вы найдете в файле Quick-Start.

Обзор примеров

Sdl2ObxLoop дает представление о работе с петлей обработки событий Sdl2 и кросс-платформенными командами рисования на окне простейших примитивов.

Важно, что при запуске нового примера необходимо выгрузить модуль предыдущего примера. Это связано с тем, что петля обработки событий Sdl2 общая для всех окон. Поэтому единовременный запуск нескольких примеров из одного Блэкбокса, может привести к непредусмотренному поведению системы, и даже «падению» среды разработки.

Sdl2ObxTwo рассматривает как организовать работу с несколькими окнами. В этом примере в окнах не происходит отрисовки, но показано как отличить события от разных окон.

Sdl2ObxOpenGL показывает как создать контекст для рисования команадми OpenGL.

(!) DevCompiler.CompileThis Sdl2ObxOpenGL

и запустить его командой:

(!) Sdl2ObxOpenGL.Start

Появится окно с квадратом, который залит градиентной заливкой.

Sdl2ObxTexture показывает как наложить текстуру.

Sdl2ObxModels демонстирирует возможность загрузки трехмерных объектов в формате ms3d с текстурами. Трехмерные объекты в формате ms3d для ваших приложений удобно создавать в бесплатном приложении Blender. Поддержка формата ms3d отключена по-умолчанию, однако легко включается в опциях в разделе import/export.

Sdl2ObxSnapshotGL — пример захвата изображения из OpenGL сцены, и сохранения в формате PNG.

Sdl2ObxTtf раскрывает особенности работы со шрифтами.

Sdl2ObxIcosphere — пример рисования корректно освященной сферы с помощью икосаэдра.

Разбор примера Sdl2ObxOpenGL

Разберем подробнее третий пример, который применяет команды OpenGL.

Модуль Sdl2/Mod/ObxOpenGL.odc содержит реализацию шести процедур. Рассмотрим, какие функции они выполняют в программе.

1. Viewport — вызывает команды OpenGL для формирования проекции трехмерных объектов на экран.

PROCEDURE Viewport;
BEGIN
	Gl.Viewport(0, 0, width, height);
	Gl.MatrixMode(Gl.GL_PROJECTION);
	Gl.LoadIdentity;
	IF height = 0 THEN height := 1 END;
	Gl.Ortho(- zoom * width / height, zoom * width / height, - zoom, zoom, -1, 300);
END Viewport;

2. Render — вызывает команды для создания самих трехмерных объектов, а затем командой `Sdl2Video.GL_SwapWindow(w)` происходит обмен буферами рисования и показа в окне Sdl2, чтобы мы увидели проекцию этих объектов в окне.

PROCEDURE Render;
BEGIN
	Gl.MatrixMode (Gl.GL_MODELVIEW);
	Gl.ClearColor(0, 0, 0, 0);
	Gl.Clear(Gl.GL_COLOR_BUFFER_BIT + Gl.GL_DEPTH_BUFFER_BIT);
	
	Gl.LoadIdentity;
	Gl.Translatef( 0, 0, -6);
	Gl.Begin(Gl.GL_QUADS);
		Gl.Color3f ( 1, 0, 0);
		Gl.Vertex3f(-1, 1, 0);
		Gl.Color3f ( 0, 1, 0);
		Gl.Vertex3f(-1,-1, 0);
		Gl.Color3f ( 0, 0, 1);
		Gl.Vertex3f( 1,-1, 0);
		Gl.Color3f ( 0, 1, 1);
		Gl.Vertex3f( 1, 1, 0);
	Gl.End;

	Sdl2Video.GL_SwapWindow(w)
END Render;

3. CloseWindow — Удаляет контекст для OpenGL и само окно.

PROCEDURE CloseWindow;
BEGIN
	IF c # NIL THEN Sdl2Video.GL_DeleteContext(c); c := NIL END;
	IF w # NIL THEN Sdl2Video.DestroyWindow(w); w := NIL END;
END CloseWindow;

4. Handle — обрабатывает события пользовательского ввода, измерения размеров окна, сигналы его показа и закрытия. Событие приходит в виде аргумента процедуры типа `Sdl2Lib.Event`, и затем с помощью оператора WITH происходит проверка типа переменной. В зависимости от типа, выполняются действия. Процедура `Sdl2Lib.PumpEvents` производит удаление событий из очереди перед закрытием окна, чтобы не получилось, что какие-то события будут обработаны после. При вращении колеса мыши происходит изменение глобальной переменной `zoom`, значение которой влияет на проекцию объектов в процедуре `Viewport`.

PROCEDURE (this: Loop) Handle (VAR e: Sdl2Lib.Event; OUT stop: BOOLEAN);
BEGIN
	WITH e: Sdl2Events.Quit DO
		stop := TRUE
	| e: Sdl2Events.WindowEventClose DO
		CloseWindow
	| e: Sdl2Events.WindowEventResized DO
		IF e.w + e.h # 0 THEN
			width := e.w;
			height := e.h;
			update := TRUE
		END;
	| e: Sdl2Events.WindowEventSizeChanged DO
		update := TRUE
	| e: Sdl2Events.WindowEventShown DO
		update := TRUE
	| e: Sdl2Events.WindowEventFocusGained DO
		update := TRUE
	| e: Sdl2Events.MouseWheelEvent DO
		zoom := zoom + 0.1 * e.x;
		IF zoom < 0.1 THEN zoom := 0.1 END;
		update := TRUE
	ELSE
	END
END Handle;

5. Do — является реализацией отложенных действий в каркасе Блэкбокс, которые позволяют путем рекурсивной установки нового действия в очередь вызывать периодическое обновления содержимого окна, если требуется перерисовка.

PROCEDURE (a: Action) Do;
BEGIN
	IF c # NIL THEN
		IF update THEN
			Viewport;
			Render;
			update := FALSE
		END;
		Services.DoLater(a, Services.Ticks()+50)
	END
END Do;

6. Start — загружает необходимые реализации, созает окно, инициализирует OpenGL, создает петлю для обработки событий пользовательского ввода и запускает рекурсивный вызов действий для обновления содержимого окна.

PROCEDURE Start*;
VAR res: INTEGER;
BEGIN
	(* Loading realisation of Sdl2Std abstract interface *)
	IF Dialog.IsWindows() THEN
		ASSERT(Kernel.ThisMod('Sdl2StdWin') # NIL, 20)
	ELSIF Dialog.IsLinux() THEN
		ASSERT(Kernel.ThisMod('Sdl2StdLin') # NIL, 20)
	ELSE
		HALT(20)
	END;
	
	width := initWidth;
	height := initHeight;
	
	CloseWindow;
	Sdl2Lib.Quit;
	res := Sdl2Lib.Init(Sdl2Const.INIT_VIDEO + Sdl2Const.INIT_EVENTS);
	
	w := Sdl2Video.CreateWindow("OpenGL window", 100, 100, width, height,
		Sdl2Const.WINDOW_OPENGL + Sdl2Const.WINDOW_RESIZABLE);
	c := Sdl2Video.GL_CreateContext(w);
	Sdl2Video.GL_MakeCurrent(w, c);
	
	Gl.ClearColor(0, 0, 0, 0);
	Gl.Enable(Gl.GL_COLOR_MATERIAL);
	Gl.ColorMaterial(Gl.GL_FRONT, Gl.GL_AMBIENT_AND_DIFFUSE);
	Viewport;
	
	NEW(loop);
	Sdl2Lib.StartLoop(loop);
	
	update:= FALSE;
	IF updater = NIL THEN NEW(updater) END;
	Services.DoLater(updater, Services.now)
END Start;

Создание отдельного приложения

Предыдущий пример показывает, как создать окно непосредственно из среды Блэкбокс.

В документации примеров Sdl2ObxModels и Sdl2ObxIcosphere содержаться примеры команд сборки независимых приложений OS Windows и других платформ.

При этом в секции BEGIN главного модуля вызывается запускающая процедура, которая содержит цикл

quit := FALSE;
WHILE ~ quit DO
	(* drive services for actions loop *)
	Services.actionHook.Step;
	Sdl2Lib.Delay(10)
END;
Sdl2Lib.Quit

Этот цикл обеспечивает работу механизма отложенных действий в Блэкбоксе.

Чтобы не делать отдельные модули для демонстрации сборки автономных приложений, используется прием условной компиляции, где в скобках около имени модуля указывается вариант фрагмента в исходных кодах.

Sdl2ObxIcosphere(mode:standalone)

При этом в исходных кодах варианты оформлены с помощью так называемых «селекторов». Этот прием условной компиляции был удобен для демонстрации, но не рекомендуется использовать его в ваших итоговых проектах.

Готовое приложение необходимо распространять вместе с набором библиотек.

В операционных системах GNU/Linux, OpenBSD или FreeBSD еще необходимо задать переменную окружения, где лежат библиотеки. В этом случае удобно создать отдельный sh скрипт для запуска:

#!/bin/sh
LD_LIBRARY_PATH=./libsdl2:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH
./icosphere $* &

Автор заметки: Иван Денисов.

blackbox/3d.txt · Последнее изменение: 2021/06/19 15:10 — iadenisov