DirectX 8.1 в MASM32: Урок 1 — Архив WASM.RU

Все статьи

DirectX 8.1 в MASM32: Урок 1 — Архив WASM.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

2002-2013 (c) wasm.ru