| Предыдущая версия справа и слева
Предыдущая версия
Следующая версия
 | 
                    Предыдущая версия
 | 
                
                        
                
                    blackbox:3d [2020/01/07 00:36] иван_денисов                  | 
                
                    blackbox:3d [2021/06/19 15:10] (текущий) iadenisov [Обзор примеров]                  | 
            
        
| ====== Разработка приложений с применением OpenGL ====== | ====== Разработка приложений с применением OpenGL ====== | 
 |  | 
| Чтобы разрабатывать в [[:blackbox:|Блэкбоксе]] приложения с трехмерной графикой, используя программный интерфейс OpenGL, удобно создавать окна с помощью библиотеки [[https://www.libsdl.org/|Sdl2]]. Кросс-платформенная библиотека Sdl2 также содержит необходимые средства, чтобы окна разрабатываемых приложений не зависели от оконной системы компонентного каркаса Блэкбокс и работали на различных платформах единообразно. | Чтобы разрабатывать в [[:blackbox:|Блэкбоксе]] приложения с трехмерной графикой, используя программный интерфейс OpenGL, существует расширение [[http://www.zinnamturm.eu/downloadsOS.htm#Ogl|Ogl]]. Это расширение само по себе позволяет рисовать трехмерные объекты на внутренних окнах Блэкбокса, а также содержит некоторое количество примеров, чтобы начать осваивать конвейерный язык OpenGL в операционной системе Windows.  | 
|   |   | 
|   | {{ :blackbox:opengl.png?600 |}}  | 
|   |   | 
|   | Однако для разработки прикладных кросс-платформенных приложений более практично создавать окна и обрабатывать события ввода данных с клавиатуры и мыши с помощью библиотеки [[https://www.libsdl.org/|Sdl2]]. Кросс-платформенная библиотека Sdl2 позволяет создавать приложения, которые не будут зависеть от оконной системы компонентного каркаса Блэкбокс, и будут единообразно работать на различных платформах. Также расширения библиотеки Sdl2 позволяют работать с растровыми изображениями и шрифтами в формате TrueType. | 
 |  | 
| ===== Настройка среды разработки ===== | ===== Настройка среды разработки ===== | 
 |  | 
| Чтобы установить расширение Sdl2 в Блэкбокс, скачайте закодированный файл с сайта:  | Файл архива с готовой «сборкой» Блэкбокса включает необходимые расширения и библиотеки:  | 
| https://blackbox.oberon.org/extension/Sdl2 |   | 
|   | {{ :blackbox:blackbox-3d-135.zip | Готовая сборка Блэкбокса с необходимыми библиотеками для Windows (v.1.7.2.135.1)}}  | 
|   |   | 
|   | Если пока не ориентируетесь в среде разработки Блэкбокс, то мы рекомендуем перед разработкой 3D-приложений освоить необходимые навыки, посмотрев [[bb:lessons:|краткие уроки]], [[blackbox:manual:|онлайн учебник]] или [[blackbox:video|видеоуроки]].  | 
|   |   | 
|   | Если выбираете готовую сборку и достаточно ориентируетесь в Блэкбоксе, то переходите [[https://wiki.oberon.org/blackbox/3d#%D0%BE%D0%B1%D0%B7%D0%BE%D1%80_%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D0%BE%D0%B2|к следующему разделу заметки]].  | 
|   |   | 
|   | Для того, чтобы самостоятельно настроить среду необходимо выполнить следующие действия действия:  | 
|   |    | 
|   |   - Скачайте [[blackbox:|Блэкбокс]].   | 
|   |   - Установите расширение Sdl2, для чего [[https://blackbox.oberon.org/extension/Sdl2|скачайте закодированный файл с сайта]].   | 
|   |   - Откройте скачанный текстовый документ в Блэкбоксе и выберите команду **Инструменты/Раскодировать**. Файлы модулей и документация будут распакованы в рабочую директорию. Как правило у расширений Блэкбокса есть файл с документацией (Quick-Start). Откройте документ **Sdl2/Docu/Quick-Start.odc**, в котором найдете документацию на английском, как скомпилировать модули и откуда скачать бинарные файлы библиотек Sdl2.   | 
|   |   - Перед тем как откомпилировать модули подсистемы Sdl2, необходимо установить также непосредственно само расширение для работы с OpenGL: https://gitlab.molpit.org/bindings/Ogl. Распаковка производится таким же образом через команду **Инструменты/Раскодировать**.   | 
|   |   - После того как модули Ogl распакованы, запустите команды для компиляции модулей в зависимости от вашей платформы. Команды запускаются с помощью коммандеров (кружков с восклицательными знаками).   | 
|   |   - Скачайте и распакуйте в рабочую папку необходимые библиотеки Sdl2. Ссылки для загрузки вы найдете в документе **Sdl2/Docu/Quick-Start**. Для Windows перезапуск среды не требуется. Для операционных систем на основе GNU/Linux необходимо перезапустить Блэкбокс, указав в переменной окружения `LD_LIBRARY_PATH` путь к файлам библиотек Sdl2 (пример bash-скрипта для запуска Блэкбокса также находится в документации, стоит лишь развернуть складку со знаками "+" в пункте 1.3).   | 
 |  | 
| Откройте скачанный текстовый документ в Блэкбоксе и выберите команду **Инструменты/Раскодировать**. Файлы модулей и документация будут распакованы в рабочую директорию. Как правило у расширений Блэкбокса есть файл с документацией (Quick-Start). Откройте документ **Sdl2/Docu/Quick-Start.odc**, в котором найдете документацию на английском, как скомпилировать модули и откуда скачать бинарные файлы библиотек Sdl2. | После того, как все действия выполнены, вы сможете ознакомиться с примерами, ссылки на которые вы найдете в файле Quick-Start. | 
 |  | 
| Перед тем как откомпилировать модули подсистемы Sdl2, необходимо установить также непосредственно само расширение для работы с OpenGL: https://gitlab.molpit.org/bindings/Ogl. Распаковка производится таким же образом через команду **Инструменты/Раскодировать**. | ===== Обзор примеров ===== | 
 |  | 
| После того как модули Ogl распакованы, запустите команды для компиляции модулей в зависимости от вашей платформы. Команды запускаются с помощью коммандеров (кружков с восклицательными знаками). Если пока не ориентируетесь в среде разработки Блэкбокс, то мы рекомендуем перед разработкой 3D-приложений освоить необходимые основы посмотрев [[blackbox:manual:|учебник]] или [[blackbox:video|видеоуроки]]. |   | 
 |  | 
| Скачайте и распакуйте в рабочую папку необходимые библиотеки Sdl2. Ссылки для загрузки вы найдете в документе **Sdl2/Docu/Quick-Start**. Для Windows перезапуск среды не требуется. Для операционных систем на основе GNU/Linux необходимо перезапустить Блэкбокс, указав в переменной окружения `LD_LIBRARY_PATH` путь к файлам библиотек Sdl2 (пример bash-скрипта для запуска Блэкбокса также находится в документации, стоит лишь развернуть складку со знаками "+" в пункте 1.3). | **Sdl2ObxLoop** дает представление о работе с петлей обработки событий Sdl2 и кросс-платформенными командами рисования на окне простейших примитивов. | 
 |  | 
|   | Важно, что при запуске нового примера необходимо выгрузить модуль предыдущего примера. Это связано с тем, что петля обработки событий Sdl2 общая для всех окон. Поэтому единовременный запуск нескольких примеров из одного Блэкбокса, может привести к непредусмотренному поведению системы, и даже <<падению>> среды разработки. | 
 |  | 
| {{ :blackbox:blackbox-3d-135.zip | Готовая сборка с необходимыми библиотеками для Windows (v.1.7.2.135.1)}} | **Sdl2ObxTwo** рассматривает как организовать работу с несколькими окнами. В этом примере в окнах не происходит отрисовки, но показано как отличить события от разных окон. | 
 |  | 
| После того, как библиотеки установлены, вы можете скомпилировать пример **Sdl2ObxOpenGL**. | **Sdl2ObxOpenGL** показывает как создать контекст для рисования команадми OpenGL. | 
 |  | 
| ```(!) DevCompiler.CompileThis Sdl2ObxOpenGL``` | ''(!) DevCompiler.CompileThis Sdl2ObxOpenGL'' | 
 |  | 
| и запустить его командой: | и запустить его командой: | 
 |  | 
| ```(!) Sdl2ObxOpenGL.Start``` | ''(!) Sdl2ObxOpenGL.Start'' | 
 |  | 
| Появится окно с квадратом, который залит градиентной заливкой. | Появится окно с квадратом, который залит градиентной заливкой. | 
 |  | 
| {{ :blackbox:opengl-demo.png?600 |}} | {{ :blackbox:opengl-demo.png?600 |}} | 
|   |  | 
|   |  | 
|   | **Sdl2ObxTexture** показывает как наложить текстуру. | 
|   |  | 
|   | **Sdl2ObxModels** демонстирирует возможность загрузки трехмерных объектов в формате **ms3d** с текстурами. Трехмерные объекты в формате **ms3d** для ваших приложений удобно создавать в бесплатном приложении Blender. Поддержка формата **ms3d** отключена по-умолчанию, однако легко включается в опциях в разделе import/export. | 
|   |  | 
|   | {{ :blackbox:texture.png?400 |}} | 
|   |  | 
|   | **Sdl2ObxSnapshotGL** — пример захвата изображения из OpenGL сцены, и сохранения в формате PNG. | 
|   |  | 
|   | **Sdl2ObxTtf** раскрывает особенности работы со шрифтами. | 
|   |  | 
|   | **Sdl2ObxIcosphere** — пример рисования корректно освященной сферы с помощью икосаэдра. | 
|   |  | 
|   | {{ :blackbox:ico.png?400 |}} | 
|   |  | 
 |  | 
| ===== Разбор примера Sdl2ObxOpenGL ===== | ===== Разбор примера Sdl2ObxOpenGL ===== | 
 |  | 
| Модуль **Sdl2/Mod/ObxOpenGL.odc** содержит реализацию пяти процедур. Рассмотрим, какие функции они выполняют в программе. | Разберем подробнее третий пример, который применяет команды OpenGL.  | 
|   |   | 
|   | Модуль **Sdl2/Mod/ObxOpenGL.odc** содержит реализацию шести процедур. Рассмотрим, какие функции они выполняют в программе. | 
 |  | 
| **Viewport** --- вызывает команды OpenGL для формирования проекции трехмерных объектов на экран. |  **1.** **Viewport** --- вызывает команды OpenGL для формирования проекции трехмерных объектов на экран. | 
 |  | 
| <code> | <code> | 
| </code> | </code> | 
 |  | 
| **Render** --- вызывает команды для создания самих трехмерных объектов, а затем командой `Sdl2Video.GL_SwapWindow(w)` происходит обмен буферами рисования и показа в окне Sdl2, чтобы мы увидели проекцию этих объектов в окне. |  **2.** **Render** --- вызывает команды для создания самих трехмерных объектов, а затем командой `Sdl2Video.GL_SwapWindow(w)` происходит обмен буферами рисования и показа в окне Sdl2, чтобы мы увидели проекцию этих объектов в окне. | 
 |  | 
| <code> | <code> | 
| </code> | </code> | 
 |  | 
|   |  **3.** **CloseWindow** --- Удаляет контекст для OpenGL и само окно. | 
|   | <code> | 
|   | 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; | 
|   | </code> | 
 |  | 
| **Handle** --- обрабатывает события пользовательского ввода, измерения размеров окна, сигналы его показа и закрытия. Событие приходит в виде аргумента процедуры типа `Sdl2Lib.Event`, и затем с помощью оператора WITH происходит проверка типа переменной. В зависимости от типа, выполняются действия. Процедура `Sdl2Lib.PumpEvents` производит удаление событий из очереди перед закрытием окна, чтобы не получилось, что какие-то события будут обработаны после. При вращении колеса мыши происходит изменение глобальной переменной `zoom`, значение которой влияет на проекцию объектов в процедуре `Viewport`. |  **4.** **Handle** --- обрабатывает события пользовательского ввода, измерения размеров окна, сигналы его показа и закрытия. Событие приходит в виде аргумента процедуры типа `Sdl2Lib.Event`, и затем с помощью оператора WITH происходит проверка типа переменной. В зависимости от типа, выполняются действия. Процедура `Sdl2Lib.PumpEvents` производит удаление событий из очереди перед закрытием окна, чтобы не получилось, что какие-то события будут обработаны после. При вращении колеса мыши происходит изменение глобальной переменной `zoom`, значение которой влияет на проекцию объектов в процедуре `Viewport`. | 
 |  | 
| <code> | <code> | 
| 		stop := TRUE | 		stop := TRUE | 
| 	| e: Sdl2Events.WindowEventClose DO | 	| e: Sdl2Events.WindowEventClose DO | 
| 		IF c # NIL THEN Sdl2Video.GL_DeleteContext(c); c := NIL END;  | 		CloseWindow | 
| 		Sdl2Lib.PumpEvents;  |  | 
| 		Sdl2Video.DestroyWindow(e.window); w := NIL; |  | 
| 	| e: Sdl2Events.WindowEventResized DO | 	| e: Sdl2Events.WindowEventResized DO | 
| 		IF e.w + e.h # 0 THEN | 		IF e.w + e.h # 0 THEN | 
| </code> | </code> | 
 |  | 
| **Do** --- является реализацией отложенных действий в каркасе Блэкбокс, которые позволяют путем рекурсивной установки нового действия в очередь вызывать периодическое обновления содержимого окна, если требуется перерисовка. |  **5.** **Do** --- является реализацией отложенных действий в каркасе Блэкбокс, которые позволяют путем рекурсивной установки нового действия в очередь вызывать периодическое обновления содержимого окна, если требуется перерисовка. | 
 |  | 
| <code> | <code> | 
| PROCEDURE (a: Update) Do; | PROCEDURE (a: Action) Do; | 
| BEGIN | BEGIN | 
| 	IF (c # NIL) & update THEN  | 	IF c # NIL THEN  | 
| 		Viewport;  | 		IF update THEN  | 
| 		Render;  | 			Viewport;  | 
| 		update := FALSE;  | 			Render;  | 
| 	END;  | 			update := FALSE  | 
| 	Services.DoLater(a, Services.Ticks()+50) | 		END;  | 
|   | 		Services.DoLater(a, Services.Ticks()+50)  | 
|   | 	END | 
| END Do; | END Do; | 
| </code> | </code> | 
 |  | 
| **Start** --- загружает необходимые реализации, созает окно, инициализирует OpenGL, создает петлю для обработки событий пользовательского ввода и запускает рекурсивный вызов действий для обновления содержимого окна.  |  **6.** **Start** --- загружает необходимые реализации, созает окно, инициализирует OpenGL, создает петлю для обработки событий пользовательского ввода и запускает рекурсивный вызов действий для обновления содержимого окна.  | 
 |  | 
| <code> | <code> | 
| PROCEDURE Start*; | PROCEDURE Start*; | 
| VAR res: INTEGER; updater: Update; | VAR res: INTEGER; | 
| BEGIN | BEGIN | 
| 	(* Loading realisation of Sdl2Std abstract interface *) | 	(* Loading realisation of Sdl2Std abstract interface *) | 
| 		HALT(20) | 		HALT(20) | 
| 	END; | 	END; | 
| 	 |   | 
| 	 | 	 | 
| 	width := initWidth; | 	width := initWidth; | 
| 	height := initHeight; | 	height := initHeight; | 
| 	 | 	 | 
|   | 	CloseWindow; | 
|   | 	Sdl2Lib.Quit; | 
| 	res := Sdl2Lib.Init(Sdl2Const.INIT_VIDEO + Sdl2Const.INIT_EVENTS); | 	res := Sdl2Lib.Init(Sdl2Const.INIT_VIDEO + Sdl2Const.INIT_EVENTS); | 
|   | 	 | 
| 	w := Sdl2Video.CreateWindow("OpenGL window", 100, 100, width, height, | 	w := Sdl2Video.CreateWindow("OpenGL window", 100, 100, width, height, | 
| 		Sdl2Const.WINDOW_OPENGL + Sdl2Const.WINDOW_RESIZABLE); | 		Sdl2Const.WINDOW_OPENGL + Sdl2Const.WINDOW_RESIZABLE); | 
| 	Gl.Enable(Gl.GL_COLOR_MATERIAL); | 	Gl.Enable(Gl.GL_COLOR_MATERIAL); | 
| 	Gl.ColorMaterial(Gl.GL_FRONT, Gl.GL_AMBIENT_AND_DIFFUSE); | 	Gl.ColorMaterial(Gl.GL_FRONT, Gl.GL_AMBIENT_AND_DIFFUSE); | 
| 	 |   | 
| 	Viewport; | 	Viewport; | 
| 	 | 	 | 
| 	NEW(l);  | 	NEW(loop);  | 
| 	Sdl2Lib.StartLoop(l); | 	Sdl2Lib.StartLoop(loop); | 
| 	 | 	 | 
| 	update:= FALSE; | 	update:= FALSE; | 
| 	NEW(updater);  | 	IF updater = NIL THEN NEW(updater) END;  | 
| 	Services.DoLater(updater, Services.now);  | 	Services.DoLater(updater, Services.now) | 
| 	 |  | 
| END Start; | END Start; | 
|   | </code> | 
|   |  | 
|   |  | 
|   | ===== Создание отдельного приложения ===== | 
|   |  | 
|   | Предыдущий пример показывает, как создать окно непосредственно из среды Блэкбокс. | 
|   |  | 
|   | В документации примеров **Sdl2ObxModels** и **Sdl2ObxIcosphere** содержаться примеры команд сборки независимых приложений OS Windows и других платформ. | 
|   |  | 
|   | При этом в секции ''BEGIN'' главного модуля вызывается запускающая процедура, которая содержит цикл | 
|   |  | 
|   | <code> | 
|   | quit := FALSE; | 
|   | WHILE ~ quit DO | 
|   | 	(* drive services for actions loop *) | 
|   | 	Services.actionHook.Step; | 
|   | 	Sdl2Lib.Delay(10) | 
|   | END; | 
|   | Sdl2Lib.Quit | 
|   | </code> | 
|   |  | 
|   | Этот цикл обеспечивает работу механизма отложенных действий в Блэкбоксе. | 
|   |  | 
|   | Чтобы не делать отдельные модули для демонстрации сборки автономных приложений, используется прием условной компиляции, где в скобках около имени модуля указывается вариант фрагмента в исходных кодах. | 
|   |  | 
|   | ''Sdl2ObxIcosphere(mode:standalone)'' | 
|   |  | 
|   | При этом в исходных кодах варианты оформлены с помощью так называемых <<селекторов>>. Этот прием условной компиляции был удобен для демонстрации, но не рекомендуется использовать его в ваших итоговых проектах. | 
|   |  | 
|   | Готовое приложение необходимо распространять вместе с набором библиотек. | 
|   |  | 
|   | В операционных системах GNU/Linux, OpenBSD или FreeBSD еще необходимо задать переменную окружения, где лежат библиотеки. В этом случае удобно создать отдельный sh скрипт для запуска: | 
|   | <code> | 
|   | #!/bin/sh | 
|   | LD_LIBRARY_PATH=./libsdl2:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH | 
|   | ./icosphere $* & | 
| </code> | </code> | 
 |  |