Расчет освещенности. Файлы эффектов
Полноэкранный режим воспроизведения
До сих пор вывод всех сцен построения производился в окно (на форму). Библиотека Direct3D позволяет осуществить рендеринг в полноэкранном режиме ( Full Screen ). Для перехода в полноэкранный режим вывода примитивов необходимо лишь при заполнении структуры D3DPRESENT_PARAMETERS явно указать размеры заднего буфера ( BackBuffer ), установить флаг Windowed в значение FALSE. Также нужно указать режим переключения первичного и вторичного (заднего) буферов рендеринга и определить интервал смены буферов.
C++ |
D3DPRESENT_PARAMETERS params; … ZeroMemory( ¶ms, sizeof(params) ); params.Windowed = FALSE; params.SwapEffect = D3DSWAPEFFECT_FLIP; params.BackBufferWidth = 1280; params.BackBufferHeight = 1024; params.BackBufferFormat = display.Format; params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; … |
Pascal |
var params: TD3DPresentParameters; … ZeroMemory( @params, SizeOf(params) ); params.Windowed := False; params.SwapEffect := D3DSWAPEFFECT_FLIP; params.BackBufferWidth := 1280; params.BackBufferHeight := 1024; params.BackBufferFormat := display.Format; params.PresentationInterval := D3DPRESENT_INTERVAL_IMMEDIATE; … |
Единственно, что необходимо еще проделать – это организовать возможность выхода (закрытия) программы. Для этого можно, например, обработать событие системы WM_KEYDOWN. Полноэкранный режим довольно часто используют в играх, так как именно при таком режиме достигается максимальная производительность видеокарты. Можно воспользоваться функцией Win32 API GetSystemMetrics() для того, чтобы узнать текущее разрешение экрана.
C++ |
D3DPRESENT_PARAMETERS params; … params.BackBufferWidth = GetSystemMetrics(SM_CXSCREEN); params.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN); |
Pascal |
var params: TD3DPresentParameters; … params.BackBufferWidth := GetSystemMetrics(SM_CXSCREEN); params.BackBufferHeight := GetSystemMetrics(SM_CYSCREEN); |
Обработка ошибок
При использовании графической библиотеки Direct3D программисту следует уделять особе внимание обработке ошибок. Для этих целей предусмотрены два специальных макроса, которые проверяют код на наличие или отсутствие ошибок:
FAILED() SUCCEEDED()
Принцип работы этих макросов очень прост и представлен ниже.
if ( FAILED()) // ошибка при выполнении команды ... else // команда завершилась успешно
Для второго макроса принцип действия будет противоположным.
if (SUCCEEDED ()) // команда завершилась успешно ... else // ошибка при выполнении команды
Ниже приведены некоторые примеры обработки ошибок.
C++ |
LPDIRECT3D9 direct3d = NULL; ... if( FAILED( direct3d -> CreateDevice( … ) ) ) { // обработка ошибки } |
Pascal |
var direct3d: IDirect3D9; ... if Failed ( direct3d.CreateDevice( … ) ) then begin // обработка ошибки end; |
Можно осуществлять анализ ошибок через дополнительную переменную.
C++ |
HRESULT hr; hr = direct3d -> CreateDevice( … ); if( FAILED(hr) ) { } |
Pascal |
var hr: HRESULT; … hr := direct3d.CreateDevice( … ); if Failed(hr) then begin end |
И еще один способ обработки ошибок заключается в сравнении результата вызова функции с константой D3D_OK.
C++ |
if ( direct3d -> CreateDevice( … ) != D3D_OK ) { } |
Pascal |
if direct3d.CreateDevice( … ) <> D3D_OK then begin end; |
Следует также остановиться на обработке ошибок при компиляции шейдеров. Как мы помним, в одном из параметров функции D3DXCompileShaderFromFile(…) возвращается указатель на буфер ошибок. Ниже приводится программный код, позволяющий вывести на экран сообщение об ошибке, полученное от компилятора HLSL.
C++ |
if ( D3DXCompileShaderFromFile( "shader.psh", NULL, NULL, "main", "ps_2_0", 0, &Code, &BufferErrors, NULL) != D3D_OK ) { MessageBox(NULL, (const char*)BufferErrors->GetBufferPointer(), "Ошибка в шейдере!!!", MB_OK | MB_ICONEXCLAMATION); } |
Pascal |
if D3DXCompileShaderFromFile('shader.psh', nil, nil, 'Main', 'ps_2_0', 0, @Code, @BufferErrors, nil) D3D_OK then begin MessageBox(0, BufferErrors.GetBufferPointer, 'Ошибка в шейдере!!!', MB_OK or MB_ICONEXCLAMATION); end; |
Такой информативный способ позволяет легко "увидеть" в какой именно строке шейдера допущена ошибка.
Подсчет количества кадров в секунду
Как правило, показателем производительности в приложениях, связанных с трехмерной графикой, является количество кадров, выводимых приложением в единицу времени (в секунду). Поэтому очень часто возникает необходимость вычислить и отобразить эту информацию в окне приложения. Ниже приведен пример, показывающий как подсчитывать количество кадров в секунду.
C++ |
count = 0; last_tick = GetTickCount(); while(msg.message != WM_QUIT) { if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(Msg); DispatchMessage(Msg); } else { this_tick = GetTickCount(); if(this_tick-last_tick>=1000) { last_tick=this_tick; fps=count; count=0; // вывод значения fps } else count++ Render(); } } |
Pascal |
count:=0; last_tick:=GetTickCount(); while Msg.message <> WM_QUIT do begin if PeekMessage(msg, 0, 0, 0, PM_REMOVE) then begin TranslateMessage(Msg); DispatchMessage(Msg); end else begin this_tick:=GetTickCount(); if(this_tick-last_tick>=500) then begin last_tick:=this_tick; fps:=count; count:=0; // вывод значения fps end else count:=count+1; Render; end; end; |