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

xiaoxiao2021-02-28  28

    字体,如果按照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。

源码下载:下载地址

转载请注明原文地址: https://www.6miu.com/read-2630669.html

最新回复(0)