Треугольник задаётся последовательностью вершин, как линейный (одномерный) массив. Для одного треугольника нам понадобится три вершины:
MyVert v[3];
//Зададим расположение для вершин:
v[0].x =-0.5f; v[0].y =-0.5f; v[0].z = 0.5f;
v[1].x =-0.5f; v[1].y = 0.5f; v[1].z = 0.5f;
v[2].x = 0.5f; v[2].y = 0.5f; v[2].z = 0.5f;
//и цвет:
v[0].Color = D3DCOLOR_XRGB(255,0,0); // красный
v[1].Color = D3DCOLOR_XRGB(0,255,0); //
зеленый
v[2].Color = D3DCOLOR_XRGB(0,0,255); // синий
Выводом объектов занимаются семейство методов DrawPrimitive интрефейса IDirect3DDevice8. Примитивом здесь называется минимальный объект, который может быть выведен таким методом, например, треугольник здесь тоже является примитивом. В нашем случае мы воспользуемся методом DrawPrimitiveUP:
Первым параметром задаётся тип примитивов, второй отвечает за количество примитивов, третий является указателем на область в памяти, где расположена информация о вершинах, в нашем случае мы указываем наш массив, последний параметр — размер шага в байтах, с которым идут вершины одна за другой, у нас элементы массива лежат "плотно", поэтому шагом является размер, занимаемый данными одной вершины, то есть размер структуры MyVert.
Поскольку всё отображение ведется в невидимую часть экрана, мы должны показать все это на экране. Этим занимается метод Present. Для нашего примера параметры этой функции нас не интересуют, выставляем их в 0:
pDevice->Present(0, 0, 0, 0);
Этот метод вызывается, когда вы отобразили все объекты, участвующие в текущем кадре, в текущей сцене, то есть после метода EndScene.
В итоге мы построили функцию Render, которая и будет выводить наш треугольник на экран:
void Render {
// Инициализацию массива v можно вынести за пределы
наше приложение больше ничего не будет выводить на экран, то некоторую часть кода из функции Render можно вынести за её пределы, а именно, инициализацию массива v, выключение освещения и установку типа просчитываемых вершин.
Ниже приведён код, который больше относится к windows-программированию. Создаётся главное окно приложения и ведётся обработка сообщений:
// функция обрабатывающая сообщения главного окна приложения
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT) {
WNDCLASSEX wc = {
sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(0), 0, 0, 0, 0, "FirstDX_cl", 0
};
RegisterClassEx(&wc);
// Создание главного окна приложения
HWND hWnd = CreateWindow("FirstDX_cl", "FirstDX",
WS_OVERLAPPEDWINDOW, 100, 100, 160, 160,
GetDesktopWindow, NULL, wc.hInstance, NULL);
if (Init(hWnd)) {
ShowWindow (hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT) {
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else Render;
}
}
ReleaseAll;
UnregisterClass("FirstDX_cl", wc.hInstance);
return 0;
}
Функция Render вызывается всегда, когда не приходят какие-либо сообщения, то есть перерисовка кадра происходит практически постоянно. Функции Init и ReleaseAll описаны в предыдущей части урока.
Теперь есть всё, чтобы вы смогли скомпилировать и запустить наш пример. Не забудьте добавить библиотеку d3d8.lib в ваш проект, чтобы линковщик смог найти реализации функций Direct3D.