Графика в OpenGL
WinMain инициализирует прикладную программу, отображает на экране её основное окно и, затем, входит в цикл сообщений «поиск и отправка по назначению (диспетчеризация)», который является управляющей структурой верхнего уровня для остальных элементов выполнения прикладной программы. Цикл сообщений завершается, когда получено сообщение WM_QUIT. В этой точке, WinMain завершает работу прикладной… Читать ещё >
Графика в OpenGL (реферат, курсовая, диплом, контрольная)
[Введите текст]
OpenGL (Open Graphics Library — открытая графическая библиотека, графическое API) — спецификация, определяющая независимый от языка программирования платформонезависимый программный интерфейс для написания приложений, использующих двухмерную и трёхмерную компьютерную графику.
Включает более 250 функций для рисования сложных трёхмерных сцен из простых примитивов. Используется при создании компьютерных игр, САПР, виртуальной реальности, визуализации в научных исследованиях. На платформе Windows конкурирует с Direct3D.
Архитектура OpenGL ориентируется на следующие задачи:
cкрыть сложности адаптации различных 3D-ускорителей, предоставляя разработчику единый API.
cкрыть различия в возможностях аппаратных платформ, требуя реализации недостающей функциональности с помощью программной эмуляции;
выполнить специальные матричные операции;
предоставить поддержку распространенных типов кривых и поверхностей.
Основным принципом работы OpenGL является получение наборов векторных графических примитивов в виде точек, линий и многоугольников с последующей математической обработкой полученных данных и построением растровой картинки на экране и/или в памяти. Векторные трансформации и растеризация выполняются графическим конвейером (graphics pipeline), который по сути представляет собой дискретный автомат. Абсолютное большинство команд OpenGL попадают в одну из двух групп: либо они добавляют графические примитивы на вход в конвейер, либо конфигурируют конвейер на различное исполнение трансформаций.
OpenGL является низкоуровневым процедурным API, что вынуждает программиста диктовать точную последовательность шагов, чтобы построить результирующую растровую графику (императивный подход). Это является основным отличием от дескрипторных подходов, когда вся сцена передается в виде структуры данных (чаще всего дерева), которое обрабатывается и строится на экране. С одной стороны, императивный подход требует от программиста глубокого знания законов трёхмерной графики и математических моделей, с другой стороны — даёт свободу внедрения различных инноваций.
1. Технические характеристики
1.1 Цель работы
директива программа архитектура оpengl
Курсовая работа заключается в получении практических навыков по работе с графикой Windows и OpenGL, самостоятельном изучении 32-битного программирования на ассемблере под Windows и в конечном итоге написание программы, демонстрирующей усвоение полученных знаний.
1.2 Описание используемых функций и директивы INVOKE
1.2.1 GetModuleHandle
Функция GetModuleHandle [2] извлекает дескриптор указанного модуля, если файл был отображен в адресном пространстве вызывающего процесса.
Синтаксис
HMODULE GetModuleHandle
LPCTSTR lpModuleName);
Параметры
lpModuleName
Указатель на символьную строку с нулем в конце, которая содержит имя модули (или.dll или. exe файл). Если расширение имени файла опускается, в конец добавляется заданное по умолчанию библиотечное расширение.dll. Символьная строка имени файла может включать в себя конечный символ точки (.), который указывает, что имя модуля не имеет расширения. Строка не должна определять путь. Когда определяется путь, убедитесь, что используются обратные слэши (), а не прямые слэши (/). Имя сравнивается (независимо от ситуации) с именами модулей в текущий момент отображаемыми в адресном пространстве вызывающего процесса.
Если этот параметр — NULL, GetModuleHandle возвращает дескриптор файла, используемый, чтобы создать вызывающий процесс (.exe файл).
Возвращаемые значения Если функция завершается успешно, возвращаемое значение — дескриптор указанного модули.
Если функция завершается ошибкой, возвращаемое значение — NULL.
1.2.2 GetCommandLine
GetCommandLine Возвращает командную строку для текущего процесса.
Собственная функция GetCommandLine возвращает указатель на буфер, выделенный операционной системой, которая является его владельцем. При маршалинге строк, как возвращаемых типов, упаковщик взаимодействия, что он должен с помощью функции освободить память, на которую указывал исходный тип LPTSTR. Чтобы предотвратить автоматическую очистку памяти упаковщиком, управляемый прототип GetCommandLine возвращает вместо строки тип IntPtr (Определяемый платформой тип, который используется для представления указателя или дескриптора.).
1.2.3 WinMain
Функция WinMain [4] вызывается системой как начальная точка входа, для базирующейся на Win32, прикладной программы.
Синтаксис:
int WINAPI WinMain
(
HINSTANCE hInstance, // дескриптор текущего экземпляра окна
HINSTANCE hPrevInstance, // дескриптор предыдущего экземпляра окна
LPSTR lpCmdLine, // указатель на командную строку
int nCmdShow // показывает состояние окна);
Параметры
hInstance
Идентифицирует текущий образец прикладной программы. hPrevInstance
Идентифицирует предыдущий образец прикладной программы. Для базирующейся на Win32 прикладной программы, этот параметр всегда имеет значение ПУСТО (NULL). Если Вам нужно обнаружить, существует ли другой образец уже существующей программы, создайте именованный mutex-объект, используя функцию CreateMutex. Если функция GetLastError возвращает сообщение ERROR_ALREADY_EXISTS, другой образец вашей прикладной программы существует (это создано mutex-объектом). lpCmdLine
Указывает на строку с нулевым символом в конце, определяющую командную строку для прикладной программы. nCmdShow
Определяет, как окно должно быть показано.
Возвращаемые значения Если функция достигла цели, она завершается тогда, когда примет сообщение WM_QUIT, она должно возвратить значение выхода, содержащееся в параметре этого сообщения wParam. Если функция завершается перед вводом цикла сообщения, она должна возвратить 0.
Замечания
WinMain инициализирует прикладную программу, отображает на экране её основное окно и, затем, входит в цикл сообщений «поиск и отправка по назначению (диспетчеризация)», который является управляющей структурой верхнего уровня для остальных элементов выполнения прикладной программы. Цикл сообщений завершается, когда получено сообщение WM_QUIT. В этой точке, WinMain завершает работу прикладной программы, возвращая значение, переданное в параметр wParam сообщения WM_QUIT. Если WM_QUIT было получено в результате вызова PostQuitMessage, значение wParam — значение параметра nExitCode функцииPostQuitMessage. Для получения дополнительной информации, см. Создание Цикла Сообщений (Creating a Message Loop).
1.2.4 ExitProcess
Функция ExitProcess [5] заканчивает работу процесса и всех его потоков.
Синтаксис
VOID ExitProcess (
UINT uExitCode // код выхода для всех потоков
);
Параметры
uExitCode
Определяет код выхода для процесса, и для всех потоков, которые завершают работу в результате вызова этой функции. Используйте функцию GetExitCodeProcess, чтобы получить значение выхода из процесса. Используйте функцию GetExitCodeThread, чтобы получить значение выхода из потока.
Возвращаемые значения У этой функции нет возвращаемого значения.
Замечания Функция ExitProcess — предпочтительный метод завершения процесса. Эта функция обеспечивает чистое отключение процесса. Такое завершение включает в себя вызов функций точек входа всех связанных динамически подключаемых библиотек (DLL) со значениями, указывающими, что процесс отключается от DLL. Если процесс заканчивается путем вызова TerminateProcess, DLL, к которым процесс подключен, не уведомляются о завершении процесса. После того, как все связанные DLL исполнили любое значение завершения, эта функция завершает работу текущего процесса.
Завершение процесса происходит по нижеследующим причинам:
1. Все дескрипторы объектов, открытые процессом, закрываются.
2. Все потоки в процессе завершают свою работу по исполнению кода.
3. Состояние объекта процесса становится сигнальным, удовлетворяя любые потоки, которые ждали завершения процесса.
4. Состояния всех потоков процесса, становятся сигнальными, удовлетворяя любые потоки, которые ждали завершения работы потоков.
5. Состояние завершения процесса изменяется из STILL_ACTIVE в значение выхода процесса.
Завершение процесса не заставляет дочерние процессы закончить свою работу.
Завершение процесса необязательно удаляет объект процесса из операционной системы. Объект процесса удаляется тогда, когда закрывается последний дескриптор процесса.
Функции ExitProcess, ExitThread, CreateThread, CreateRemoteThread и процесс, который запущен, (как результат вызова CreateProcess), в пределах процесса переводятся между собой в последовательный режим. Одновременно в адресном пространстве может происходить только одно из этих событий. Это означает нижеследующие ограничения выполнения:
В ходе запуска процесса и процедуры инициализации DLL, новые потоки могут быть созданы, но они не начинают исполнение кода до тех пор, пока не будет сделана инициализация DLL для процесса.
Одновременно только один поток в процессе может быть инициализирован или отключен процедурой в DLL.
Функция ExitProcess не возвращает значения до тех пор, пока в потоках не отработают в их DLL процедуры инициализации или отключения.
1.2.5 LoadMenu
Функция LoadMenu [6] загружает заданный ресурс меню из исполняемого (.exe) файла программы, связанного с экземпляром приложения.
Синтаксис
HMENU LoadMenu (
HINSTANCE hInstance,
LPCTSTR lpMenuName
);
Параметры
hInstance
Дескриптор модуля, содержащего ресурс меню, который будет загружен.
lpMenuName
Указатель на символьную строку с нулем в конце, которая содержит имя ресурса меню. Или же, этот параметр может состоять из идентификатора ресурса в младшем слове и нулей в старшем слове. Чтобы создать это значение, используйте макрокоманду MAKEINTRESOURCE.
Возвращаемые значения Если функция завершается успешно, возвращаемое значение — дескриптор ресурса меню.
Если функция завершается ошибкой, возвращаемое значение — ПУСТО (NULL).
1.2.6 SetMenu
Функция SetMenu [7] назначает новое меню для заданного окна.
Синтаксис
BOOL SetMenu (
HWND hWnd,
HMENU hMenu);
Параметры
hWnd
Дескриптор окна, к которому назначается меню.
hMenu
Дескриптор нового меню. Если этот параметр имеет значение ПУСТО (NULL), текущее меню окна удаляется.
Возвращаемые значения Если функция завершается успешно, величина возвращаемого значения — не нуль.
Если функция завершается ошибкой, величина возвращаемого значения — нуль. Чтобы получить дополнительные данные об ошибке, вызовите GetLastError.
Замечания Окно перерисовывается, чтобы отразить изменение меню. Меню может быть назначено любому окну, которое — не дочернее окно.
Функция SetMenu заменяет предшествующее меню, если таковое вообще имеется, но оно не уничтожает его.
1.2.7 ShowWindow
Функция ShowWindow [8] устанавливает состояние показа определяемого окна.
Синтаксис
BOOL ShowWindow
(
HWND hWnd, // дескриптор окна
int nCmdShow // состояние показа окна);
Параметры
hWnd
Идентифицирует окно.
nCmdShow
Определяет, как окно должно быть показано. Этот параметр первоначально игнорируется, когда прикладная программа вызывает ShowWindow, если программа, которая запустила прикладную программу, обеспечивает структуру STARTUPINFO. Иначе, при первом вызове функции ShowWindow, это значение должно быть значением, полученным функцией WinMain в ее параметре nCmdShow.
Возвращаемые значения Если функция завершилась успешно, возвращается значение отличное от нуля. Если функция потерпела неудачу, возвращаемое значение — ноль.
Замечания Первый раз, когда программа вызывает ShowWindow, она использует параметр nCmdShow функции WinMain как свой параметр nCmdShow. Последующие обращения к ShowWindow должны использовать одно из значений в данном списке, вместо того, заданного функцией WinMain параметра nCmdShow. Как отмечено в обсуждении параметра nCmdShow, значение nCmdShow игнорируется при первом обращении к ShowWindow, если программа, которая запустила прикладную программу, определяет информацию автозапуска в структуре STARTUPINFO. В этом случае, ShowWindow использует информацию, заданную в структуре STARTUPINFO, чтобы показать окно. На последующих обращениях, прикладная программа должна вызвать ShowWindow с установкой nCmdShow в SW_SHOWDEFAULT, чтобы использовать информацию автозапуска, обеспеченную программой, которая запустила прикладную программу. Например, программа Program Manager устанавливает, что прикладные программы начинаются со свернутого основного окна. Это поведение разработано для следующих ситуаций:
Прикладные программы создают свое основное окно, вызывая CreateWindow с установкой флажка WS_VISIBLE.
Прикладные программы создают свое основное окно, вызывая CreateWindow со сброшенным флажком WS_VISIBLE, а при более позднем обращении к ShowWindow с установкой флаж-ка SW_SHOW, чтобы делать его видимым.
1.2.8 UpdateWindow
Функция UpdateWindow обновляет рабочую область заданного окна, отправляя сообщение WM_PAINT окну, если регион обновления окна не пуст. Функция отправляет сообщение WM_PAINT непосредственно оконной процедуре указанного окна, обходя очередь приложения. Если регион обновления пуст, никакое сообщение не отправляется.
Синтаксис
BOOL UpdateWindow (
HWND hWnd // дескриптор окна
);
Параметры
hWnd
Дескриптор обновляемого окна.
Возвращаемые значения Если функция завершается успешно, возвращаемое значение — не нуль.
Если функция завершается ошибкой, возвращаемое значение — нуль.
1.2.9 GetMessage
Функция GetMessage [10] извлекает сообщение из очереди сообщений вызывающего потока и помещает его в заданную структуру. Эта функция регулирует поступление отправленных сообщений до тех пор, пока помещенное в очередь сообщение доступно для извлечения.
Синтаксис
BOOL GetMessage (
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax);
Параметры
lpMsg
Указатель на структуру MSG, которая принимает информацию из очереди сообщений потока.
hWnd
Дескриптор окна, чьи сообщения должны быть извлечены. Окно должно принадлежать вызывающему потоку. Значение ПУСТО (NULL) имеет специальное предназначение:
1.2.10 DrawScen
Функция DrawScene () [11] использует функцию DirectDrawWin: BltSurface () для копирования поверхности surf1 на поверхность backsurf. Два последних аргумента BltSurface ()определяют точку поверхности-приемника, куда должно быть скопировано содержимое источника. Для выполнения этой операции можно было бы воспользоваться функцией Blt () или BltFast () интерфейсаDirectDrawSurface, но мы не делаем этого из-за возможного отсечения. Обратите внимание — код, определяющий положение растра, позволяет источнику выйти за пределы приемника, в результате чего может потребоваться отсечение. Мы не можем воспользоваться функцией Blt (), потому что тогда потребовалось бы присоединить к приемнику объект DirectDrawClipper, чего мы не делаем. ФункцияBltFast () тоже не подходит, потому что она вообще не поддерживает отсечения. Функция BltSurface () автоматически выполняет отсечение, а функции Blt () и BltFast () вызываются внутри нее.
Функция BltSurface () класса DirectDrawWin оказывается более гибкой и удобной по сравнению с функциями DirectDrawSurface: Blt () и BltFast (). Мы уже видели, как BltSurface ()используется внутри функции BounceWin: DrawScene (), а сейчас рассмотрим саму функцию.
Функция BltSurface () требует передачи четырех аргументов, а пятый аргумент необязателен. Первые два аргумента представляют собой указатели на поверхности — источник и приемник. Следующие два аргумента — координаты x и y, определяющие положение копируемой области на приемнике. По умолчанию блиттинг выполняется без цветовых ключей, однако их можно активизировать с помощью необязательного пятого параметра.
1.2.11 TranslateMessage
Функция TranslateMessage переводит сообщения виртуальных клавиш в символьные сообщения. Символьные сообщения помещаются в очереди сообщений вызывающего потока для прочтения в следующий раз, когда поток вызовет функцию GetMessage или PeekMessage.
Синтаксис
BOOL TranslateMessage (
const MSG* lpMsg
);
Параметры
lpMsg — Указатель на структуру MSG, которая содержит информацию о сообщении извлеченную из очереди сообщений вызывающего потока при помощи использования функции GetMessage или PeekMessage.
Возвращаемые значения Если сообщение переведено (то есть символьное сообщение помещено в очереди сообщений потока), величина возвращаемого значения не нуль.
Если сообщение является WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN или WM_SYSKEYUP, величина возвращаемого значения — не ноль, независимо от результата перевода.
Если сообщение не переведено (то есть символьное сообщение не помещено в очереди сообщений потока), величина возвращаемого значения — нуль.
1.2.12 DispatchMessage
Функция распределяет сообщение оконной процедуре. Обычно она используется, чтобы доставить сообщение, извлеченное функцией GetMessage.
Синтаксис
LRESULT DispatchMessage (const MSG* lpmsg);
Параметры
lpmsg
Указатель на структуру MSG, которая содержит сообщение.
Возвращаемое значение Величина возвращаемого значения определяется значением, которое возвращает оконная процедура. Несмотря на то, что это значение зависит от отправляемого сообщения, возвращаемое значение, как правило, игнорируется.
1.2.13 GetClientRect
Функция GetClientRect [14] извлекает координаты рабочей области окна. Рабочие координаты определяют левый верхний и нижний правый углы рабочей области. Поскольку рабочие координаты определены относительно левого верхнего угла рабочей области окна, координаты левого верхнего угла — (0,0).
Синтаксис
BOOL GetClientRect
(
HWND hWnd, // дескриптор окна
LPRECT lpRect // адрес структуры рабочих координат
);
Параметры
hWnd
Идентифицирует окно, рабочие координаты которого должны быть возвращены.
lpRect
Указывает на структуру RECT, которая принимает рабочие координаты. Левые и верхние элементы — нулевые. Правые и нижние элементы содержат ширину и высоту окна.
Возвращаемые значения Если функция завершается успешно, возвращаемое значение отлично от нуля. Если функция потерпит неудачу, возвращаемое значение нулевое.
1.2.14 DestroyWindow
Функция DestroyWindow уничтожает определенное окно. Функция посылает сообщения WM_DESTROY и WM_NCDESTROY окну, чтобы дезактивировать его и удалить фокус клавиатуры из него. Функция также уничтожает меню окна, очищает очередь потоков сообщений, уничтожает таймеры, удаляет монопольное использование буфера обмена и разрывает цепочку просмотра окон буфера обмена (если окно имеет наверху цепочку просмотров). Если определенное окно — родитель или владелец окон, DestroyWindow автоматически уничтожает связанные дочерние или находящиеся в собственности окна, когда она уничтожает окно владельца или родителя. Функция сначала уничтожает дочерние или находящиеся в собственности окна, и затем она уничтожает окно владельца или родителя. DestroyWindow также уничтожает немодальные диалоговые окна, созданные функцией CreateDialog.
Синтаксис
BOOL DestroyWindow
(
HWND hWnd // дескриптор для разрушения окна
);
Параметры
hWnd
Идентификатор окна, которое будет разрушено.
Возвращаемые значения Если функция завершается успешно, возвращаемое значение отлично от нуля. Если функция не выполняет задачу, возвращаемое значение нулевое. Чтобы получать расширенные данные об ошибках, вызовите GetLastError.
Замечания Поток не может использовать DestroyWindow, чтобы уничтожить окно, созданное другим потоком. Если разрушаемое окно — дочернее окно, которое не имеет стиля WS_EX_NOPARENTNOTIFY, сообщение WM_PARENTNOTIFY посылается родителю.
1.2.15 PostQuitMessage
Функция PostQuitMessage [16] указывает системе, что поток сделал запрос на то, чтобы завершить свою работу (выйти). Это обычно используется в ответ на сообщение WM_DESTROY.
Синтаксис
void PostQuitMessage (
int nExitCode
);
Параметры
nExitCode
Определяет код завершения прикладной программы. Это значение используется как параметр wParam сообщения WM_QUIT.
Возвращаемые значения Возвращаемых значений нет.
Замечания Функция PostQuitMessage помещает сообщение WM_QUIT в очередь сообщений потока и немедленно возвращает значение; функция просто указывает системе, что потоку требуется прекратить свою работу в какое-то время в будущем.
Когда поток извлекает сообщение WM_QUIT из своей очереди сообщений, он должен выйти из своего цикла обработки сообщений и возвратить управление системе. Значение выхода, возвращенное системой должно быть параметром wParam сообщения WM_QUIT.
1.2.16 DefWindowProc
Функция DefWindowProc [17] вызывается оконной процедурой по умолчанию, чтобы обеспечить обработку по умолчанию любого сообщения окна, которые приложение не обрабатывает. Эта функция гарантирует то, что обрабатывается каждое сообщение. Функция DefWindowProc вызывается с теми же самыми параметрами, принятыми оконной процедурой.
Синтаксис
LRESULT DefWindowProc
HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam;
Параметры
hWnd
Дескриптор оконной процедуры, которая получает сообщение.
Msg
Определяет сообщение.
wParam
Определяет дополнительную информацию о сообщении. Содержание этого параметра зависит от значения параметра Msg.
lParam
Определяет дополнительную информацию о сообщении. Содержание этого параметра зависит от значения параметра Msg.
Возвращаемые значения Величина возвращаемого значения определяет результат обработки сообщения и зависит от сообщения.
1.2.17 WglCreateContext
WglCreateContext [18] функция создает новый контекст рендеринга OpenGL, которая подходит для нанесения на устройство ссылается HDC. Оказание контексте имеет тот же формат пикселов, что и контекст устройства.
Синтаксис
HGLRC WINAPI wglCreateContext (
HDC HDC
);
Параметры
HDC
Handle на контекст устройства, для которых функция создает подходящую оказания OpenGL контекст.
Возвращаемое значение Если функция завершается успешно, возвращаемое значение является правильным дескриптором контекста рендеринга OpenGL.
Если функция завершается ошибкой, возвращаемое значение NULL. Чтобы получить расширенную информацию об ошибке, вызовите GetLastError.
Замечания Оказание контексте не то же самое, как контекст устройства. Установить формат пикселей контекста устройства, прежде чем создавать контекст рендеринга. Для получения дополнительной информации о настройке формат пикселя в контексте устройства, см. SetPixelFormat функции.
Для использования OpenGL, вы создаете контекст визуализации, выбрать его в качестве текущего контекста визуализации потока, а затем вызвать OpenGL функций. Когда вы закончите с оказанием контексте, вы распоряжаться им по телефону wglDeleteContext функции.
1.2.18 INVOKE
С Microsoft Macro Assembler (MASM) версии 6.0, написание кода для вызова процедуры может упростить с помощью директивы PROTO и INVOKE. Эти директивы обработки множества данных, помещают параметры в стек в правильном порядке, создают правильные внешние ссылки, преобразуют аргументы нужного размера и очищают стек (если требуется) после завершения функции.
PROTO определяет прототип для процедуры гораздо способ работы прототип функции в C. Это синтаксис PROTO:
label PROTO [distance] [langtype] [,[parameter]: tag]
PROTO оператор используется для проверки типов параметров и количество, а также соглашение об именах для функции, указывающий ассемблер. Вывод типа и, при необходимости, имя параметра указываются аргументы функции.
Например,
myfunc PROTO C arg1: SWORD, arg2: SBYTE
Это означает, что функция myfunc принимает два аргумента. Во-первых, подписанный слова, второй — в байт со знаком. Если требуется список аргументов переменных, следует использовать с переменным количеством АРГУМЕНТОВ типа.
Фактически, INVOKE создает код для вызова функции. Необходимо определить функцию ранее PROC, EXTERNDEF, определение ТИПА или имя оператора. Далее представлен синтаксис для ВЫЗОВА:
INVOKE expression [, arguments]
Поскольку ассемблер обладает функцией является ожидается в отношении аргументов, соглашение о вызовах, он может принимать аргументы, переданные в операторе ВЫЗОВА их помещают в стек в правильном порядке, вызов функции, используя имя функции, необходимые и очистку стека после этого (если требуется использовать соглашение о вызовах).
Если аргумент, передаваемый методом INVOKE меньше типа, указанного в операторе PROTO, MASM выполняет преобразование типов. Он может быть расширен в аргументе оператора PROTO в соответствии в операторе ВЫЗОВА (например, SBYTE на КОНЦАХ). Эти типы преобразований используют регистры 8086 и 8088 AX и DX и регистра EAX и EDX на 80 386/80486. Поскольку эти регистры эффективно перезаписываются, следует позаботиться следует применять эти регистры для передачи аргументов.
Тип языка для функции определяет правила именования и вызывающий. В дополнение к типу языка в операторе PROTO, можно задать тип языка. МОДЕЛЬ директивы, параметр LANGTYPE, или /Gc переключатели командной строки (для Pascal) и /Gd (для C). Имеется таблица различные языковые соглашения содержатся в справке.
2. Текст программы
2.1 Описание
Оpengl.asm — содержит процедуры WinMain — она создает окно, WndProc — обрабатывает поступающие сообщения, RegisterWinClass — регистрация класса окна и TopXY — необходима для позиционирования окна на экране
Opengl.inc — содержит список подключаемых библиотек, необходимый минимальный набор макросов, секцию. data, где инициализируются необходимы переменные, список подключаемых файлов — здесь он один — это opngl. asm и прототипы функций.
Opngl.asm Именно он подключает и инициализирует OpenGL. В секции данных определяются три идентификатора — окна программы, связки с OpenGL и формата экранных пикселей. Затем — прототипы функций DrawScene — именно она отвечает за события на экране и Init, которая инициализирует OpenGL. Функция Init вызывается при создании окна.
2.2 opengl. inc
include c: osmasm32includewindows. inc
include c: osmasm32includeuser32. inc
include c: osmasm32includekernel32. inc
include c: osmasm32includegdi32. inc
include c: osmasm32includeopengl32. inc
include c: osmasm32includeglu32. inc
include c: osmasm32includemasm32. inc
includelib c: osmasm32libuser32. lib
includelib c: osmasm32libkernel32. lib
includelib c: osmasm32libgdi32. lib
includelib c: osmasm32libopengl32. lib
includelib c: osmasm32libglu32. lib
includelib c: osmasm32libmasm32. lib
; Объявление локальных макросов
szText MACRO Name, Text: VARARG; Дает возможность определить последовательность байт (символов) — содержимое параметра Text, закачивающуюся 0×0 (С-строка) с именем, определяемым параметром Name. (Макрокоманда или макрос — программный объект, который во время вычисления заменяется на новый объект, создаваемый определением макроса на основе его аргументов, затем выражается обычным образом.
LOCAL lbl
jmp lbl
Name db Text, 0
lbl:
ENDM
m2m MACRO M1, M2
push M2
pop M1
ENDM
return MACRO arg
mov eax, arg
ret
ENDM
literal MACRO quoted_text:VARARG
LOCAL local_text
.data
local_text db quoted_text, 0
align 4
.code
EXITM
ENDM
SADD MACRO quoted_text:VARARG
EXITM
ENDM
top MACRO arg
lea eax, arg
invoke glVertex3f,[eax],[eax+4],[eax+8]
ENDM
put2scene MACRO num, arg
invoke glPushMatrix;система кординат
lea eax, arg
mov ecx,[eax]
mov ebx,[eax+4]
mov eax,[eax+8]
invoke glTranslatef, ecx, ebx, eax
invoke glCallList, num
invoke glPopMatrix
ENDM
rotate MACRO num, pos, speed, angles
invoke glPushMatrix
invoke Rotate, num, pos, speed, angles
invoke glPopMatrix
ENDM
; ############################################################
.data
szClassName db «OpenGl», 0
szDisplayName db ««, 0
CommandLine dd 0
hWnd dd 0
hInstance dd 0
hIcon dd 0
hCursor dd 0
; ###########################################################
include opngl. asm
; ############################################################
WinMain PROTO: DWORD:DWORD:DWORD:DWORD
RegisterWinClass PROTO:
DWORD:DWORD:DWORD:DWORD:DWORD
WndProc PROTO: DWORD:DWORD:DWORD:DWORD
TopXY PROTO: DWORD:DWORD
2.3 opngl. asm
.data
MainHDC dd 0
OpenDC dd 0
PixFrm PIXELFORMATDESCRIPTOR <>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Позиции объектов определяются в секции данных:
CentrePosition dd 0.0,0.1,-5.0
CentreAngles dd 0.0,0.0,0.0
CentreSpeed dd -0.5,0.0,0.0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SpherePosition1 dd 1.0,1.0,0.0
SphereRadius1 dq 1.0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SpherePosition2 dd 0.7,0.0,0.0;0.7,0.0,0.0
SphereRadius2 dq 0.4
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SpherePosition3 dd 0.0,0.5,0.0
SphereRadius3 dq 0.3
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SpherePosition4 dd 0.2,0.1,0.0;0.3,0.1,0.0
SphereRadius4 dq 0.1
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SpherePosition5 dd 0.1,-0.5,0.0;0.2,-0.5,0.0
SphereRadius5 dq 0.1
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SpherePosition6 dd 0.0,0.1,0.6
SphereRadius6 dq 0.3
SpherePosition7 dd -0.6,-0.2,0.2
SphereRadius7 dq 0.1
CylinderPosition dd -0.5,0.0,-0.8
CylinderRadius dq 1.0,1.1,1.0;0.25,0.15,0.4;конус форма
DiskPosition dd 0.0,0.0,-1.4; 0.0,0.2,0.0,-90.0,1.0,0.0,0.0
DiskRadius dq 0.5,1.1
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
LightPosition dd -2.0,0.0,2.0,0.0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;glColor3f (0.0, 0.0, 0.0); //черный
;glColor3f (1.0, 0.0, 0.0); //красный
;glColor3f (0.0, 1.0, 0.0); //синий
;glColor3f (0.0, 0.0, 1.0); //зеленый
;glColor3f (1.0, 1.0, 0.0); //желтый
;glColor3f (0.0, 1.0, 1.0); //голубой
;glColor3f (1.0, 0.0, 1.0); //пурпурный
;glColor3f (1.0, 1.0, 1.0); //белый
green dd 0.0,1.0,0.4
orange dd 1.0,0.4,0.0
purpur dd 1.0, 0.0, 1.0
white dd 0.9,0.9,1.0
black dd 0.2,0.2,0.2
red dd 1.0,0.0, 0.0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
dFloat0 dd 0.0
dFloat1 dd 1.0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
RotSpeed dd 0.0,0.0,0.0
RotAngles dd 0.5,0.5,0.5
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Float45 dq 45.0
Float3 dq 3.0
Float9 dq 18.0
Float1 dq 1.0
.code
ResizeObject PROTO: DWORD:DWORD
DrawScene PROTO
Init PROTO: DWORD
CreateObjects PROTO: DWORD:DWORD
SolidCylinder PROTO: DWORD:DWORD:DWORD:DWORD
WireCylinder PROTO: DWORD:DWORD:DWORD:DWORD:DWORD
CreateLight PROTO
Rotate PROTO: DWORD:DWORD:DWORD:DWORD
SolidSphere PROTO: DWORD:DWORD:DWORD:DWORD
SolidDisk PROTO: DWORD:DWORD:DWORD:DWORD
; ###########################################################
ResizeObject PROC ParentW: DWORD, ParentH: DWORD
invoke glViewport, 0,0,ParentW, ParentH
invoke glMatrixMode, GL_PROJECTION
invoke glLoadIdentity
invoke gluPerspective, DWORD PTR Float45, DWORD PTR Float45+4,DWORD PTR Float1, DWORD PTR Float1+4,DWORD PTR Float3, DWORD PTR Float3+4,DWORD PTR Float9, DWORD PTR Float9+4; создать матрицу перспективной проекции
invoke glMatrixMode, GL_MODELVIEW
invoke glLoadIdentity
ret
ResizeObject ENDP
; ############################################################
CreateObjects PROC ParentW: DWORD, ParentH: DWORD; Создать эти объекты:
invoke SolidSphere, 1, ADDR orange, ADDR SphereRadius1,24
invoke SolidSphere, 2, ADDR white, ADDR SphereRadius2,24
invoke SolidSphere, 3, ADDR white, ADDR SphereRadius3,24
invoke SolidSphere, 4, ADDR black, ADDR SphereRadius4,24
invoke SolidSphere, 5, ADDR black, ADDR SphereRadius5,24
invoke SolidSphere, 6, ADDR red, ADDR SphereRadius6,24
invoke SolidSphere, 7, ADDR purpur, ADDR SphereRadius7,24
invoke SolidDisk, 8, ADDR green, ADDR DiskRadius, 24
invoke SolidCylinder, 9, ADDR green, ADDR CylinderRadius, 24
invoke glMatrixMode, GL_PROJECTION
ret
CreateObjects ENDP; CreateObjects Функция CreateObjects считывает информацию о графических объектах из файла и помещает ее в список. Параметры: cpFileName — имя файла, pList — указатель на список графических объектов. Возвращаемое значение: код ошибки. */
; ############################################################
DrawScene PROC
invoke CreateLight
invoke glClear, GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT
invoke glPushMatrix
Установка деталей в необходимое положение происходит в функции Rotate:
каждый последующий объект позиционируется относительно предыдущего. Позиция задает не только координаты каждой детали, но и начальную ориентацию детали относительно осей координат — четвертый элемент массива — это угол поворота, пятый, шестой и седьмой элементы показывают, вокруг каких осей производится поворот (1 — есть поворот, 0 — нет). Установка деталей в необходимое положение происходит в функции Rotate:
invoke Rotate, 1, ADDR CentrePosition, ADDR CentreSpeed, ADDR CentreAngles
invoke Rotate, 2, ADDR SpherePosition2, ADDR RotSpeed, ADDR RotAngles
invoke Rotate, 3, ADDR SpherePosition3, ADDR RotSpeed, ADDR RotAngles
invoke Rotate, 4, ADDR SpherePosition4, ADDR RotSpeed, ADDR RotAngles
invoke Rotate, 5, ADDR SpherePosition5, ADDR RotSpeed, ADDR RotAngles
invoke Rotate, 6, ADDR SpherePosition6, ADDR RotSpeed, ADDR RotAngles
invoke Rotate, 7, ADDR SpherePosition7, ADDR RotSpeed, ADDR RotAngles
invoke Rotate, 8, ADDR DiskPosition, ADDR RotSpeed, ADDR RotAngles
invoke Rotate, 9, ADDR CylinderPosition, ADDR RotSpeed, ADDR RotAngles
invoke glPopMatrix
invoke SwapBuffers, MainHDC
ret
DrawScene ENDP
; ############################################################
CreateLight PROC
invoke glLightfv, GL_LIGHT0,GL_POSITION, ADDR LightPosition; Устанавливаем источник света в заданную позицию
invoke glEnable, GL_LIGHT0;
ret
CreateLight ENDP
; ############################################################
SolidCylinder PROC ListNumber: DWORD, Color: DWORD, Radius: DWORD, Parts: DWORD
LOCAL hCylinder: DWORD
invoke glNewList, ListNumber, GL_COMPILE_AND_EXECUTE; Для того, чтобы занести в список некоторую последовательность команд надо поместить их между командными скобками glNewList и glEndList. Первый аргумент команды glNewList — номер списка. Вы можете использовать большое количество списков в своей программе и каждый из них будет иметь свой номер. В принципе можно самому задавать числа, но для того чтобы избежать наложений рекомендуется использовать специальную команду, которая генерирует номера списков и первый номер возвращает в вашу переменную. В качестве аргумента она принимает количество номеров списков, которое вы хотите получить.
invoke gluNewQuadric; Функция gluNewQuadric создает новый объект нужного нам типа (в реальности просто создается указатель на пустую структуру).
mov hCylinder, eax
invoke gluQuadricDrawStyle, hCylinder, GLU_FILL; Теперь устанавливаете свойства с помощью функции gluQuadricDrawStyle. Доступны стили: GLU_FILL — рисуется сплошной объект, GLU_LINE — проволочный объект, GLU_POINT — рисуются только точки.
invoke gluQuadricNormals, hCylinder, GL_SMOOTH; определяет, строятся ли нормали для каждой вершины, для всего сегмента либо вообще не строятся.
invoke glColor3fv, Color; У OpenGL есть ф-ии, которые принимают в качестве параметра адрес такой структуры. Все такие ф-ии оканчиваются на 3fv,
mov eax, Radius
invoke gluCylinder, hCylinder,[eax],[eax+4],[eax+8],[eax+12],[eax+16],[eax+20], Parts, Parts;цилиндр
invoke glEndList
mov eax, hCylinder
ret
SolidCylinder ENDP
; ############################################################
SolidSphere PROC ListNumber: DWORD, Color: DWORD, Radius: DWORD, Parts: DWORD
LOCAL hSphere: DWORD
invoke glNewList, ListNumber, GL_COMPILE_AND_EXECUTE
invoke gluNewQuadric
mov hSphere, eax
invoke gluQuadricDrawStyle, hSphere, GL_FILL
invoke gluQuadricNormals, hSphere, GL_SMOOTH
invoke glColor3fv, Color
mov eax, Radius
invoke gluSphere, hSphere,[eax],[eax+4], Parts, Parts
invoke glEndList
mov eax, hSphere
ret
SolidSphere ENDP
; ###########################################################
SolidDisk PROC ListNumber: DWORD, Color: DWORD, Radius: DWORD, Parts: DWORD
LOCAL hDisk: DWORD
invoke glNewList, ListNumber, GL_COMPILE_AND_EXECUTE
invoke gluNewQuadric
mov hDisk, eax
invoke gluQuadricDrawStyle, hDisk, GLU_FILL
invoke gluQuadricNormals, hDisk, GL_SMOOTH
invoke glColor3fv, Color
mov eax, Radius
invoke gluDisk, hDisk,[eax],[eax+4],[eax+8],[eax+12], Parts, Parts
invoke glEndList
mov eax, hDisk
ret
SolidDisk ENDP
; ############################################################
Rotate PROC ListNumber: DWORD, ZYXPosition: DWORD, ZYXRotations: DWORD, ZYXAngles: DWORD
mov eax, ZYXPosition
invoke glTranslatef,[eax],[eax+4],[eax+8]; Функция glTranslate (x, y, z) перемещает оси координат на указанные значения.
mov eax, ZYXPosition
invoke glRotatef,[eax+12],[eax+16],[eax+20],[eax+24]; отвечает за вращения объекта вдоль оси. Вы многое получите от использования этой команды. Угол некоторое число (обычно переменная), которое задает насколько Вы хотите повернуть объект.
mov eax, ZYXAngles
mov ebx, ZYXRotations
fld DWORD PTR [eax]
fadd DWORD PTR [ebx]
fstp DWORD PTR [eax]
invoke glRotatef,[eax], dFloat1, dFloat1,dFloat1; отвечает за вращения объекта вдоль оси
invoke glCallList, ListNumber;вызов списка
ret;возарвт
Rotate ENDP
; ############################################################
Init proc hWn: DWORD
LOCAL WINRect: RECT
LOCAL PixFormat: DWORD
invoke GetDC, hWn
mov MainHDC, eax
mov ax, SIZEOF PixFrm
mov PixFrm. nSize, ax
mov PixFrm. nVersion, 1
mov PixFrm. dwFlags, PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER
mov PixFrm. dwLayerMask, PFD_MAIN_PLANE
mov PixFrm. iPixelType, PFD_TYPE_RGBA
mov PixFrm. cColorBits, 8
mov PixFrm. cDepthBits, 16
mov PixFrm. cAccumBits, 0
mov PixFrm. cStencilBits, 0
invoke ChoosePixelFormat, MainHDC, ADDR PixFrm; она определит какой из системных форматов больше всего подходит к интересующему нас формату пикселей:
mov PixFormat, eax
invoke SetPixelFormat, MainHDC, PixFormat, ADDR PixFrm; Заполнив все поля, выполняем запрос на выбор подходящего формата. Делаем это с помощью функции ChoosePixelFormat. Если функция не возвратила ноль, можно установить данный формат функцией SetPixelFormat.
or eax, eax
jz Fail
invoke wglCreateContext, MainHDC
mov OpenDC, eax
invoke wglMakeCurrent, MainHDC, OpenDC; Если удалось установить пиксельный формат, то теперь нужно создать просчитывающий контекст (rendering context) OpenGL. Это делается вызовом функции wglCreateContext (). Далее, созданный контекст выставляется текущим функцией wglMakeCurrent ().
invoke GetClientRect, hWn, ADDR WINRect
invoke CreateObjects, WINRect. right, WINRect. bottom
invoke glEnable, GL_DEPTH_TEST;освещение
invoke glEnable, GL_LIGHTING
invoke glShadeModel, GL_SMOOTH
invoke glEnable, GL_NORMALIZE
invoke glEnable, GL_COLOR_MATERIAL
jmp abrt
Fail:
invoke MessageBox, hWn, SADD («OpenGL инициализировaть не удалось»), SADD («Отчет об инициализации»), MB_OK
abrt:
return 0
Init endp
2.4 opengl. asm
.386;тип процессора
.model flat, stdcall; модель памяти и вызова подпрограмм; объявление включаемых (заголовочных) файлов, макросов, макроопределений,; также внешних определений
option casemap: none; CaseMap: NONE (эквивалентно / Cx) сохраняет случае идентификаторы в общественных местах, COMM, EXTERNDEF, EXTERN, PROTO и PROC деклараций.
include opengl. inc
; ###########################################################
.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax; hInstance — уникальный идентификатор текущего экземпляра приложения
invoke GetCommandLine
mov CommandLine, eax
invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
invoke ExitProcess, eax
; ############################################################
WinMain proc hInst: DWORD,
hPrevInst:DWORD,
CmdLine:DWORD,
CmdShow:DWORD
LOCAL msg: MSG
LOCAL Wwd: DWORD
LOCAL Wht: DWORD
LOCAL Wtx: DWORD
LOCAL Wty: DWORD
invoke LoadIcon, hInst, 500
mov hIcon, eax
invoke LoadCursor, NULL, IDC_ARROW
mov hCursor, eax
invoke RegisterWinClass, ADDR WndProc, ADDR szClassName,
hIcon, hCursor, COLOR_BTNFACE+1
mov Wwd, 500
mov Wht, 500
invoke GetSystemMetrics, SM_CXSCREEN
invoke TopXY, Wwd, eax
mov Wtx, eax
invoke GetSystemMetrics, SM_CYSCREEN
invoke TopXY, Wht, eax
mov Wty, eax
invoke CreateWindowEx, WS_EX_LEFT,
ADDR szClassName,
ADDR szDisplayName,
WS_OVERLAPPEDWINDOW,
Wtx, Wty, Wwd, Wht,
NULL, NULL,
hInst, NULL
mov hWnd, eax
invoke LoadMenu, hInst, 600
invoke SetMenu, hWnd, eax
invoke ShowWindow, hWnd, SW_SHOWNORMAL
invoke UpdateWindow, hWnd
StartLoop:
invoke GetMessage, ADDR msg, NULL, 0,0
cmp eax, 0
je ExitLoop
invoke DrawScene
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp StartLoop
ExitLoop:
return msg. wParam
WinMain endp
; ############################################################
WndProc PROC hWin: DWORD, uMsg: DWORD, wParam: DWORD, lParam: DWORD
LOCAL rc: RECT
.if uMsg == WM_COMMAND
.if wParam == 1000
invoke SendMessage, hWin, WM_SYSCOMMAND, SC_CLOSE, NULL
.endif
.elseif uMsg == WM_CREATE
invoke Init, hWin
.elseif uMsg == WM_SIZE
invoke GetClientRect, hWin, ADDR rc
invoke ResizeObject, rc. right, rc. bottom
return 0
.elseif uMsg == WM_CLOSE
mov eax, OpenDC
cmp eax, 0
jz outDC
invoke wglDeleteContext, OpenDC
;Обращаться в контексте OpenGL рендеринг, что функция для удаления.
;Возвращаемое значение
;Если функция завершается успешно, возвращаемое значение TRUE.
;Если функция завершается ошибкой, возвращаемое значение FALSE.
outDC:
invoke ReleaseDC, hWin, MainHDC
invoke DestroyWindow, hWin
return 0
.elseif uMsg == WM_DESTROY
invoke PostQuitMessage, NULL
return 0
.endif
invoke DefWindowProc, hWin, uMsg, wParam, lParam
ret
WndProc ENDP
; ############################################################
TopXY proc wDim: DWORD, sDim: DWORD
shr sDim, 1; divide screen dimension by 2 (Разрыва размеров для экрана на 2)
shr wDim, 1; divide window dimension by 2
mov eax, wDim; copy window dimension into eax
sub sDim, eax; sub half win dimension from half screen dimension
return sDim
TopXY endp
; ############################################################
RegisterWinClass proc lpWndProc: DWORD, lpClassName: DWORD,
Icon:DWORD, Cursor: DWORD, bColor: DWORD
LOCAL wc: WNDCLASSEX
mov wc. cbSize, sizeof WNDCLASSEX
mov wc. style, CS_VREDRAW or
CS_HREDRAW
m2m wc. lpfnWndProc, lpWndProc
mov wc. cbClsExtra, NULL
mov wc. cbWndExtra, NULL
m2m wc. hInstance, hInstance
m2m wc. hbrBackground, bColor
mov wc. lpszMenuName, NULL
m2m wc. lpszClassName, lpClassName
m2m wc. hIcon, Icon
m2m wc. hCursor, Cursor
m2m wc. hIconSm, Icon
invoke RegisterClassEx, ADDR wc
ret
RegisterWinClass endp
; ############################################################
end start
2.5 Результаты выполнения программы
Рис. 3.1
Выводы
В ходе выполнения курсовой работы были изучены основы работы с OpenGL, была написана программа на MASM.