Бесплатная реклама

Автор: Борис Клевич «wildboar»

Опубликовано: 13.12.2006

Изменено: 12.01.2007

Постоянная ссылка

Комментарии [5]

Текст на основе ID3DXFont и Счетчик кадров





Страницы: 1 2

Делаем текст и счетчик FPS

Я решил не описывать примитивные текстовые функции GDI TextOut() и DrawText(), а сразу приступить к использованию более продвинутого текста на основе ID3DXFont. Такой текст работает медленнее, чем CD3DFont, так как ID3DXFont использует GDI для отображения текста, зато он поддерживает сложные шрифты и форматирование. Для этого нам потребуется:

Объявить специальные для этого заголовочные и библиотечные файлы

#include ‹d3dx9core.h›			//требуется для работы с текстом ID3DXFont
#include ‹tchar.h›			//возникла необходимость из-за: _T("текст")
#include ‹stdio.h›			// для sprintf
#pragma comment (lib,"d3dx9.lib")	// библиотека утилит direct3d9

Создать глобальные переменные для шрифтов

// Указатель на интерфейс ID3DXFONT для текста
LPD3DXFONT m_pd3dxFont		= NULL; 
// Указатель на интерфейс ID3DXFONT для маленького текста
LPD3DXFONT m_pd3dxFont_Small 	= NULL;
// lfFaceName из структуры LOGFONT (wingdi.h)
TCHAR 	m_strFont[LF_FACESIZE];
// Размер шрифта
DWORD         m_dwFontSize 	= 41;
// Размер шрифта для маленького текста
DWORD         m_dwFontSize_Small = 22;
// Переменная структуры HFONT, будет содержать шрифт
HFONT hFont;
// Для хранения FPS
static char buffer[256];

Написать функцию для инициализации текста

//----------------------------
// Текст на основе D3DXFont
// Функция CreateD3DXFont()
//----------------------------
HRESULT CreateD3DXFont( LPD3DXFONT* ppd3dxFont, TCHAR* pstrFont, DWORD dwSize )
{
    HRESULT hr;
    LPD3DXFONT pd3dxFontNew = NULL;
    HDC hDC;
    INT nHeight;

    hDC = GetDC( NULL );
    nHeight = -MulDiv( dwSize, GetDeviceCaps(hDC, LOGPIXELSY), 72 );
    ReleaseDC( NULL, hDC );

    hr = D3DXCreateFont( m_pd3dDevice,		// D3D device
                   nHeight,			// Height
                   0,				// Width
                   FW_BOLD,			// Weight
                   0,				// MipLevels
                   FALSE,			// Italic
                   DEFAULT_CHARSET,		// CharSet
                   OUT_DEFAULT_PRECIS,		// OutputPrecision
                   DEFAULT_QUALITY,		// Quality
                   DEFAULT_PITCH | FF_DONTCARE, // PitchAndFamily
                   pstrFont,			// шрифт, например TEXT("Arial")
                   &pd3dxFontNew);		// ppFont

    if( SUCCEEDED( hr ) )
        *ppd3dxFont = pd3dxFontNew;

    return hr;
}

Добавляем создание текста D3DXFont в InitDirect3D

//----------------------------
// Инициализация Direct3D
// Функция InitDirect3D() 
//----------------------------
HRESULT InitDirect3D(HWND hwnd)
{
	if (NULL == (m_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
	return E_FAIL;
	
	D3DDISPLAYMODE Display;
	if (FAILED(m_pD3D -> GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&Display)))
	return E_FAIL;
	
	D3DPRESENT_PARAMETERS Direct3DParam;
	ZeroMemory(&Direct3DParam, sizeof(Direct3DParam));
	Direct3DParam.Windowed = TRUE;
	Direct3DParam.SwapEffect = D3DSWAPEFFECT_DISCARD;
	Direct3DParam.BackBufferFormat = Display.Format;
	Direct3DParam.EnableAutoDepthStencil = TRUE;
	Direct3DParam.AutoDepthStencilFormat = D3DFMT_D16;
	Direct3DParam.BackBufferWidth  = GetSystemMetrics(SM_CXSCREEN);
	Direct3DParam.BackBufferHeight = GetSystemMetrics(SM_CYSCREEN);
	Direct3DParam.BackBufferCount = 3;
	Direct3DParam.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // выкл. vsync
	if (FAILED(m_pD3D ->CreateDevice(D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL, hwnd,
		D3DCREATE_HARDWARE_VERTEXPROCESSING,
		& Direct3DParam, &m_pd3dDevice )))
	return E_FAIL;
	
	// Создание текста
	CreateD3DXFont(&m_pd3dxFont,m_strFont,m_dwFontSize); 
	CreateD3DXFont(&m_pd3dxFont_Small,m_strFont,m_dwFontSize_Small);
	return S_OK;
}

Функция подсчета FPS (упирается в max Hz монитора)

//------------------------------------
// Подсчет кадров в секунду (версия 1)
// Функция GetFPS()
//------------------------------------
void GetFPS()
{
   // Колличество кадров в секунду между секундами
   static float FPS = 0.0f;
   // Используется для проверки если прошла секунда
   float nextSecond = 0.0f;
   // Последняя секунда которая occured
   static float prevSecond = 0.0f;
   // Добавляем к кадрам в секунду каждый раз когда вызывается эта функция
   FPS++;
   // Берем секунду в милисекундах, затем умножаем на 0.001 чтобы перевести в секунду
   nextSecond = GetTickCount() * 0.001f;

   // Если время извлеченное из предыдущей секунды больше или равно 1
   // (т.е. прошла секунда) то вывести число FPS
   if(nextSecond - prevSecond > 1.0f)
      {
      // Приравнивание для использования при следующем вызове этой функции
	prevSecond = nextSecond;
		   
      sprintf(buffer, "Кадров в Секунду = %.f", FPS);
      // Сбрасываем значение FPS
      FPS = 0;
      }
}

Вызов вывода текста и счетчика FPS

//-----------------------
// Прорисовка графики
// Функция Render()
//-----------------------
void Render()
{
  // Очистка экрана указанным D3DCOLOR_XRGB цветом 1 раз до цикла
  m_pd3dDevice ->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
						 D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
	
  // Начало сцены
  m_pd3dDevice ->BeginScene();

  // Прорисовка Сцены
  // Вывод текста на основе D3DXFont в 2D (малиновый цвет) 
  // Тескт - выводить последним, иначе он будет перекрыт другими объектами
  RECT rc = {100, 300, 0, 0}; //прямоугольник вывода текста
  RECT rc1 ={0, 0, 700, 100};
  m_pd3dxFont_Small->DrawText(0, buffer, -1, &rc1, DT_TOP|DT_LEFT,
				D3DCOLOR_XRGB(255, 255, 0));

  m_pd3dxFont->DrawText(0, _T("текст ID3DXFont !!!"), -1, &rc, 
				DT_SINGLELINE | DT_CALCRECT, 0 );
  m_pd3dxFont->DrawText(0, _T("текст ID3DXFont !!!"), -1, &rc, 
				DT_SINGLELINE, D3DCOLOR_ARGB(255, 255, 0, 255) );
        
  // Конец сцены
  m_pd3dDevice ->EndScene();
  m_pd3dDevice ->Present( NULL, NULL, NULL, NULL );
  GetFPS(); //вызов функции подсчета кадров
}

Освобождаем ресурсы

//-----------------------------------
// Освобожение захваченных ресурсов
// Функция Release3D()
//-----------------------------------
void Release3D()
{
	if(m_pd3dxFont !=NULL)
		m_pd3dxFont->Release();
	if(m_pd3dxFont_Small !=NULL)
		m_pd3dxFont_Small->Release();
	if( m_pd3dDevice  != NULL) 
		m_pd3dDevice ->Release();
	if( m_pD3D != NULL)
		m_pD3D ->Release();
}

В итоге мы получаем следующий экран приложения:

Текст и счетчик ID3DXFont

Возможные ошибки

Ошибка С2440 – не может конвертировать из ‘const char[]’ в ‘LPCWSTR’ ( winuser.h).
Причина - по умолчанию используется Unicode, нужно или работать в Unicode или поставить Multi-Byte (Character Set).
Решение:

Project -> "имя проекта" Properties (Alt+F7) -> Configuration Properties -> Generals -> Project Defaults -> Character Set -> Use Multi-Byte Character Set

(Что также может привести к ошибке – перегрузке функции main в консольных приложениях и в исходниках, написанных не на Visual C++ 2005)

Ошибка С2065 – будто бы не объявлен индификатор. Обычно в циклах (For Loop).
Причина - те самые Несовместимые Изменения или объявление переменной в цикле и использование её вне цикла.
Решение:

Project -> "имя проекта" Properties (Alt+F7) -> Configuration Properties -> C/C++ -> Language -> Force Conformance in For Loop Scope -> NO (/ZC:ForScope~)

Ошибка LNK 1120 - не может найти "libc.lib", "libcd.lib", "libcmtd.lib", "libci.lib" и т. д.
Возможное решение:
Alt+F7 -> Linker -> Input -> Ignore Specific Library -> введите имя отсутствующей библиотеки, чтобы попробовать собрать программу без неё.

 

 
   Скачать исходный код к статье
 
Страницы: 1 2