[DirectX]Programming.Role.Playing.Games:02_06_Font

    字体,如果按照Programming.Role.Playing.Games.with.DirectX书上的作做法,使用ID3DXFont会很简单,完全无脑,但是DX9太老了,在学习DX11的时候,就会发现没有ID3DXFont,需要自己利用绘制2D的方式来实现字体。还是老规则,左边的是用固定管线实现的,右边是用Shader实现的,而且这次会非常明显,有文字提示。

    Programming.Role.Playing.Games.with.DirectX书上用的DX9版本比较老,实现的方式有点不一样,所以就没有用书的源码。右边的就是使用贴图加构建顶点的方式来实现的,类似我之前学习DX11学习的font工程,也是我之前学习卡住的地方,显示有点模糊,之前以为是采样方式的问题,但在DX9上完全没问题,还的抽个时间再去学习下。

    来看下渲染的代码,代码是在Draw2D上修改的:

void FontClass::Render(IDirect3DDevice9* device, TCHAR* content, int strLength, RECT* rect, DWORD format, D3DCOLOR color)
{
	m_font->DrawTextW(nullptr, content, strLength, rect, format, color);
}

    是不是很简单,再加上创建ID3DXFont的函数,也没几句代码。

bool FontClass::Initialize(IDirect3DDevice9* device)
{
	D3DXFONT_DESC fontDesc;
	HRESULT result;

	::ZeroMemory(&fontDesc, sizeof(D3DXFONT_DESC));
	fontDesc.CharSet = DEFAULT_CHARSET;
	::lstrcpyn(fontDesc.FaceName, TEXT("Arial"), 20);
	fontDesc.Height = 25;
	fontDesc.Italic = false;
	fontDesc.MipLevels = D3DX_DEFAULT;
	fontDesc.OutputPrecision = 0;
	fontDesc.PitchAndFamily = 0;
	fontDesc.Quality = 0;
	fontDesc.Weight = 500;
	fontDesc.Width = 12;

	result = ::D3DXCreateFontIndirect(device, &fontDesc, &m_font);
	if (FAILED(result))
		return false;

	return true;
}

    这些接口都可以查到,而且更加仔细,就不细讲了。接着就上重点了,用渲染2D的方式来实现,其实也是很简单,就是一个字,一个正方形,两个三角面,6个顶点,其实也可以是4个顶点,但需要索引缓存。可以在Unity引擎里测试下,就会发现1个字就是2个三角面,4个顶点。

    Shader渲染,其实就是用Draw2D的代码,这里就不贴了,就贴构建顶点缓存的代码:

bool ShaderFontClass::BuildVertexArray(IDirect3DDevice9* device, char* sentence, float drawX, float drawY)
{
	VertexType* vertices;
	int numLetters;
	int index;
	HRESULT result;
	VertexType* verticesPtr;
	int width, height;

	numLetters = (int)::strlen(sentence);

	vertices = new VertexType[numLetters * 6];
	if (!vertices)
		return false;

	index = 0;
	width = 15;
	height = 25;

	for (int i = 0; i < numLetters; ++i)
	{
		int letter = (int)sentence[i] - 32;

		if (0 == letter)
			drawX += 3.0f;
		else
		{
			// First triangle
			vertices[index]._x = drawX;// Top left
			vertices[index]._y = drawY;
			vertices[index]._z = 0.0f;
			vertices[index]._rhw = 1.0f;
			vertices[index]._u = m_font[letter].left;
			vertices[index]._v = 0.0f;
			++index;

			vertices[index]._x = drawX + width;// Bottom right
			vertices[index]._y = drawY + height;
			vertices[index]._z = 0.0f;
			vertices[index]._rhw = 1.0f;
			vertices[index]._u = m_font[letter].right;
			vertices[index]._v = 1.0f;
			++index;

			vertices[index]._x = drawX;// Bottom left
			vertices[index]._y = drawY + height;
			vertices[index]._z = 0.0f;
			vertices[index]._rhw = 1.0f;
			vertices[index]._u = m_font[letter].left;
			vertices[index]._v = 1.0f;
			++index;

			// Second triangle
			vertices[index]._x = drawX;// Top left
			vertices[index]._y = drawY;
			vertices[index]._z = 0.0f;
			vertices[index]._rhw = 1.0f;
			vertices[index]._u = m_font[letter].left;
			vertices[index]._v = 0.0f;
			++index;

			vertices[index]._x = drawX + width;// Top right
			vertices[index]._y = drawY;
			vertices[index]._z = 0.0f;
			vertices[index]._rhw = 1.0f;
			vertices[index]._u = m_font[letter].right;
			vertices[index]._v = 0.0f;
			++index;

			vertices[index]._x = drawX + width;// Bottom right
			vertices[index]._y = drawY + height;
			vertices[index]._z = 0.0f;
			vertices[index]._rhw = 1.0f;
			vertices[index]._u = m_font[letter].right;
			vertices[index]._v = 1.0f;
			++index;

			drawX += m_font[letter].size + width;
		}
	}

	m_vertexCount = index;

	result = device->CreateVertexBuffer(
		sizeof(VertexType),
		D3DUSAGE_WRITEONLY,
		VERTEX_FVF,
		D3DPOOL_DEFAULT,
		&m_vertexBuffer,
		nullptr);
	if (FAILED(result))
		return false;

	result = m_vertexBuffer->Lock(0, 0, (void**)&verticesPtr, 0);
	if (FAILED(result))
		return false;

	::memcpy(verticesPtr, (void*)vertices, (sizeof(VertexType) * m_vertexCount));

	result = m_vertexBuffer->Unlock();
	if (FAILED(result))
		return false;

	return true;
}

    核心思想就是,根据一个字符,构建6个顶点,顶点位置没什么好讲的,重点就是uv的位置,因为dx是以左上角为原点的,而且uv的也是以左上角为原点的,topleft翻转一下其实就是bottomleft。

源码下载:下载地址

猜你喜欢

转载自blog.csdn.net/zp288105109a/article/details/80954366