Небольшое введение в win32 OpenGLЯ думаю, вы, как и я, смотрели на эти OpenGL'ные демки, как двигаются по экрану полигоны, меняются различные эффекты и так далее. Также, вполне вероятно, вы не очень сильны в математике и не хотите самостоятельно выводить все эти математические синусоидальные процедуры. OpenGL - это классная библиотека, которая позволит вам создать 3D-вселенную очень быстро, двигать ее и наложить серию спецэффектов, используя простую концепцию API. В наши дни есть два основных вида программирования под OpenGL, в зависимости от операционной системы, которую вы используете. Обычный путь состоит в использовании glut-библиотеки, чтобы задавать анимацию, которая совместима с linux, win32, sgx-станциями и т.д... Другой путь - эт чистый win32. В последнем случае используются обратный вызов win32-клинта, чтобы переключиться на следующее изображение. Как бы то ни было, результат одинаков. Мы будем рассматривать программирование под win32. Поэтому для использования OpenGL вам сначала нужно инициализровать процедуру окна. 1 Процедура окна Процедура окна обычно обрабатывает все системные события, которые направляются текущему (отображаемому или нет) окну. Этот принцип очень хорошо работает для GUI и уменьшает количество потребляемых машиной ресурсов. 1.1 Класс окна Для инициализации процедуры окна вам требуется определить класс, небольшую структуры, в которой задается различная информация, например адрес процедуры окна. Это очень легко сделать:
mov edx,esp ; сохраняем стек Как только вы зарегистрировали класс, вам необходимо создать свою процедуру окна 1.2 Создание окна Это просто: один вызов функции API
push 0 Это правильно, но если вы вызовите его таким образом, приложение может повиснуть, почему? Потому что мы еще не создали процедуру окна. 1.3 Процедура окна Процедура окна получает 4 аргумента. Первый - это хэндл окна. Второй - это сообщение. Третий - это нижний параметр, а четвертый - это верхний параметр. Так как Windows работает в C-подобной среде, аргументы лежат на стеке. Поэтому к ним легко получить доступ. Также вам потребуется позаботиться о некоторых регистра, не модифицировать ebp, например, или ваша программа будет закрыта. Ваша процедура окна должна перехватывать некоторые сообщения, которые заданы как win32-константы. Давайте взглянем, на что похожа процедура окна.
lParam equ 16 1.4 Обработка события В силу определенных причин некоторые сообщения принимаются, а некоторые посылаются. Поэтому вам нужно, чтобы текущить тред принимал сообщения, что стоит довольно мало ресурсов. Поэтому не паникуйте. Этот код достаточно общий, он может меняться от программиста к программиста, но делает он примерно одно и то же.
mov edx,esp Как только ваша процедура окна инициализирована, вам требуется синхронизировать ее с OpenGL. 2 OpenGL Сейчас у нас есть зарегистрированный класс, созданное окно и маленькая оконная процедура. Но теперь нам нужна помощь OpenGL, чтобы инициализировать систему, графику и множество других вещей. Нам необходимо будет делать их в два момента времени: при создании окна и при обновлении экрана. 2.1 При создании окна Во-первых, вам нужно инициализировать пиксельный формат, который будет использоваться как двойной графический буфер. Для этого вам необходимо использовать PIXELFORMATDESCRIPTOR, это длинная и скучная структура, в которой нужно заполнить тольконесколько полей
mov ecx,40 Если результат равен 0, вызов API не удавлся, и пользователь не может отобразить разрешение. В противном случае вы можете напрямую установить пиксельный формат.
push edi тогда это равно пиксельному формату. Получить текущий DC очень просто:
push dword ptr [esp+hWnd] и eax равен текущему DC. Нам также требуется создать контекст OpenGL из этого DC.
push eax Если eax == 0, то вызов не удался и лучшее, что мы можем сделать - это послать WM_CLOSE, чтобы благополучно закрыть приложение. Далее мы синхронизируем оба контекста:
push eax ; контекст OpenGL Сделано, OpenGL был проинициализирован, теперь вы можете наложить ряд эффектов, но прежде, чем сделать это, вы должны из разрешить. Делается это так:
push 0B57h ; CL_COLOR_MATERIAL Вы также можете попробовать другие значения: GL_DEPTH, G_LIGHTING. 2.2 Как только был изменен размер окна Когда Windows закончила с инициализацией, она шлет сообщение WM_SIZE, которое озанчает, что настало время пофиксить все, связанное с графикой. Разрешение экрана посылается в lParam. Поэтому сначала устанавливаем порт просмотра.
mov ecx,dword ptr [esp+lParam] После этого нам нужно определить модель матрицы, я не буду давать урок математики о матрицах и трансформациях, но как обычно это очень легко:
push 1701h ; GL_PROJECTION После этого мы вызываем функцию glLoadIndentity:
call glLoadIdentity Затем мы вызываем библиотеку GL-эффектов, чтобы добавить перспективу порту просмотра. Эта функция принимает только числа двойной точности. Компилер может инициализировать такое число так:
double1 dq 1.0f А вот макрос, облегчающий загонку таких чисел в стек:
pushdl macro double1 Теперь передадим необходимые параметры порту просмотра.
pushdl farclip Перспектива - это необходимый аспект нашего 3D-мира. Перспектива бывает разных видов, например как при обзоре через камеру наблюдения или обзор сцены в формате 16/9. И, опционально, вы можете установить модель теней для сложной 3D-сцены, установите ее в GL_F:AT, это может ускорить рендеринг изображения.
push 01D01h Вот и все с этим. 3 Пришло время показать ваши умения демокодера Windows говорит процедуре окна, что настало время обновить текущее изображение с помощью сообщения WM_PAINT. Первое, что нужно сделать - это обновить текущее изображение с помощью сообщения WM_PAINT.
push 04100h ; GL_COLOR_BUFFER_BIT или Теперь мы можем установить порт просмотра в виде камеры. У этой камеры есть 9 операндов.
3 первых - это начало камеры Эти операнды также двойной точности, поэтому используйте pushdl, чтобы использовать эту функцию.
pushf... А теперь надо отрисовать окружение. Можно сделать много вещей: установить свет, тени, прозрачность, искажения и так далее. Давайте сделаем такую простую вещь:
push GL_POINTS glColor3d и glVertex3i существуют во многих форматах. Последняя буква задает тип переменной, который вы хотите использовать. glVertex3d означается, что вы используете аргумент двойной точности. Когда окружение построено, вы можете закончить это так:
push DC И буфер окажется на экране. 4 Небольшое приложение Часто люди удивляются, почему их продукция отображается на экране очень странно. Причина проста: OpenGL не интересуется другими элементами, расположенными на экране, поэтому н может перерисовать их... Вы можете установить тест глубины во время создания окна:
push 0B71h ; DEPTH_TEST Некоторые люди хотят полноэкранное разрешение, это можно сделать в два шага, меняя разрешение дисплея:
mov ecx,148 Не правда ли, это очень легко? |