allasm.ru

    Меню

 

Самое главное, что нам потребуется для работы с DirectX это заголовочные файлы и библиотеки. Можно
взять их из Microsoft DirectX SDK 8.1. Все, что нам оттуда нужно, это только папка LIB. У меня не было
возможности взять SDK с компакта, а качать более 100 метров ради пары десятков файлов полный
идиотизм. Хоть мелгомягкие и запрещают выкладывать какие либо части их SDK, находятся еще
добрые люди на свете и набрав в поисковике искомое мы всегда получим парочку адресов. Все ленивые
могут посмотреть по адресу упомянутому мною в предыдущем уроке. До последнего момента там было то
что нам нужно.

Так как SDK рассчитан на работу с языком C++, то заголовочные файлы необходимо адаптировать.
Не переживайте. Для данных уроков я уже адаптировал все необходимые файлы и надеюсь, работа
будет продолжена. Адаптированные INC файлы включены в исходник уроков, забирайте и пользуйтесь.
Формат библиотек является родным и для С++ и для MASM, поэтому библиотеки подходят без проблем.
Ну вот и все приготовления и прежде, чем мы перейдем собственно к нашему уроку, хотелось бы еще
упомянуть, что все относящееся к DirectX я буду сопровождать подробной справкой. Справка является
моим корявым переводом справочника из SDK, поэтому не ругайте меня за возможные ошибки.

Все что у нас сейчас имеется это приложение, при запуске выводящее на экран окошко размером
320х240, и нам надо заставить работать в этом окне Direct3D. Как это сделать? Нет ничего проще!

Первое что мы добавим это подключение необходимых файлов:

    include 		d3d8.inc		
    include 		d3d8caps.inc
    include 		d3d8types.inc
    includelib 		d3d8.lib

Теперь обьявим необходимые переменные и структуры:

    Clearcolor		DWORD	 0 ; Переменная для очистки экрана цветом
    Zvalue		REAL4 1.0 ; Значение для Z буфера ( см.ниже )

    pd3d		DWORD  ? ; Указатель на Direct3D			
    pd3dDevice	DWORD	 ? ; Указатель на Direct3DDevice		
    d3ddm		D3DDISPLAYMODE  <>	 ; Структура для параметров экрана
    d3dpp 		D3DPRESENT_PARAMETERS <> ; Структура для параметров нашего Direct3Ddevice
	

Справка

D3DDISPLAYMODE STRUC
Width1 UINT ? ; Ширина экрана в пикселях
Height UINT ? ; Высота экрана в пикселях
RefreshRate UINT ? ; Частота обновления. 0 означает частота по умолчанию
Format DWORD ? ; Формат использ. поверхности ( см. D3d8Types.inc )
D3DDISPLAYMODE ENDS
D3DPRESENT_PARAMETERS STRUC
BackBufferWidth UINT ? ; Ширина BackBuffer. 0 если работаем в окне.
BackBufferHeight UINT ? ; Высота BackBuffer. 0 если работаем в окне.
BackBufferFormat DWORD ? ; Формат использ. поверхности ( см. D3d8Types.inc )
BackBufferCount UINT ? ; 0,1,2 или 3 - число буферов. 0 трактуется как 1.
; Если указанное число буферов не может быть
; создано то помещается число буферов которые
; были реально созданы
MultiSampleType DWORD ? ; 2-16 уровни мультисэмплинга картинки.
; 1 не используется, а 0 равносилен отсутствию
; мультисэмплинга ( D3DMULTISAMPLE_NONE )
; Мультисэмплинг возможен только если установлен
; D3DSWAPEFFECT_DISCARD. В противном случае
; здесь должен быть 0.
SwapEffect DWORD ? ; Эффект обмена поверхностей.
; Если мы работаем в окне и используем
; D3DSWAPEFFECT_FLIP, тогда будет создан один
; дополнительный BackBuffer. Пока один буфер
; показывается на экране можно рисовать в другой.
; Потом они меняются местами и т.д
; D3DSWAPEFFECT_COPY и
; D3DSWAPEFFECT_COPY_VSYNC требуют чтобы
; BackBufferCount был установлен в 1. ( содержимое
; буфера копируется на экран без ожидания
; обратного хода луча и с ожиданием соответственно)
; D3DSWAPEFFECT_DISCARD сначала буфер
; заполняется а потом показывается на экран
hDeviceWindow HWND ? ; ID нашего окошка
Windowed BOOL ? ; Режим работы. 0 - полноэкранный, 1 - в окошке
EnableAutoDepthStencil BOOL ? ; Если значение установить в 1, то Direct3D будет управлять
; для приложения буфером глубины. Будет создан Z-Stencil
; буфер. При этом в AutoDepthStencilFormat должен быть
; установлен правильный формат поверхности.
; Если 0 - ничего не будет создано
AutoDepthStencilFormat DWORD ? ; Формат использ. поверхности ( см. D3d8Types.inc )
; Игнорир. если EnableAutoDepthStencil не равен 1
Flags DWORD ? ; 0 или D3DPRESENTFLAG_LOCKABLE_BACKBUFFER=1
; Нужен если мы будем блокировать BackBuffer
FullScreen_RefreshRateInHz UINT ? ; Частота обновления экрана в Hz.
; Должно быть 0 если мы работаем в оконном режиме
; Если указать D3DPRESENT_RATE_DEFAULT, то
; берется текущее значение, если в окошке, и по
; умолчанию ( обычно 60 Hz ), если в полноэкранном
FullScreen_PresentationInterval UINT ? ; Интервал показа на экране backbufferа
; Должно быть 0 если мы работаем в оконном режиме
; D3DPRESENT_INTERVAL_IMMEDIATE - рисуем немедленно
; не ждя обратного хода луча
; 1 - рисуем ждя обратный ход луча ( FPS - не будет
; превышать Hz экрана )
; 2 - FPS равен половине Hz
; 3 - FPS равен трети Hz
; 4 - FPS равен четверти Hz
D3DPRESENT_PARAMETERS ENDS

Далее создадим три процедуры Init_Direct3D, Destroy_Direct3D и Render_Scene

итак Init_Direct3D

Создаем обьект Direct3D8:

    invoke  	Direct3DCreate8, D3D_SDK_VERSION 						
    mov	pd3d, eax

Справка

 Direct3DCreate8 передается в качестве параметра версия SDK.

 Метод возвращает указатель на обьект если все прошло успешно. 
 Если ошибка, то в EAX возвращается код ошибки, какой именно я не знаю :( ( возможно 0 )  

Затем мы получаем информацию о текущих параметрах экрана:

    d3d8 	GetAdapterDisplayMode, pd3d, D3DADAPTER_DEFAULT, ADDR d3ddm	

Справка

 1. Номер видеоадаптера. D3DADAPTER_DEFAULT - всегда главный адаптер
( под номером 0 ) можно вставить цифру нужного адаптера если в системе их несколько 2. Указатель на структуру параметров экрана ( см. выше ) Возвращает в случае успеха D3D_OK. Если нет то D3DERR_INVALIDCALL - недействительный вызов.

Заполняем только те поля структуры которые нам необходимы:

    mov	d3dpp.Windowed, TRUE				; Работаем в окошке			
    mov	d3dpp.SwapEffect, D3DSWAPEFFECT_FLIP	; Будем менять буфера 
    mov	eax, d3ddm.Format				; Берем формат экрана
    mov	d3dpp.BackBufferFormat, eax 			; Сохраняем в структуре

А сейчас делаем самое главное ! Создаем устройство Direct3DDevice8.

Создавать Direct3DDevice в сообщении WM_Create нельзя ! ( проверено опытным путем :) ) То же самое можно найти в документации по Direct3D8.

CreateDevice мы должны передать hwnd полностью созданного окна на экране которое находится в фокусе.

    d3d8  CreateDevice, pd3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd , \ 
              D3DCREATE_HARDWARE_VERTEXPROCESSING, ADDR d3dpp, ADDR pd3dDevice

Справка

 1. Номер видеоадаптера. D3DADAPTER_DEFAULT - всегда главный адаптер
( под номером 0 ) можно вставить цифру нужного адаптера если в системе их несколько. 2. Тип устройства рендеринга. D3DDEVTYPE_HAL - аппаратный рендеринг.
D3DDEVTYPE_REF - програмный рендеринг. 3. Hwnd - ID нашего окошка. 4. Комбинация флагов. D3DCREATE_FPU_PRESERVE - нам нужна двойная точность вычисления с плавающей запятой. D3DCREATE_HARDWARE_VERTEXPROCESSING - аппаратная обработка вершин D3DCREATE_SOFTWARE_VERTEXPROCESSING - программная обработка вершин D3DCREATE_MIXED_VERTEXPROCESSING - аппаратная + программная обработка вершин D3DCREATE_MULTITHREADED - многопоточность приложения ( direct3D создает глобальный критический раздел это может привести к падению FPS ) D3DCREATE_PUREDEVICE - не поддерживать Get вызовы. Также не обеспечивать эмуляцию каких- либо сервисов связанных с Vertex processing. Имеется в виду что если устройство не поддерживает vertex processing тогда приложение может использовать только post трансформацию вершин. D3DCREATE_DISABLE_DRIVER_MANAGEMENT - D3D будет управлять ресурсами вместо драйвера. Флаги SOFTWARE_VERTEXPROCESSING, HARDWARE_VERTEXPROCESSING и MIXED_VERTEXPROCESSING недопустимы для совместного использования. 5. Указатель на структуру D3DPRESENT_PARAMETERS. ( см. выше ) 6. Адрес переменной куда будет помещен указатель на D3DDevice Возвращает в случае успеха D3D_OK. Если нет то D3DERR_INVALIDCALL - недействительный вызов, D3DERR_NOTAVAILABLE - устройством требуемое не поддерживается или D3DERR_OUTOFVIDEOMEMORY - не хватает видео памяти для данной операции.

Теперь наше устройство создано и настало время написать функцию Render_Scene !

итак Render_Scene

Для простого примера применим очистку backbuffer`а цветом и показа его на экране:

    d3dev8	Clear, pd3dDevice, 0 , NULL , D3DCLEAR_TARGET, clearcolor, Zvalue, 0

Справка

 1. Число структур прямоугольников в массиве. ( см. Параметр 2 )
 2. Указатель на массив структур прямоугольников. Каждый прямоугольник 
     указывает какое место в поверхности  рендеринга очищать. 
	 Если 0 то очищается вся поверхность. При этом в первом параметре тоже должен быть 0.

 3. Комбинация флагов.  
        D3DCLEAR_STENCIL - очищать стенсель буфер стенсель значением. ( см.параметр 6 )
 	D3DCLEAR_TARGET - очищать поверхность рендеринга цветовым значением. ( см.параметр 4 )
 	D3DCLEAR_ZBUFFER - очищать Z буфер z значением. ( см.параметр 5 )

 4. Цветовое значение. 32bit-ное значение в формате ARGB

 5. Z значение. Может быть в диапазоне от 0.0 до 1.0 
 ( для z основного или w основного буфера глубины ) 0.0 - ближняя гараница. 1.0 - дальняя граница.

 6. Stencil значение. Может быть в диапазоне от 0 до 2^n-1 где n это глубина бит стенсель буфера.

 Возвращает в случае успеха D3D_OK. Если нет то D3DERR_INVALIDCALL,   
 D3DERR_NOTAVAILABLE или D3DERR_OUTOFVIDEOMEMORY. ( расшифровку см. выше )

А теперь все покажем этой функцией

    d3dev8     Present, pd3dDevice, NULL, NULL, NULL, NULL

Справка

 1. Указатель на структуру источник типа RECT. Должно быть 0 если 
     поверхности не были созданы с флагами 
     D3DSWAPEFFECT_COPY и D3DSWAPEFFECT_COPY_VSYNC.

 2. Указатель на структуру назначение типа RECT. Должно быть 0 если 
     поверхности не были созданы с флагами 
     D3DSWAPEFFECT_COPY и D3DSWAPEFFECT_COPY_VSYNC.

 3. ID окошка куда показывать результат. Если мы указали его ранее в 
     структуре D3DPRESENT_PARAMETERS, то здесь 0
 4. Не используется и должен быть 0.

Откомпилировав и запустив это приложение, вы увидите, что оно работает. Но это еще не все.
После того как наше приложение будет закрыто, нам необходимо удалить все созданные нами интерфейсы
и занятые ими ресурсы. Для этого создадим функцию Destroy_Direct3D.

итак Destroy_Direct3D

    d3dev8	Release, pd3dDevice	; Метод специально для Direct3DDevice8  
    d3d8	Release, pd3d		; Метод специально для Direct3D8   

На этом позволю себе откланяться. До следующих встреч !

Исходник прилагается.

PS

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

Авторство принадлежит Пономареву Михаилу ака keYMax. Все вопросы и ругательства слать по адресу mybox@aib.ru