Суровая правда жизни о Direct3D
Спецвыпуск Хакер, номер #004, стр. 004-098-8
mat.dcvAmbient.g = (D3DVALUE)1.0;
mat.dcvAmbient.b = (D3DVALUE)0.0;
mat.dcvAmbient.a = (D3DVALUE)1.0;
mat.dcvSpecular.r = (D3DVALUE)0.0;
mat.dcvSpecular.g = (D3DVALUE)1.0;
mat.dcvSpecular.b = (D3DVALUE)0.0;
mat.dcvSpecular.a = (D3DVALUE)1.0;
hr = lpD3DD->SetMaterial(&mat);
if(FAILED(hr)) return hr;
//Создаем нашу лампу
//Она будет белая
//Тип - точечная (светит во все стороны без разбора)
d3dLight.dltType = D3DLIGHT_POINT;
d3dLight.dcvDiffuse.r = 1.0f;
d3dLight.dcvDiffuse.g = 1.0f;
d3dLight.dcvDiffuse.b = 1.0f;
d3dLight.dcvAmbient.r = 1.0f;
d3dLight.dcvAmbient.g = 1.0f;
d3dLight.dcvAmbient.b = 1.0f;
d3dLight.dcvSpecular.r = 1.0f;
d3dLight.dcvSpecular.g = 1.0f;
d3dLight.dcvSpecular.b = 1.0f;
d3dLight.dvPosition.x = 0.0f;
d3dLight.dvPosition.y = 0.0f;
d3dLight.dvPosition.z = -4.0f;
d3dLight.dvAttenuation0 = 1.0f;
//Да пусть светит далеко-далеко
d3dLight.dvRange = D3DLIGHT_RANGE_MAX;
//Регистрируем нашу лампу
hr = lpD3DD->SetLight(0, &d3dLight);
if(FAILED(hr)) return hr;
//Разрешаем ей светить
hr = lpD3DD->LightEnable(0, TRUE);
if(FAILED(hr)) return hr;
Конец листинга 7.
Н-да-а... Сделаем последний рывок и закончим инициализацию. Теперь надо проинициализировать матрицы, они служат для трансформаций. Что это за матрицы и какие преобразования они делают - смотри в имаги.
Сначала надо создать мировую матрицу (Гхм...) без всяких трансформаций. Описывает матрицу структура D3DMATRIX. Чтобы применить ее, воспользуйся методом SetTransform. Первый параметр говорит о том, что мы будем трансформировать (D3DTRANSFORMSTATE_WORLD - трансформирует мир, D3DTRANSFORMSTATE_VIEW - трансформирует вид, но там определенные параметры - довольно сложная вещь, D3DTRANSFORMSTATE_PROJECTION - трансформирует вид проекции - как это будет выглядеть на экране). Второй параметр - адрес матрицы. Все, что тебе потребуется сделать, написано в листинге.
Листинг №8 - Main.cpp, завершение инициализации
D3DMATRIX mat;
mat._11 = mat._22 = mat._33 = mat._44 = 1.0f;
mat._12 = mat._13 = mat._14 = mat._41 = 0.0f;
mat._21 = mat._23 = mat._24 = mat._42 = 0.0f;
mat._31 = mat._32 = mat._34 = mat._43 = 0.0f;
lpD3DD->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
//Создаем матрицу вида
D3DMATRIX matView = mat;
matView._43 = 10.0f; //Будем отодвинуты по Z назад на 10
lpD3DD->SetTransform(D3DTRANSFORMSTATE_VIEW, &matView);
//Создаем матрицу проекции
D3DMATRIX matProj = mat;
matProj._11 = 2.0f;
matProj._22 = 2.0f;
matProj._34 = 1.0f;
matProj._43 = -1.0f;
matProj._44 = 0.0f;
lpD3DD->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &matProj);
return S_OK; //Радостно завершаем инициализацию
}
Конец листинга 8.
Теперь будем рендерить. Для начала заставим мир крутиться. Просто измени мировую матрицу, как это написано в листинге. Перед рендерингом надо очистить экран методом Clear. Первый параметр - количество прямоугольников в массиве второго параметра (0). Второй - Указатель на пресловутый массив (NULL). Третий - тип, что будем затирать (D3DCLEAR_TARGET - затрем экран). Четвертый - цвет в хексе (0x00000000 - черный). Пятый и шестой нам не нужны, они относятся к z и stencil буферам (0, 0). Далее идет уже непосредственно рендеринг. Его обязательно надо располагать между вызовами методов BeginScene и EndScene, не имеющих параметров. Вот и выполняй сейчас BeginScene. Собственно рисование осуществляется методом DrawPrimitive. Первым его параметром является тип примитива (в данном случае D3DPT_TRIANGLELIST - список полигонов; еще есть D3DPT_TRIANGLESTRIP - последовательность оных; D3DPT_TRIANGLEFAN - что-то типа веера, см. SDK; D3DPT_LINELIST - список линий; D3DPT_LINESTRIP - последовательность; D3DPT_POINTLIST - список точек). Следующий, второй, параметр - тип данных, в которых указываются вершины примитивов (D3DFVF_VERTEX - поступают в типе D3DVERTEX). Третий параметр - данные наших вершин в том типе, в котором мы указали выше (в нашем случае это переменная vtx). Далее, четвертый параметр - количество вершин в той переменной, которую мы указали (6). Последний параметр - ждать ли рендеринг или плевать на все (в нашем случае я бы даже посоветовал всегда так делать: D3DDP_WAIT). Пора и закончить рендеринг. EndScene. Ну и если ты помнишь про двойную буферизацию, выведем все это на экран. Разрешенный метод Flip интерфейса IDirectDrawSurface7 нам в этом деле поможет. Первый параметр - указатель на серфайсу, куда будем переносить изображение (ставь NULL для того, чтобы перенести его на следующую серфайсу в цепи (экран)). Второй - флаги (DDFLIP_WAIT). Вот и весь рендеринг.