Укрощение Direct3D
Структура движка
По мере роста нашего движка, постепенно меняется и его структура. Посмотрите:
Появился новый класс - tD3D, отвечающий за инициализацию Direct3D. Он же будет базовым для будущих классов для работы с графикой. Немного сместился tLogFile, став общим для всех классов.
Direct3D
Как я говорил выше, класс tD3D отвечает за инициализацию Direct3D. Производится она вызовом функции InitD3D с указанием размеров и положении окна, в котором будет выводиться графика, и если игра запускается в полноэкранном режиме, то дополнительно указывается глубина цвета. Рассмотрим подробнее работу этой функции:
/*--------------------------------------------------------------
tD3D::InitD3D()
Инициализация D3D
--------------------------------------------------------------*/
void tD3D::InitD3D(int x,int y,int width,int height,int color)
{
HRESULT hResult;
D3DADAPTER_IDENTIFIER8 adapterIdentifier;
D3DDISPLAYMODE displayMode;
try {
// Создание окна
tWindow::InitWindow(x,y,width,height);
}
catch(tError &error) {
error.AddErrorHistory(" <-tD3D::InitD3D");
throw;
}
Сперва создаем окно.
tLogFile::LogMessage("Create
D3D ... ");
// Создаем Direct3D
m_d3d = Direct3DCreate8(D3D_SDK_VERSION);
if(!m_d3d) throw tError(__FILE__,__LINE__,"tD3D::InitD3D",
"Can't
create D3D!");
tLogFile::LogMessage("Ok.\n");
// Получаем информацию о видео-адаптере
hResult = m_d3d->GetAdapterIdentifier(D3DADAPTER_DEFAULT,0,&adapterIdentifier);
if(hResult!=D3D_OK)
throw tError(__FILE__,__LINE__,"tD3D::InitD3D",
"Fail
to get adapter information! (%s)",DXGetErrorString8(hResult));
// Выводим информацию о видео-адаптере в log-файл
tLogFile::LogMessage(" Description: %s\n",adapterIdentifier.Description);
tLogFile::LogMessage(" Driver: %s\n",adapterIdentifier.Driver);
tLogFile::LogMessage(" Driver Version: %d.%d.%d.%d\n",
HIWORD(adapterIdentifier.DriverVersion.HighPart),
LOWORD(adapterIdentifier.DriverVersion.HighPart),
HIWORD(adapterIdentifier.DriverVersion.LowPart),
LOWORD(adapterIdentifier.DriverVersion.LowPart));
// Выводим информацию о видео-режимах в log-файл
tLogFile::LogMessage(" Available video modes:\n");
for(int i=0;i<tD3D::GetD3DDisplayModeCount();i++)
{
tD3D::GetD3DDisplayMode(i,&displayMode);
tLogFile::LogMessage(" %dx%dx%d %d\n",
displayMode.Width,
displayMode.Height,
tD3D::ConvertD3DFormat(displayMode.Format),
displayMode.RefreshRate);
}
Потом создаем Direct3D - первый объект, который должен быть получен в любой программе, которая работает с графикой. Через него мы дальше получаем информацию о видеокарте и доступных видеорежимах, выводя все это в log-файл (вот зачем я сделал класс tLogFile общим для всех).
tLogFile::LogMessage("Create D3D Device ... ");
// Создаем устройство
Direct3D
if(!color) {
// Получаем текущий режим дисплея
m_d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&displayMode);
// Параметры создания устройства D3D
m_d3dPP.BackBufferWidth = width;
m_d3dPP.BackBufferHeight = height;
m_d3dPP.BackBufferFormat = displayMode.Format;
m_d3dPP.BackBufferCount = 1;
//
m_d3dPP.MultiSampleType = D3DMULTISAMPLE_NONE;
//
m_d3dPP.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_d3dPP.hDeviceWindow = m_hWindow;
m_d3dPP.Windowed = TRUE;
//
m_d3dPP.EnableAutoDepthStencil = TRUE;
m_d3dPP.AutoDepthStencilFormat = D3DFMT_D16;
}
else {
// Параметры
создания устройства D3D
m_d3dPP.BackBufferWidth
= width;
m_d3dPP.BackBufferHeight
= height;
if(color==32)
m_d3dPP.BackBufferFormat = D3DFMT_X8R8G8B8;
else
m_d3dPP.BackBufferFormat = D3DFMT_R5G6B5;
m_d3dPP.BackBufferCount
= 1;
//
m_d3dPP.MultiSampleType
= D3DMULTISAMPLE_NONE;
//
m_d3dPP.SwapEffect
= D3DSWAPEFFECT_DISCARD;
m_d3dPP.hDeviceWindow
= m_hWindow;
m_d3dPP.Windowed
= FALSE;
//
m_d3dPP.EnableAutoDepthStencil
= TRUE;
m_d3dPP.AutoDepthStencilFormat
= D3DFMT_D16;
}
Перед тем, как создать устройство Direct3D, сперва мы должны заполнить структуру D3DPRESENT_PARAMETERS, которая определить некоторые параметры этого устройства. Как вы понимаете, для оконного и полноэкранного режимов есть отличия в заполнении. Во-первых, в оконном режиме в m_d3dPP.BackBufferFormat заносится формат пикселя соответствующий формату текущего режима дисплея, а в полноэкранном - значения D3DFMT_X8R8G8B8 или D3DFMT_R5G6B5, в зависимости от требуемой глубины цвета. И во-вторых, m_d3dPP.Windowed определяет какой режим мы хотим использовать.
// Создаем устройство Direct3D с программной
обработкой вершин
hResult = m_d3d->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,m_hWindow,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&m_d3dPP,&m_d3dDevice);
if(hResult!=D3D_OK)
throw tError(__FILE__,__LINE__,"tD3D::InitD3D",
"Can't
create D3D Device! / x - %d, y - %d, width - %d, height - %d, color - %d / (%s)",
x,y,width,height,color,DXGetErrorString8(hResult)); tLogFile::LogMessage("Ok.\n");
И последним этапом, создаем устройство Direct3D. Пока мы будем использовать программную обработку вершин, потому что GeForce 3 у меня еще нет :).
Пример
Пример я взял из 7-го урока с сайта directxdesign.narod.ru. Немного переправил функции, и теперь выводится знакомый нам чайник.
Кстати, загляните после работы программы в log-файл, найдете немного информации о вашей видеокарте :).