[ главная ]   [ рейтинг статей ]   [ справочник радиолюбителя ]   [ новости мира ИТ ]



Ответов: 0
25-02-12 07:01







   Web - программирование
PHP


ASP






XML



CSS

SSI





   Программирование под ОС











   Web - технологии








   Базы Данных









   Графика






Данные




Графика / Open GL /

Небольшое введение в win32 OpenGL

Я думаю, вы, как и я, смотрели на эти OpenGL'ные демки, как двигаются по экрану полигоны, меняются различные эффекты и так далее. Также, вполне вероятно, вы не очень сильны в математике и не хотите самостоятельно выводить все эти математические синусоидальные процедуры. OpenGL - это классная библиотека, которая позволит вам создать 3D-вселенную очень быстро, двигать ее и наложить серию спецэффектов, используя простую концепцию API.

В наши дни есть два основных вида программирования под OpenGL, в зависимости от операционной системы, которую вы используете. Обычный путь состоит в использовании glut-библиотеки, чтобы задавать анимацию, которая совместима с linux, win32, sgx-станциями и т.д... Другой путь - эт чистый win32. В последнем случае используются обратный вызов win32-клинта, чтобы переключиться на следующее изображение. Как бы то ни было, результат одинаков. Мы будем рассматривать программирование под win32. Поэтому для использования OpenGL вам сначала нужно инициализровать процедуру окна.

1 Процедура окна

Процедура окна обычно обрабатывает все системные события, которые направляются текущему (отображаемому или нет) окну. Этот принцип очень хорошо работает для GUI и уменьшает количество потребляемых машиной ресурсов.

1.1 Класс окна

Для инициализации процедуры окна вам требуется определить класс, небольшую структуры, в которой задается различная информация, например адрес процедуры окна. Это очень легко сделать:

 

        mov     edx,esp                 ; сохраняем стек

push offset classname
push 0 ; меню окна
push 0 ; цвет бэкграунда (черный)
push 0 ; наш курсор
push 0 ; наша иконка

push edx ; сохраняем стек
push 0
call GetModuleHandleA ; загружаем текущую программу
pop edx

push eax ; равен hinstance

push 0 ; дополнительно резервирующаяся память
push 0 ; дополнительный размер структуры
push offset Window_proc ; адрес процедуры окна
push 0 ; we don't care of style

mov eax,esp

push edx
push eax
call RegisterClassA ; регистрируем класс
pop esp ; восстанавливаем стек

Как только вы зарегистрировали класс, вам необходимо создать свою процедуру окна

1.2 Создание окна

Это просто: один вызов функции API

 

        push    0

call GetModuleHandleA
push eax

push 0
push 0
push 480
push 640
push 0
push 0
push 090000000h ; WS_VISIBLE
push offset windowname
push offset classname
push 0400000h ; WS_EX_CLIENTEDGE

call CreateWindowExA

Это правильно, но если вы вызовите его таким образом, приложение может повиснуть, почему? Потому что мы еще не создали процедуру окна.

1.3 Процедура окна

Процедура окна получает 4 аргумента. Первый - это хэндл окна. Второй - это сообщение. Третий - это нижний параметр, а четвертый - это верхний параметр.

Так как Windows работает в C-подобной среде, аргументы лежат на стеке. Поэтому к ним легко получить доступ. Также вам потребуется позаботиться о некоторых регистра, не модифицировать ebp, например, или ваша программа будет закрыта.

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

 

        lParam          equ     16
wParam equ 12
uMsg equ 8
hWnd equ 4

window_proc:

cmp dword ptr [esp+uMsg], 0Fh ; WM_PAINT
jne not_event1

... здесь какой-то код по обработке WM_PAINT

not_event1:

... здесь вы можете поместить обработку других событий

not_event99:

cmp dword ptr [esp+uMsg], WM_CLOSE
jne not_quiting

push dword ptr [esp+lParam]
push dword ptr [esp+4+wParam]
push dword ptr [esp+4+4+uMsg]
push dword ptr [esp+4+4+4+hWnd]
call DefWindowProc

ret 16

1.4 Обработка события

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

 

        mov     edx,esp
sub esp,44
mov ebx,esp

push ebx
push eax

loopit:

push ebx

push 0
push 0
push eax
push ebx
call GetMessageA

pop ebx

cmp eax,0
je goodbye

push ebx
push ebx
call TranslateMessage
call DispatchMessageA

pop eax
pop ebx

push ebx
push eax
jmp loopit

goodbye:

program_error:

add esp,44+4+4

push 0
call ExitProcess

Как только ваша процедура окна инициализирована, вам требуется синхронизировать ее с OpenGL.

2 OpenGL

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

2.1 При создании окна

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

 

        mov     ecx,40
sub esp,ecx
mov edi,esp
push edi

xor eax,eax
repz stosb

pop edi

mov word ptr [edi], 40 ; размер структуры
mov word ptr [edi+2], 1 ; заполняем версию
mov dword ptr [edi+4], 37 ; PFD_SUPPORT_OPENGL
; PFD_DRAW_TO_WINDOW
; PFD_DOUBLE_BUFFER
mov byte ptr [edi+9], 16 ; биты цвета
mov byte ptr [edi+17], 16 ; биты глубины

push edi
push dword ptr [currentDC] ; загружаем DC
call ChoosePixelFormat

Если результат равен 0, вызов API не удавлся, и пользователь не может отобразить разрешение. В противном случае вы можете напрямую установить пиксельный формат.

 

        push    edi
push eax
push dword ptr [currentDC] ; загружаем DC
call SetPixelFormat

тогда это равно пиксельному формату. Получить текущий DC очень просто:

 

        push    dword ptr [esp+hWnd]
call GetDC

и eax равен текущему DC. Нам также требуется создать контекст OpenGL из этого DC.

 

        push    eax
call wglCreateContext

Если eax == 0, то вызов не удался и лучшее, что мы можем сделать - это послать WM_CLOSE, чтобы благополучно закрыть приложение.

Далее мы синхронизируем оба контекста:

 

        push    eax             ; контекст OpenGL
push ebx ; текущий DC
call wglMakeCurrent

Сделано, OpenGL был проинициализирован, теперь вы можете наложить ряд эффектов, но прежде, чем сделать это, вы должны из разрешить. Делается это так:

 

        push    0B57h           ; CL_COLOR_MATERIAL
call glEnable ; damn easy isn't ?

Вы также можете попробовать другие значения: GL_DEPTH, G_LIGHTING.

2.2 Как только был изменен размер окна

Когда Windows закончила с инициализацией, она шлет сообщение WM_SIZE, которое озанчает, что настало время пофиксить все, связанное с графикой. Разрешение экрана посылается в lParam. Поэтому сначала устанавливаем порт просмотра.

 

        mov     ecx,dword ptr [esp+lParam]
movzx edx,cx
shr ecx,16

push ecx
push edx ; длина
push 0
push 0 ; начало
call glViewport ; определяем порт просмотра

После этого нам нужно определить модель матрицы, я не буду давать урок математики о матрицах и трансформациях, но как обычно это очень легко:

 

        push    1701h           ; GL_PROJECTION
call glMatrixMode

После этого мы вызываем функцию glLoadIndentity:

 

        call    glLoadIdentity

Затем мы вызываем библиотеку GL-эффектов, чтобы добавить перспективу порту просмотра. Эта функция принимает только числа двойной точности. Компилер может инициализировать такое число так:

 

double1         dq      1.0f

А вот макрос, облегчающий загонку таких чисел в стек:

 

pushdl  macro   double1

fld qword ptr [&double1&]
sub esp,8
fstp qword ptr [esp]

endm

Теперь передадим необходимые параметры порту просмотра.

 

        pushdl  farclip
pushdl nearclip
pushdl XYration
pushdl FovAngle

call gluPerpective

Перспектива - это необходимый аспект нашего 3D-мира. Перспектива бывает разных видов, например как при обзоре через камеру наблюдения или обзор сцены в формате 16/9.

И, опционально, вы можете установить модель теней для сложной 3D-сцены, установите ее в GL_F:AT, это может ускорить рендеринг изображения.

 

                push    01D01h
call glShadeModel

Вот и все с этим.

3 Пришло время показать ваши умения демокодера

Windows говорит процедуре окна, что настало время обновить текущее изображение с помощью сообщения WM_PAINT.

Первое, что нужно сделать - это обновить текущее изображение с помощью сообщения WM_PAINT.

 

        push    04100h                  ; GL_COLOR_BUFFER_BIT или
call glClear ; GL_DEPTH_BUFFER_BIT

push GL_MODEL_VIEW
call glMatrixMode

call glLoadIdentity

Теперь мы можем установить порт просмотра в виде камеры. У этой камеры есть 9 операндов.

 

        3 первых - это начало камеры
3 следующих - это назанчение камеры
3 последних - это координаты верхнего вектора камеры, ее вращение

Эти операнды также двойной точности, поэтому используйте pushdl, чтобы использовать эту функцию.

 

        pushf...
pushf...
call gluLookAt

А теперь надо отрисовать окружение. Можно сделать много вещей: установить свет, тени, прозрачность, искажения и так далее.

Давайте сделаем такую простую вещь:

 

        push    GL_POINTS
call glBegin

push 0.5
push 0.5
push 0.5
call glVertex3f

call glEnd

glColor3d и glVertex3i существуют во многих форматах. Последняя буква задает тип переменной, который вы хотите использовать. glVertex3d означается, что вы используете аргумент двойной точности.

Когда окружение построено, вы можете закончить это так:

 

        push    DC
call SwapBuffers

И буфер окажется на экране.

4 Небольшое приложение

Часто люди удивляются, почему их продукция отображается на экране очень странно. Причина проста: OpenGL не интересуется другими элементами, расположенными на экране, поэтому н может перерисовать их... Вы можете установить тест глубины во время создания окна:

 

        push    0B71h           ; DEPTH_TEST
call glEnable ;

Некоторые люди хотят полноэкранное разрешение, это можно сделать в два шага, меняя разрешение дисплея:

 

        mov     ecx,148
mov esp,ecx
mov edi,esp
xor eax,eax

repz stosb

mov dword ptr [esp+36],148 ; dmSize
mov dword ptr [esp+104],16 ; dmBitsPerPixel
mov dword ptr [esp+108],640 ; dmWidth
mov dword ptr [esp+112], 480 ; dmHeight
mov dword ptr [esp+40], 1C0000h
; DM_BITSPERPEL DM_PELSWIDTH DM_PELSHEIGHT

mov edx,esp

push 4 ; CDS_FULLSCREEN
push edx ; dmScreenSettings
call ChangeDisplay

add esp,148

Не правда ли, это очень легко?




Комментарии

 Ваш комментарий к данному материалу будет интересен нам и нашим читателям!



Последние статьи: Графика / Open GL /

Введение opengl трехмерная 3d графика
17-05-2010   

Современный мир уже немыслим без трехмерной 3D графики - в том числе интерактивной. В свое время было предпринято множество попыток создать универсальный язык описания трехмерных сцен. Самой удачной оказалась попытка компании Silicon Graphics - ее язык OpenGL получил всемирное признание... подробнее

Кол. просмотров: общее - 2913 сегодня - 1

Небольшое введение в win32 OpenGL
17-05-2010   

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

Кол. просмотров: общее - 3187 сегодня - 2

Подробные примеры OpenGL
17-05-2010   

Привет всем (уважаемым читателям/телезрителям/а также их родителям и пр ;) Сразу хочу предупредить, что это моя первая статья, поэтому просьба не пинать меня ногами, никакого заме-е-ечательного Набоковского слога и живописных эпитетов вы тут не увидите... подробнее

Кол. просмотров: общее - 3466 сегодня - 0

OpenGL: Open Graphics Library
02-05-2010   

Графическая библиотека OpenGL, как утвержденный индустриальный стандарт, разработана и утверждена в 1992 году девятью ведущими IT-фирмами: Digital Equipment Corp., Evans & Sutherland, Hewlett-Packard Co., IBM Corp., Intel Corp., Intergraph Corp... подробнее

Кол. просмотров: общее - 2924 сегодня - 0

Где взять OpenGL и другое ПО
18-01-2009   

Здесь я перечислю необходимый инструментарий для работы с книгой, и где его можно раздобыть. По минимуму вам нужен сишный компилятор и библиотека OpenGL... подробнее

Кол. просмотров: общее - 3131 сегодня - 2



  WWW.COMPROG.RU - 2009-2012 | Designed and Powered by Zaipov Renat | Projects