Шрифт:
Интервал:
Закладка:
p_p.BackBufferFormat = dm.Format;
p_p.Windowed=TRUE;
p_p.SwapEffect=D3DSWAPEFFECT_DISCARD;
Последний шаг, который осуществляет наша функция Init() — создание устройства. Для этого воспользуемся методом IDirect3D8::CreateDevice().
Укажем следующие параметры:
a. D3DADAPTER_DEFAULT — используется стандартный видеоадаптер
b. D3DDEVTYPE_REF — визуализация будет происходить исключительно программными средствами Direct3D
c. hWnd — собственно, идентификатор окна
d. D3DCREATE_SOFTWARE_VERTEXPROCESSING — обработка точек будет происходить исключительно программными средствами
e. &p_p — указатель на структуру, описывающую параметры создающегося устройства
f. &g_pd3dDevice — адрес указателя на интерфейс IDirect3DDevice8, который будет создан
Вот, что должно получиться:
g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &p_p,&g_pd3dDevice);
Функция Render()Эта функция как раз рендерит сцену. Принцип ее действия:
a. Очищается бэк-буфер, и в него рендерится сцена (итого, в бэк-буфере окажется темно-синий экран, т.к. сцена не содержит объектов)
b. Происходит передача данных во франт-буфер
c. Содержимое франт-буфера "выбрасывается" на экран
Очистить сцену можно вызвав метод IDirect3DDevice8::Clear(). Его первые два параметра мы обнуляем, т.к. хотим очистить экран (на самом деле не экран, а рабочую область окна, но так проще писать :) ) целиком. Значение третьего параметра (D3DCLEAR_TARGET) говорит о том, что очистка должна происходить цветом, заданным четвертым параметром (в нашем случае D3DCOLOR_XRGB(30, 60, 120)). Последние два параметра в нашем случае игнорируются. Поэтому, пишем:
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(30, 60, 120), 1.0f, 0);
Подготовка завершена, переходим к рендерингу в бэк-буфер:
g_pd3dDevice->BeginScene();
g_pd3dDevice->EndScene();
Методы IDirect3DDevice8::BeginScene() и IDirect3DDevice8::EndScene() показывают, в каком месте начинается, а в каком заканчивается процесс рендеринга. Все методы рендеринга, вызванные вне зоны ограниченной данными операторами, игнорируются.
Последний шаг - передача видеоданных на экран через франт-буфер. Это осуществляется с помощью метода IDirect3DDevice8::Present().
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
Первые два параметра задают прямоугольные области источника (бэк-буфера) и места назначения (франт-буфера), поскольку копируется целиком вся область, то эти параметры выставлены в ноль. Третий параметр - указатель на принимающее окно, в клиентскую часть которого происходит выполнение метода Present(). Поскольку мы используем структуру D3DPRESENT_PARAMETERS, то третий параметр выставляем в NULL. Четвертый параметр — никогда не используется, его всегда нужно выставлять в NULL :-)
Функция Sweep()Самая короткая по программному коду функция. Осуществляет "подчистку" после нашей работы.
g_pd3dDevice->Release();
g_pD3D->Release();
UnregisterClass("InitClass", wclass.hInstance);
Все просто. Сначала освобождаем устройства рендеринга, затем объект D3D. После этого остается лишь удалить класс окна и все!
Функция MessageProc()Стандартная функция всех Windows приложений (название функции может быть любым), которая обрабатывает поступившие окну сообщения.
switch (msg) {
case WM_DESTROY:
Sweep();
PostQuitMessage(0);
break;
case WM_PAINT:
Render();
ValidateRect(hWnd, NULL);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
break;
}
Если окну поступает сообщение WM_DESTROY, то происходит "подчистка" функцией Sweep(), а обращение к функции PostQuitMessage(0) говорит системе, что наше приложение завершило работу. Если же окну поступило сообщение WM_PAINT (например, когда пользователь передвинул окно мышкой), то все окно должно быть немедленно перерисовано, что и делает наша функция Render(). Остальные сообщения обрабатываются стандартным образом. Как мне приятно описывать эту функцию :-) И не потому, что она последняя в данной статье. Просто в ней все красиво, т.к. ранее мы подготовили базу для ее работы.
Ну, вот и все. Надеюсь, что ты почерпал из этой статьи для себя что-то новое и интересное… Не пугайся, если программа показалась тебе слишком большой и сложной. Это не значит, что для рисования треугольника придется добавлять к ней такой же большой кусок кода. Просто дописать пару десятков строчек кода и делов-то :-) Ты сделал самый сложный шаг — первый. Теперь будет легче. Позже будем учиться отрисовывать трехмерные объекты, научимся использовать матрицы трансформации, устанавливать источники света, накладывать текстуры… Но об этом уже в следующих статьях…
Удачной тебе компиляции!
Примечание: Если будешь писать программу сам, помни, что для ее компиляции нужно подключить библиотечные файлы [*.lib]. Lib'ы подключайются так:
a. Project->Settings…
b. Открой вкладку "Link"
c. В строке "Object/library modules" добавь в начало d3d8.lib
d. Должно получиться примерно следующее: "d3d8.lib kernel32.lib user32.lib gdi32.lib…"
Автор: voxatu.DirectX 8: Создание и текстурирование простого трехмерного объекта
Автор: voxatuТы уже умеешь инициализировать Direct3D, а значит можно на этой базе создавать трехмерные объекты. Чтобы было совсем интересно, натянем на наш трехмерный объект текстуру и заставим его вращаться!!! Кроме того, воспользуемся фильтрацией текстур и MipMapping'ом, чтобы получить более реалистичный результат почти без потери быстродействия. Попутно, научимся работать со вспомогательной библиотекой Direct3DX. Пример можешь скачать ЗДЕСЬ.
Итак, приступим. За "трехмерный объект" возьмем правильную четырехугольную пирамиду, а за текстуру — подредактированную фотографию каменной стены (первоначальный вариант текстуры взят с сайта http://www.3dcafe.com/, на котором собрано огромное количество различных бесплатных для скачивания изображений).
Функции WinMain(), MessageProc() и InitD3D() будут очень похожи на аналогичные функции программы из предыдущей статьи, поэтому я буду объяснять, в основном, только модифицированные их части. Структура программы немного изменилась. Теперь более грамотно обрабатываются ошибки, которые могут возникнуть при выполнении той или иной части программы.
Рассмотренные функции исходника:
Функция WinMain()
Функция Initialization()
Функция InitD3D()
Функция InitTexture()
Функция InitScene
Функция DoMatrices()
Функция RenderScene()
Функция Deinitialization()
Функция MessageProc()
Функция WinMain()Главная функция нашего приложения. Практически аналогична одноименной функции из предыдущей статьи. Единственное, что сильно изменилось — цикл обработки сообщений. Также, вынесены в отдельные функции инициализация и деинициализация приложения.
if (Initialization(hWnd)) {
ShowWindow(hWnd, nCmdShow);
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 RenderScene();
}
}
Deinitialization();
Если инициализация проходит успешно, окно приложения отображается на экране и начинается цикл обработки сообщений, иначе деинициализация и выход из программы. Функция PeekMessage() проверяет очередь сообщений для текущей нити процесса и, если таковые имеются, помещает одно из них в структуру MSG. Флаг PM_REMOVE говорит о том, что сообщение из очереди удаляется, т.е. на нас возлагается ответственность его корректной обработки в любом случае. Это мы и делаем в следующих двух строчках. Если же очередь сообщений пуста, вызывается функция RenderScene(), которая, согласно ее названию, рендерит очередной кадр сцены. Как только поступает сообщение WM_QUIT, происходит деинициализация приложения (функция Deinitialization()).
Функция Initialization()Осуществляет грамотную (т.е. с учетом ошибок) инициализацию D3D, текстур и сцены. Замечу, что все функции нашего приложения, в которых может возникнуть ошибка, имеют тип BOOL. Рассмотрим программный код:
CurrentFilter = D3DTEXF_NONE;
if (!InitD3D(hWnd)) return FALSE;
if (!InitTexture()) {
MessageBox(NULL, "Не найден файл текстуры!", "Ошибка", MB_ICONERROR);
return FALSE;
}
if (!InitScene()) return FALSE;
return TRUE;
Что такое CurrentFilter? Забегая вперед, скажу, что наша программа будет использовать фильтрацию текстур, причем можно будет переключаться между различными фильтрами. Неплохо для первой программы с использованием D3D? ;-) Итак, первая строка кода говорит, что по умолчанию фильтром является D3DTEXF_NONE, т.е. фильтрация не используется. Затем вызываются три функции дополнительной инициализации, причем, если хотя бы в одной из них возникнет ошибка, функция Initialization() вернет значение FALSE, что в свою очередь остановит выполнение программы (вспомни функцию WinMain()) и приведет к деинициализации. Если функция InitTexture() возвращает значение FALSE, значит не удалось найти файл текстуры и перед аварийным завершением программы необходимо вывести предупредительное сообщение: MessageBox(NULL, "Не найден файл текстуры!", "Ошибка", MB_ICONERROR);
- Как функции, не являющиеся методами, улучшают инкапсуляцию - Скотт Мейерс - Программирование
- Программист-фанатик - Чед Фаулер - Программирование
- Как я делаю мультфильмы - Андрей Шумин - Прочая научная литература / Прочее / Программирование
- Эффективное использование STL - Скотт Мейерс - Программирование
- Python для детей. Анимация с черепашьей графикой - Виктор Рабинович - Прочая детская литература / Программирование
- Программирование на языке Пролог для искусственного интеллекта - Иван Братко - Программирование
- ДИАЛОГ С КОМПЬЮТЕРОМ - Александр Журавлев - Программирование
- Новое в зарплатном учете в 2023 году: лайфхаки бухгалтера в 1С - Компания СервисКлауд - Программирование / Финансы
- ВСТУП ДО ІНЖЕНЕРІЇ ПРОГРАМНОГО ЗАБЕЗПЕЧЕННЯ - М. Сидоров - Программирование
- Программирование - Ирина Козлова - Программирование