MASM.OpenGL.1.First.Blood

Дата публикации 21 июл 2003

MASM.OpenGL.1.First.Blood — Архив WASM.RU

MASM.OPENGL - Глава 1

x z a z e t
787A617A6574406E61726F642E7275

MASM.OPENGL

GLьчатай, открой личико!

В предыдущей части мы занимались теорией, а сегодня пришло время практики. Давайте разбираться.

Скелет нашей первой программы.

Синими рамками обведены процедуры нашей программы, в которых мы будем обращатся к подпрограммам API OpenGL. В принципе больше комментировать здесь нечего. Если вы хорошо поработали над уроками Win32API от Iczelion'a, остальная часть схемы (подпрограммы в черных рамках) не должна вызвать недоумения. Если это не так, то работу над Win32API придется продолжить. Остальным слушателям предлагаю перейти к следующей главе.

Таможня дает "добро"

Давайте посмотрим на подпрограмму "CreateOGLWindow" повнимательнее. Ее название говорит само за себя - мы создаем окно, в котором будут отображаться результаты нашего творчества в построении 3D виртуальной реальности. В следующей таблице расписаны шаги нашей подпрограммы, а также состояние OpenGL после каждого из них.

CreateOGLWindow Состояние OpenGL
Создаем окно windows приложения --неактивен--
Запрашиваем ОС Windows контекст устройства нашего окна --неактивен--
Настраиваем контекст устройства нашего окна для работы с ним на OpenGL --неактивен--
Сообщаем OpenGL о подготовленном контексте устройства OpenGL создает контекст рендеринга (изображения), пригодный для работы с нашим окном (контекстом устройства)
Выбираем созданный ОpenGL'ем контекст изображения (рендеринга) для построения 3D сцен командами API OpenGL OpenGL готов к работе на выбранном контексте изображения - ожидает от нас команды для исполнения ( путь в 3D мир открыт!)
MOV EAX, ECX (или любая другая) OpenGL активен (ждет команды)

Cразу договоримся - мы будем смотреть на работу нашей программы с API OpenGL как на общение Клиента (наша программа) с Сервером (OpenGL). Представим на минутку, что мы пытаемся взломать секретный Сервер "OpenGL". Что нужно сделать сначала? Определить по какому сетевому протоколу нам удобнее приконектиться к серверу! Допустим, мы выбрали протокол ABC_32бита. Это хорошо, но настоящие "кулхацкеры" не вламываются на секретные сервера со своего домашнего компьютера! Они вламываются с убитых PСишек (напомню, мы работаем в MASM) деревенских интернет-кафе.

Давайте посмотрим на подпрограмму "CreateOGLWindow" повнимательнее. Ее название говорит само за себя - мы создаем окно, в котором будут отображаться результаты нашего творчества в построении 3D виртуальной реальности. В следующей таблице расписаны шаги нашей подпрограммы, а также состояние OpenGL после каждого из них.

Поддерживается ли на них нужный нам протокол ABC_32бита? Нужно обязательно проверить его наличие перед использованием. Если он не поддерживается, то выбираем другой протокол или отказываемся от идеи взлома. По-моему, пока все логично. На этот раз нам повезло – PCшка поддерживает протокол АВС_16бит (хуже, чем ABC_32бита, но хоть что-то). Мы посылаем команду серверу OpenGL с запросом на соединение по протоколу ABC_16бит и получаем сообщение, что сервер готов к соединению. Дальше дело техники - сделать соединение активным. И всё, сервер ОpenGL ожидает от нас команд для исполнения.

Не бойтесь контекстов устройств (device context) – они не кусаются. Вспомним наше дество: детский сад, строгую воспитательницу и неуемную страсть к рисованию. (на стенах, ватманах, на руках шариковой ручкой, на новеньком БМВ богатого дяди острым гвоздем). Но в детском саду у строгой воспитательницы всегда нужно было спрашивать ее разрешение перед тем, как расписывать что-нибудь – «Марья Ивановна (OC Windows), можно я пририсую усы фломастером на вашей фотографии (в окне моей программы)?». А как иначе? За плохое поведение могут и из детского садика исключить («Ваша программа пыталась выполнить недопустимую операцию и будет закрыта» © WIndows), а там столько красивых игрушек!

Давайте договоримся, что под контекстом устройства (device context) мы будем понимать некий объект на котором нам не терпится что-либо нарисовать. В детском саду такими объектами (контекстами устройства) могли быть: лицо лучшего друга (зубной пастой во время «тихого часа»), стена в туалете, асфальтовая дорожка (цветными мелками – милое дело).

В мире Windows мы будем пользоваться 3-мя такими объектами (контекстами устройств) – монитором, принтером и памятью компьютера. API OpenGL может обрисовывать наши картины не только на мониторе, но и на принтере (есть ограничения) и просто рисовать картинку в памяти компьютера (Off-screen rendering. Кстати, только в этом случае мы можем подправлять изображения OpenGL самостоятельно непосредственно в памяти.) Контекст изображения OpenGL (не путать с контекстом устройства) к Windows не имеет никакого отношения, это “внутренняя кухня” OGL.

Теперь, отягощенные знанием о контекстах устройств Windows и контексте изображения OpenGL, еще раз изучите таблицу «CreateOGLWindow».

Что автор имел в виду под «протоколом», например «ABC_32бита»?. Структуру под симпатичным названием PIXELFORMATDESCRIPTOR.

;
; C
; © MSDN Library
typedef struct tagPIXELFORMATDESCRIPTOR { // pfd
WORD nSize;
WORD nVersion;
DWORD dwFlags;
BYTE iPixelType;
BYTE cColorBits;
BYTE cRedBits;
BYTE cRedShift;
BYTE cGreenBits;
BYTE cGreenShift;
BYTE cBlueBits;
BYTE cBlueShift;
BYTE cAlphaBits;
BYTE cAlphaShift;
BYTE cAccumBits;
BYTE cAccumRedBits;
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits;
BYTE cStencilBits;
BYTE cAuxBuffers;
BYTE iLayerType;
BYTE bReserved;
DWORD dwLayerMask;
DWORD dwVisibleMask;
DWORD dwDamageMask;
} PIXELFORMATDESCRIPTOR;

Я специально сделал фонт помельче, чтобы у вас не возникло желание с ним разбираться прямо сейчас. На данном этапе просто насладитесь количеством разных параметров, которые мы сможем выбирать для работы с OpenGL.

Для чего конкретно нужна эта структура? PIXELFORMATDESCRIPTOR определяет формат пикселей графического изображения, например, сколько цветов оно может отображать (16бит или 32бита - вы неоднократно делали этот выбор, играя в компьютерные игры). Механизм работы со структурой предельно простой. Мы «заказываем» нужный нам формат пикселей с которыми хотели бы работать в 3D. Затем отправляем «заказ» OC Windows. Система подбирает нам наиболее подходящий формат из списка тех, что поддерживаются «железом» на данном компьютере и возвращает его порядковый номер (индекс). Мы сообщаем Windows, что будем работать в предложенном формате, и настраиваем контекст устройства окна под него. Теперь мы уверены, что контекст устройства окна и контекст изображения OpenGL будут работать в одинаковых форматах пикселей, т.е. не будет ситуации, когда OpenGL пытается запихнуть 32бита туда, где могут поместится только 16бит. Логично?

MASM.OpenGL.Chapters – первая кровь

Вот как выглядит подпрограмма CreateOGLWindow.

Код (Text):
  1.  
  2. <font color="#006600">;
  3. ;  MASMv7
  4. ;
  5. ;-------------------------------------------------------
  6. </font>CreateOGLWindow <font color="#0000FF">proc</font>
  7. <font color="#006600">;-------------------------------------------------------
  8. ;  Резервируем место для индекса
  9. ;  формата пикселей, возращаемого Windows
  10. </font><b>LOCAL</b> PixelFormat :<b><font color="#804000">DWORD</font></b>
  11.  
  12. <font color="#006600">; Регистрируем класс нашего окна </font>
  13. <b>invoke</b>   </code><font color="#0000FF">RegisterClassEx</font><code>, <strong>ADDR</strong> wc
  14. <font color="#006600">; Oшибка? - "Ошибка при регистрации окна"
  15. ; и выходим
  16. </font>
  17. <font color="#006600">; Создаем окно win32 приложения
  18. ; Для окна с OpenGL необходимы WS_CLIPSIBLINGS и WS_CLIPCHILDREN !
  19. ; Выставляем размеры окна 400 x 400</font>
  20. <b>invoke</b> <font color="#0000FF">CreateWindowEx</font>,
  21.                 </code><font color="#990066"><code>NULL</code></font><code>,
  22.                 </code><b>ADDR</b><code> szWinClass,
  23.                 </code><b>ADDR</b><code> szWinName,
  24.                 <font color="#990066">WS_CLIPSIBLINGS</font> </code><font color="#0000FF">or</font><code> <font color="#990066">WS_CLIPCHILDREN</font> \</code>
  25. <font color="#0000FF">or</font><code> <font color="#990066">WS_OVERLAPPEDWINDOW</font>,
  26.                 0, 0,
  27.                 400,
  28.                 400,
  29.                 <font color="#990066">NULL</font>,
  30.                 <font color="#990066">NULL</font>,
  31.                 hInstance,
  32.                 <font color="#990066">NULL</font>
  33. <font color="#006600">; Oшибка? -  "Ошибка при создании окна"
  34. ; и выходим
  35. </font><font color="#0000FF">mov</font> hWnd, </code><b><font color="#0000FF">eax</font></b><code>
  36.  
  37. <font color="#006600">; Подпрграмма GetDC  (входит в Win32API) возвращает
  38. ; нам указатель на контекст устройства (КУ) нашего окна
  39. ; "Марьиванновна, можно мне порисовать на вашей фотографии?"
  40. ; Марьиванновна (с кислым лицом) - "Да на, рисуй. У меня еще есть".
  41. </font><b>invoke</b> <font color="#0000FF">GetDC</font>, hWnd
  42. <font color="#006600">; Ошибка - "Не могу получить указатель КУ окна"
  43. ; и выходим
  44. </font><font color="#0000FF">mov</font> hDC, <b><font color="#0000FF">eax</font></b>
  45.  
  46. <font color="#006600">; Подпрграмма ChoosePixelFormat входит в Win32API.
  47. ; В структуре pfd :PIXELFORMATDESCRIPTOR
  48. ; лежит наш "заказ" на пиксельный формат (ПФ),
  49. ; который мы хотели бы использовать в OpenGL.
  50. ; Просим Windows подобрать нам подходящий
  51. ; ПФ из поддерживаемых железом на выбранном
  52. ; контексте устройства - hDC
  53. </font><b>invoke</b> <font color="#0000FF">ChoosePixelFormat</font>, hDC, <b>ADDR</b> pfd
  54. <font color="#006600">; Ошибка - "Нет подходящего пиксельного формата."
  55. ; и выходим
  56. </font><font color="#0000FF">mov</font> PixelFormat, <b><font color="#0000FF">eax</font></b>
  57.  
  58. <font color="#006600">; Подпрграмма SetPixelFormat входит в Win32API.
  59. ; Настраиваем наш контекст устройства (hDC) на
  60. ; работу с подходящим пиксельным форматом, также
  61. ; сообщаем некоторую дополнительную информацию
  62. ; из нашей структуры pfd :PIXELFORMATDESCRIPTOR
  63. ; (windows добавит к выбранному ПФ "тонкие настройки")
  64. ; "Cоединение КУ с ОpenGL возможно по протоколу ABC_XXbits"
  65. </font><b>invoke</b> <font color="#0000FF">SetPixelFormat</font>, hDC,PixelFormat, <b>ADDR</b> pfd
  66. <font color="#006600">; Ошибка - "Установка ПФ не удалась."
  67. ; и выходим
  68. </font>
  69. <font color="#006600">; Подпрграмма wglCreateContext входит в API OpenGL (windows версия).
  70. ; Просим OpenGL создать у себя контекст изображения,
  71. ; который можно отобразить на контексте устройства нашего
  72. ; окна -- формат пикселей у КУ и КИ  одинаковый!
  73. ; "Подготовить OpenGL для коннекта по протоколу ABC_XXbits"
  74. </font><b>invoke</b> <font color="#0000FF">wglCreateContext</font>, hDC
  75. <font color="#006600">; Ошибка - "Ошибка в создании контекста изображения."
  76. ; и выходим
  77. </font><font color="#0000FF">mov</font> hRC, eax
  78.  
  79. <font color="#006600">; Подпрграмма wglMakeCurrent входит в API OpenGL (windows версия).
  80. ; Делаем созданный котекст изображения (hRC) активным,
  81. ; сообщаем на каком контексте устройства (hDC) мы хотим видеть
  82. ; результаты выполнения наших комманд к ОpenGL (сегодня мы рисуем
  83. : на мониторе).  OpenGL готов к выполнению наших комманд, находится
  84. : в режиме ожидания.
  85. ; Поздравляю, мы в OpenGLe - 3D открыт!
  86. </font><b>invoke</b> <font color="#0000FF">wglMakeCurrent</font>, hDC, hRC
  87. <font color="#006600">; Oшибка - "Ошибка активизации КИ."
  88. ; и выходим
  89. </font>
  90. <font color="#006600">; Подпрграмма ShowWindow входит в Win32API.
  91. ; Являем OpenGL окно миру
  92. </font><b>invoke</b> <font color="#0000FF">ShowWindow</font>, hWnd, <font color="#990066">SW_SHOW</font>
  93.  
  94. <font color="#006600">; Подпрграмма SetForegroundWindow входит в Win32API.
  95. ; Да не просто являем, а выпячиваем
  96. </font><b>invoke</b> <font color="#0000FF">SetForegroundWindow</font>, hWnd
  97.  
  98. <font color="#006600">; Подпрграмма SetFocus входит в Win32API.
  99. ; Да не просто являем и выпячиваем, а насильно
  100. ; приковываем к нему всеобщее внимание.
  101. </font><b>invoke</b> <font color="#0000FF">SetFocus</font>, hWnd
  102.  
  103. return <font color="#990066">TRUE</font>
  104. CreateGLWindow <font color="#0000FF">endp</font></code>
  105. </pre>
  106. <h2 align="center">Keep your country tidy! (англ.)</h2>
  107. <p>Как бы Вам понравилось, если на Вашей жилой площади совершенно чужие люди
  108.   брали ваши кровные контекстные устройства и создавали разные контексты изображения,
  109.   работали с ними в свое удовольствие, жутко при этом мусорили и, махнув ручкой
  110.   на прощанье, убирались восвояси, не прибрав за собой? Вот и ОС Windows будет
  111. ужасно расстроена, если мы не приберемся.</p>
  112. <p>Напомню, что, создавая наше первое OpenGL приложение, мы на время
  113.   взяли для рисования контекст устройства окна. Затем по нашей просьбе добрый
  114.   OpenGL выделил для программы частичку себя – контекст изображения. Настоящие
  115. джентльмены, поиграв в чужие игрушки, возвращают их хозяевам.</p>
  116. <pre><code>
  117. <font color="#006600">;
  118. ;  MASMv7
  119. ;
  120. ;-------------------------------------------------------
  121. </font>CloseOGLWindow <b><font color="#0000FF">proc</font></b>
  122. <font color="#006600">;-------------------------------------------------------</font>
  123.  
  124. <font color="#006600">; Есть ли в нашем распоряжении контекст изображения OpenGL?
  125. </font><b>.IF</b> hRC <font color="#0000FF">!=</font> 0
  126.  
  127.    <font color="#006600">; Подпрограмма wglMakeCurrent входит в API OpenGL (windows версия).
  128.    ; Сообщаем OpenGL, что больше не хотим активного соединения с его
  129.    ; сервером. ОpenGL перестает быть активным, все наши комманды ему
  130.    ; будут проигнорированы, хотя созданный для  программы контекст
  131.    ; изображения все еще зарезервирован.</font>
  132.    <b>invoke</b> <font color="#0000FF">wglMakeCurrent</font>, <font color="#990066">NULL</font>, <font color="#990066">NULL</font>
  133.  
  134. <font color="#006600">   ; Подпрограмма wglDeleteContext входит в API OpenGL (windows версия).
  135.    ; Мы сообщаем OpenGL, что выделенный для нас контекст изображения
  136.    ; нам больше не понадобится. Сервер приводит себя в порядок, а мы идем
  137.    ; своей дорогой. «И разошлись как в море корабли»
  138. </font>   <b>invoke</b> <font color="#0000FF">wglDeleteContext</font>, hRC                     
  139. <b>.ENDIF</b>
  140.  
  141.  
  142. <font color="#006600">; Подпрограмма ReleaseDC входит в Win32API.
  143. ; Возвращаем фотографию Марьивановне с глубокой благодарностью
  144. </font><b>invoke</b> <font color="#0000FF">ReleaseDC</font>, hWnd, hDC
  145.  
  146. <font color="#006600">; Окно нашей программе больше не нужно</font>
  147. <b>invoke</b> <font color="#0000FF">DestroyWindow</font>, hWnd
  148.  
  149. <font color="#006600">; Убираем за собой</font>
  150. <b>invoke</b> <font color="#0000FF">UnregisterClass</font>, <b>ADDR</b> szClassName, hInstance
  151.  
  152. <font color="#006600">; Рисуем поразительно реальный 3D образ Клаудии Шифер, в полный рост и
  153. ; совершенно голую.
  154. </font><b>ret</b>
  155. <font color="#006600">; Шутка.</font>
  156. KillOGLWindow <b><font color="#0000FF">endp</font></b>  
  157.  

PFD_SUPPORT_OPENGL equ 020h

Мы узнали почти все, чтобы закончить этот отрывок из МASM.OpenGL.Chapters. На сладкое осталась структура формата пикселей – pfd.

Код (Text):
  1.  
  2. ;<font color="#006600">
  3. ;  MASMv7
  4. ;
  5. </font>pfd <b><font color="#0000FF">PIXELFORMATDESCRIPTOR</font></b>  { \
  6.     <b>sizeof</b> <b><font color="#0000FF">PIXELFORMATDESCRIPTOR</font></b>,
  7.         1,
  8.         <code><font color="#990066">PFD_DRAW_TO_WINDOW</font></code> <font color="#0000FF">or</font>  <code><font color="#990066">PFD_SUPPORT_OPENGL</font></code>,
  9.         <code><font color="#990066">PFD_TYPE_RGBA</font></code>,
  10.         32,
  11.         0, 0, 0, 0, 0, 0,
  12.         0,
  13.         0,
  14.         0,
  15.         0, 0, 0, 0,
  16.         0,
  17.         0,
  18.         0,
  19.         0,
  20.         0,
  21.         0, 0, 0}
  22.  

Нули нас пока не интересуют.

Единица это pfd.nVersion – версия структуры (да и такое бывает). nVersion всегда равна единице.

32 – это pfd.cColorBits, определяет кол-во битов на один пиксель (bbp), т.е. количество разнообразных цветов в которые можно этот пиксель покрасить. Я взял 32 (а мог бы 24 или 16, например), что даст мне возможность отобразить 4,294,967,295 цветов.

PFD_TYPE_RGBA (pfd. iPixelType)– сообщает Windows, что цвета пикселей мы будем определять через Red Green Blue компоненты (подробнее в следующих главах)

И последним определяем элемент pdf. dwFlags:
PFD_DRAW_TO_WINDOW сообщает Windows о том, что мы будет рендерить (строить 3D сцены) в окно, а не в память, например.
PFD_SUPPORT_OPENGL – у меня нет информации.

В этой главе мы казалось бы ничего не сделали особенного. То, что получилось, Вы увидите, когда после внимательнейшего изучения исходника; сами скомпилируете его, если надо – отловите ошибки, а затем запустите. Напоминаю, СНАЧАЛА изучаете исходник, ПОТОМ компилируете, выдерживаете одни сутки, и в самую последнюю очередь запускаете. Так и только так.

Один мой хороший знакомый добился исключительных результатов за непостижимо короткий срок. Когда я попытался выяснить, в чем секрет и какими пособиями он пользовался, ZYtDHE грустно посмотрел в мою сторону и виновато промямлил «Рассыпался винчестер, а на старом не было компилятора». (!!!) Этот парень создавал программы, отлавливал свои ошибки в течении двух недель, так не разу и не запустив код на исполнение. «All errors are made by mistake» (c) ZYtDHE.

Вы замечали, что первое впечатление от знакомства с чем-то новым - самое сильное? Если именно сейчас в эти первые минуты после прочтения текста вы постараетесь вникнуть в философию OpenGL, с самых азов, с вызова его первой подпрограммы, с инициализации его первой структуры, то остальной более продвинутый материал покажется вам логичным продолжением, вы увидите в хаосе нулей и единиц, байтов и двойных слов, в контекстах изображения удивительную красоту и гармонию. И тогда вы сможете импровизировать, как хороший музыкант на любимом инструменте, а возможности API OpenGL будут ограниченны лишь Вашей фантазией.

Информация к размышлению

Так как исходник без комментариев и обработки возможных ошибок после вызова подпрограмм API (на их месте стоят мои комментарии «и выходим» ,смотри выше по тексту), предлагаю следующий конкурс для любознательных – доработайте исходник. Лучший будет опубликован в следующей главе).

Еще необходимо предупредить читателя о том, что откомпилированный исходник может вообще не запуститься. Если это Ваш случай – остается только порадоваться. Ведь потратив некоторое время на самостоятельный поиск и исправление ошибок вы лучше усвоите материал, и значит потратили время не зря. Вам может понадобится отладчик. К сожалению, у меня сейчас при себе нет его номера телефона, а на email он не отвечает. Поищите его в Интернете. Встретите Сафонову Асю, передавайте привет.

Автор работает в редакторе AsmEditor, который можно скачать отсюда (http://www.avtlab.ru/) Так же скачайте и установите базу подсветки синтаксиса, которую любезно предоставил vkim, разработчик VKDEBUG (входит в пакет MASMv7).

Основные возможности AsmEditor:

  • подключение различных компиляторов (Ассемблер, Си и другие);
  • настраиваемые схемы подсветки ключевых слов;
  • быстрый переход между процедурами, функциями, метками;
  • возможность подключения файлов помощи (например, win32.hlp) для вызова контекстной справки по выделенному в редакторе слову;
  • работа с исходными кодами в DOS-кодировке без потери символов псевдографики;
  • меню и дополнительные кнопки с функциями, назначаемыми пользователем;
  • настраиваемые "горячие клавиши"; быстрый переход по номеру строки; "закладки"; сохранение позиции курсора и т.д.
  • Не требует инсталляции, не вносит изменений в системные файлы и реестр.
  • По умолчанию настроен на пакет MASM32

Также скачайте fraps (www.fraps.com) и испробуйте его на каких-нибудь программах.

Для развлечения, поиграйте с графическими режимами в своем любимом FPS, попереключайтесь с 16 на 32 цветность. Постарайтесь объяснить увиденное.

Просто вопросы на засыпку:

1) Если мы будем работать в режиме off-screen rendering’га (т.е. рисовать изображение в памяти компьютера, а не выводить на экран) сможем ли получить любой «заказанный» формат пикселей для роботы на этом контексте устройства (ограничений то по «железу» на память нет)?

2) Что такое wiggle?

3) Почему в нашей программе необходимо указывать WS_CLIPSIBLINGS и WS_CLIPCHILDREN при вызове CreateWindowEx?

 


0 1.370
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532