Уголок DirectX        Содержание

 

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

В этой части мы поговорим о различных видеокартах, 3D-акселераторах, уникальных идентификаторах, а также напишем первую программу, шаблон которой будем использовать в дальнейшей работе.

Честно говоря, я был поражен, когда узнал насколько просто Direct3D организовавает доступ к различным видеокатрам и акселераторам. Вот тут то я понял все значение слова device-independent. Мало того, я даже с удивлением обнаружил, что моя главная видеокарта S3 Virge DX/GX на 2мб еще и поддерживает Direct3D ускорение! (ну поддерживает как может, естесственно, но даже невооруженным глазом заметно:)

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

Все операции Direct3D и DirectDraw одинаковы для всех видеокарт. Даже если видеокарта не может на аппаратном уровне выполнить требуемую от нее операцию, DirectX сделает это за нее программно. Однако, вы можете проанализировать все возможности видеокарты, чтобы установить наиболее подходящие под нее установки своей программы.

Direct3D "подступается" к конкретному графическому устройству через так называемый Глобальный Уникальный Идентификатор (GUID). Смысл его в том, что каждое устройство в компьютере имеет "прилепленный к себе" набор букв и цифр, которые служат чем-то вроде нагрудного значка у заключенных - для того, чтобы их ни с кем не спутали. При инициализации каждый главный объект DirectX (DirectDraw, Direct3D, DirectSound...) по хорошему требует, чтобы ему ввели этот самый GUID устройства. По этому GUID'у объект, посоветовавшись с реестром, решает на какое системное устройство (видеокарту, звуковую карту...) ему направлять вывод.

Помните, в Учебнике по DirectDraw у нас была такая строка:

Set dd=dx.DirectDrawCreate("")

Вот обратите внимание на параметр, передаваемый в скобках. Мы передаем пустую строку. Однако в этом месте функция требует, чтобы ей передали GUID видеокарты, для которой создавать объект DirectDraw. Передавая пустую строку вместо GUID мы говорим, что надо использовать устройство по умолчанию, то-есть драйвер устройство, активного сейчас (вы ведь видите картинку на экране, значит какая-то видеокарта у вас все равно есть... :)

Так вот, если бы мы вместо этой пустой строки подсунули функции идентификатор другой видеокарты, то вся графическая информация передавалась бы на эту карту. Что я и сделал, чуть-чуть поиздевавшись над игрухой, которую мы делали в Учебнике по DirectDraw - VBPong, превратив ее в 3DFX-Pong

Но это все DirectDraw. А как же дело обстоит с Direct3D? А так же! Единственное различие состоит в том, что для Direct3D вам надо передавать два GUID. Дело в том, что передавая первый GUID вы определяете видеокарту, с которой собираетесь работать, а передавая второй GUID, вы определяете устройство рендеринга этой видеокарты. Устройство рендеринга - это аппаратное устройство прорисовки примитивов на экране. Его может просто не быть на аппаратном уровне, и тогда вы вынуждены эмулировать его программно. Такое устройство называется Direct3D RGB Software Emulation. Ежели чипсет видеокарты оснащен каким-нибудь устройством ускорения 3D-графики, тогда такое устройство называется Hardware Acceleration Trough Direct3D HAL. HAL - (Hardware Abstraction Layer) - это способ взаимодействия Direct3D и аппаратного обеспечения карты.

Пишем первую программу

Ну вот, теорию я вроде оттараторил. Сейчас мы займемся написанием программы, которая будет работать как необходимая составная часть всех наших дальнейших программ. В чем она заключается? Если вы когда-нибудь играли в Tomb Raider, то наверное видели, как перед первым запуском игры на экран вылазит такое окошко, где вы выбираете ваш акселератор, разрешение экрана и кучу других опций. Сейчас мы сделаем подобное эе окошк, котрон будет вылазить перед запусками основных программ с просьбой выбрать способ рендеринга. (Ну, Tomb Raider мы пока не пишем, поэтому наша программа будет определять только доступные видеокарты, а также устройства рендеринга этой видеокарты).

Кроме этого, мы начнем написание модуля mdlDirect3DRM, (аналогичного по значению модулю mdlDirectDraw7) в котором мы определим все объекты DirectX и важные функции, необходимые нам для дальнейшей работы.

Стартуем!

Создайте новый проект и добавьте к нему наши стандартные библиотеки - Microsoft dx7vb.dll и Patrice Scribe Win32.tlb

Добавили? Теперь создайте новый модуль, свойству Name которого присвойте mdlDirect3DRM. Стартовой форме присвойте Name - frmDriver, Caption - "Выберите драйвер". В свойствах проекта укажите стартовым объектом не frmDriver, а Sub Main. Позже вы поймете, зачем нам это понадобилось. Сохраните проект.

Теперь надо построить форму. Ориентируйтесь по следующей картинке. Enable у cmdOK должно быть False

Приступим к написанию кода.

Сначала - mdlDirect3DRM. Внесите туда такие объявления:

Option Explicit

Public dx As New DirectX7 'Объект DirectX
Public dd7 As DirectDraw7 'Объект DD для оконного режима
Public dd4 As DirectDraw4 'Объект DD для полноэкранного режима
Public d3d As Direct3D7 'Объект D3D:IM
Public d3dRm As Direct3DRM3 'Объект D3D:RM

Public driverGuid As String 'Используемая видеокарта
Public renderGuid As String 'Используемое устройство рендеринга видеокарты

Как я говорил в самой первой части, DirectDraw7 не поддерживает полноэкранного режима Direct3DRM и поэтому приходится использовать старые интерфейсы 4 из DirectX6. Объект D3D:IM будет использоваться при определении существующих устройств рендеринга. Объект D3D:RM вообще-то не нужен для этой программы, но я оставил его, чтобы вы знали, как он определяется :)

Private Sub Main()
frmDriver.Show vbModal
End Sub

Sub Main нам пока здесь ничего не дает, но ее необходимость будет ясна в дальнейших программах.

Переходим к форме. В модуль ее кода поместите такие строки:

Dim EnumVideo As DirectDrawEnum 'Список видеоустройств
Dim EnumDevice As Direct3DEnumDevices 'Список устройств рендеринга
Dim I As Integer

Здесь мы объявляем парочку объектов, которые потребуются нам для определения существующих видеоустройств.

Private Sub Form_Load()
'Получаем список видеокарт
Set EnumVideo = dx.GetDDEnum
For I = 1 To EnumVideo.GetCount
  cmbVideo.AddItem EnumVideo.GetDescription(I) 'Выписываем все видеокарты
Next I
cmbVideo.ListIndex = 0
End Sub

Первый оператор получает объект EnumVideo As DirectDrawEnum. В этом объекте содержтся информация обо всех найденных видеокартах. Нам надо ее оттуда вытащить, что мы и делаем затем в цикле. EnumVideo.GetCount дает количество найденных видеокарт, а EnumVideo.GetDescription(I) получает описание I-той видеокарты. В конце, мы устанавливаем элемент Combo отображать первую видеокарту. (Это сразу генерирует событие cmbVideo_Click)

Private Sub cmbVideo_Click()
txtDriver.Text = EnumVideo.GetName(cmbVideo.ListIndex + 1) 'Получаем имя драйвера
cmdOK.Enabled = False 'Чтобы не нажали OK когда не выбрано устройство рендеринга
lstDevice.Clear
If cmbVideo.ListIndex = 0 Then 'Если основная видеокарта,..
  '...то смотрим какие на ней навешаны устройства рендеринга
  Set dd7 = dx.DirectDrawCreate(EnumVideo.GetGuid(cmbVideo.ListIndex + 1))
  Set d3d = dd7.GetDirect3D 'Получим D3D:IM
  Set EnumDevice = d3d.GetDevicesEnum 'Получим устройства рендеринга
  For I = 1 To EnumDevice.GetCount
      lstDevice.AddItem EnumDevice.GetDescription(I) 'Выписываем все устройства
  Next I
  Set d3d = Nothing
  Set dd7 = Nothing
Else 'Если выбрали дополнительную карту, то подразумевается, что это акселератор
  lstDevice.AddItem "3D Acceleration through Direct3D HAL"
End If
End Sub

Вторая часть определения способа рендеринга - выбор устройства рендеринга для выбранной видекарты. Благодаря Microsoft, которая не догадалась оставить метод получения Direct3D из DirectDraw4, мы не можем определить устройства рендеринга для дополнительных карт. Так что остается уповать, что пользователь вставил на место второй видеокарты какой-нибудь акселератор, например, 3DFX.

Процесс определения устройства рендеринга для главной карты таков: создаем объект DirectDraw7 для главной видеокарты. Получаем из объекта DirectDraw объект Direct3D:IM. Из последнего получаем объект DeviceEnum As Direct3DEnumDevice, в котором содержится информация о найденных устройствах рендеринга. Мы получаем и записываем ее аналогично информации о видеокартах.

Ну вот. Информацию мы получили - теперь последние штрихи:

Private Sub lstDevice_Click()
'Выбрали устройство - теперь можно нажимать OK
cmdOK.Enabled = True
End Sub

Private Sub cmdCancel_Click()
If MsgBox("Правда выйти?", vbYesNo, "Выбор устройства") = vbYes Then
    End
End If
End Sub

Private Sub cmdOK_Click()
'Записываем выбранные настройки
If cmbVideo.ListIndex = 0 Then 'Если главная видеокарта, то...
    'Дравер по умолчанию, устройство рендеринга - которое выбрали
    mdlDirect3DRM.driverGuid = ""
    mdlDirect3DRM.renderGuid = EnumDevice.GetGuid(lstDevice.ListIndex + 1)
Else 'Если дополнительная, ...
    'Драйвер этой видеокарты, устройство рендеринга - по умолчанию
    'для этой карты (3D-акселерация)

    mdlDirect3DRM.driverGuid = EnumVideo.GetGuid(cmbVideo.ListIndex + 1)
    mdlDirect3DRM.renderGuid = "IID_IDirect3DHALDevice"
End If
Unload Me
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
'Убиваем все что можно и нельзя
Set EnumVideo = Nothing
Set EnumDevice = Nothing
Set d3d = Nothing
Set dd4 = Nothing
Set dd7 = Nothing
End Sub

При нажатии на cmdCancel мы завершаем программу (насовсем). При нажатии на cmdOK мы записываем в mdlDirect3DRM выбранные значения GUID'ов (они получаются через метод EnumVideo.GetGuid(Index) и EnumDevice.GetGuid(Index)), а затем выгружаем форму выбора драйвера. При этом подразуемвается, что Sub Main перехватывает управление и продолжает выполнение программы. В любом случает, перед выгразкой формы мы уничтожаем все объекты, которые создали.

Ну вот вроде и все. Обратите внимание на строку IID_IDirect3DHALDevice в задании GUID. Она обозначает использование акселерации для устройства по умолчанию.

Вы можете загрузить готовый проект (8k).

Фундамент возведен. Теперь можно со спокойной совестью переходить к построению графики!

Приятного программирования, Antiloop


>>> Реклама <<<