Опубликован: 08.07.2007 | Доступ: свободный | Студентов: 1431 / 183 | Оценка: 4.43 / 4.02 | Длительность: 13:47:00
Специальности: Программист
Лекция 9:

Расчет освещенности. Файлы эффектов

Полноэкранный режим воспроизведения

До сих пор вывод всех сцен построения производился в окно (на форму). Библиотека Direct3D позволяет осуществить рендеринг в полноэкранном режиме ( Full Screen ). Для перехода в полноэкранный режим вывода примитивов необходимо лишь при заполнении структуры D3DPRESENT_PARAMETERS явно указать размеры заднего буфера ( BackBuffer ), установить флаг Windowed в значение FALSE. Также нужно указать режим переключения первичного и вторичного (заднего) буферов рендеринга и определить интервал смены буферов.

C++
D3DPRESENT_PARAMETERS params;
…
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;
…
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;