|
05.01.2015, 16:11
|
#1
|
|
|
|
Старший сержант
|
Регистрация: 04.02.2011
Сообщений: 198
Популярность: 12244
Сказал(а) спасибо: 453
Поблагодарили 435 раз(а) в 242 сообщениях
|
[C++,DX11] Кириллица и шрифт для DX11 без дополнительных зависимостей.
Результат:
[ Ссылки могут видеть только зарегистрированные пользователи. ]
cD3D11Font.h
Код:
#pragma once
#include <Windows.h>
#include <d3dcompiler.h>
#include <D3DX11async.h>
#include <string>
#include <stdio.h>
#include <tchar.h>
#include <xnamath.h>
#include <D3D11.h>
#include <d3d9.h>
#pragma comment(lib, "d3dx11.lib")
using namespace std;
static const int MAX_CHAR_INDEX = 256;
#define FONT_LEFT 0
#define FONT_CENTER 1
#define FONT_RIGHT 2
#define D3DFONT_BOLD 0x0001
#define D3DFONT_ITALIC 0x0002
#define D3DFONT_ZENABLE 0x0004
#define D3DFONT_CENTERED 0x0001
#define D3DFONT_TWOSIDED 0x0002
#define D3DFONT_FILTERED 0x0004
class cD3D11Font
{
public:
cD3D11Font(string strFontName, DWORD m_dwFontHeight, DWORD m_dwFontFlags, ID3D11Device* pDevice);
struct D3D11Vertex
{
XMFLOAT3 vec;
DWORD color;
};
struct D3D11FontVertex
{
D3D11Vertex vertex;
XMFLOAT2 uv;
};
~cD3D11Font();
virtual HRESULT InitObjects();
virtual void DestroyObjects();
virtual void AddText(FLOAT sx, FLOAT sy, const char* strText, DWORD dwColor = 0xFFFFFFFF, float scale = 1.f, BYTE flag = FONT_LEFT);
virtual HRESULT GetTextExtent(const char* text, float scale, SIZE &sz);
virtual bool Begin();
virtual bool End();
HRESULT CreateFontObjects( UINT32& texWidth, XMFLOAT4 txtCoords[], DWORD** lpBitmapBits);
HRESULT CompileShaderFromMemory(const char* szdata, SIZE_T len, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut);
virtual void render_String(FLOAT x, FLOAT y, DWORD colour, BYTE flag, const char* strText, ...);
private:
TCHAR m_strFontName[80];
DWORD m_dwFontHeight;
DWORD m_dwFontFlags;
FLOAT m_fSpacing;
bool CheckChar(unsigned char c) { return c < 32 || c > MAX_CHAR_INDEX; }
UINT32 texWidth;
// float m_fSpacing;
XMFLOAT4* txtCoords;
DWORD maxFontVertices;
DWORD maxVertices;
bool VerticesResize;
bool FontVerticesResize;
DWORD numFontVertices;
DWORD numVertices;
float width, height;
ID3D11Device* m_pDevice;
ID3D11DeviceContext* m_pContext;
ID3D11InputLayout* m_InputLayout;
ID3D11BlendState* m_blendstate;
ID3D11RasterizerState* m_raststate;
ID3D11Buffer* m_vbuffer;
D3D11Vertex* m_vertexBuffer;
ID3D11PixelShader* m_pshader;
ID3D11VertexShader* m_vshader;
ID3D11Buffer* m_vfontbuffer;
ID3D11ShaderResourceView* m_fontTexture;
ID3D11InputLayout* m_fontInputLayout;
ID3D11PixelShader* m_fontpshader;
ID3D11VertexShader* m_fontvshader;
D3D11FontVertex* m_fontVertexBuffer;
bool alive;
ID3D11BlendState* m_pUILastBlendState;
float m_LastBlendFactor[4];
UINT m_LastBlendMask;
UINT m_LastStencilRef;
ID3D11InputLayout* m_LastInputLayout;
D3D11_PRIMITIVE_TOPOLOGY m_LastTopology;
ID3D11Buffer* m_LastBuffers[8];
UINT m_LastStrides[8];
UINT m_LastOffsets[8];
ID3D11PixelShader* m_LastPSShader;
ID3D11VertexShader* m_LastVSShader;
ID3D11GeometryShader* m_LastGSShader;
ID3D11DepthStencilState* m_LastDepthState;
ID3D11RasterizerState* m_pUILastRasterizerState;
};
#define CALC_FONT_SIZE(a) -MulDiv( a, (INT)(GetDeviceCaps(hDC, LOGPIXELSY)), 72 )
#define SafeRelease(v) if (v) { v->Release(); v = nullptr; }
const char pixshader[] =
{
"Texture2D tex2D;\n"
"SamplerState linearSampler\n"
"{\n"
" Filter = MIN_MAG_MIP_LINEAR;\n"
" AddressU = D3D11_TEXTURE_ADDRESS_BORDER;\n"
" AddressV = D3D11_TEXTURE_ADDRESS_BORDER;\n"
" BorderColor = float4(0.f, 0.f, 0.f, 1.f);\n"
"};\n"
"struct PS_INPUT\n"
"{\n"
" float4 pos : SV_POSITION;\n"
" float4 col : COLOR;\n"
"};\n"
"float4 main( PS_INPUT input ) : SV_Target\n"
"{\n"
" return input.col;\n"
"};\n"
"struct FPS_INPUT\n"
"{\n"
" float4 pos : SV_POSITION;\n"
" float4 col : COLOR;\n"
" float2 tex : TEXCOORD;\n"
"};\n"
"float4 fontmain( FPS_INPUT input ) : SV_Target\n"
"{\n"
" return tex2D.Sample( linearSampler, input.tex ) * input.col;\n"
"};\n"
};
const char vertshader[] =
{
"struct VS_INPUT\n"
"{\n"
" float4 pos : POSITION;\n"
" float4 col : COLOR;\n"
"};\n"
"struct PS_INPUT\n"
"{\n"
" float4 pos : SV_POSITION;\n"
" float4 col : COLOR;\n"
"};\n"
"struct FVS_INPUT\n"
"{\n"
" float4 pos : POSITION;\n"
" float4 col : COLOR;\n"
" float2 tex : TEXCOORD;\n"
"};\n"
"struct FPS_INPUT\n"
"{\n"
" float4 pos : SV_POSITION;\n"
" float4 col : COLOR;\n"
" float2 tex : TEXCOORD;\n"
"};\n"
"float4 rearrange(float4 value)\n"
"{\n"
" float4 color;\n"
" color.a = value.a;\n"
" color.r = value.b;\n"
" color.g = value.g;\n"
" color.b = value.r;\n"
" return color;\n"
"};\n"
"PS_INPUT main( VS_INPUT input )\n"
"{\n"
" PS_INPUT output;\n"
" output.pos = input.pos;\n"
" output.col = rearrange(input.col);\n"
" return output;\n"
"};\n"
"FPS_INPUT fontmain( FVS_INPUT input )\n"
"{\n"
" FPS_INPUT output;\n"
" output.pos = input.pos;\n"
" output.col = rearrange(input.col);\n"
" output.tex = input.tex;\n"
" return output;\n"
"};\n"
};
cD3D11Font.cpp
Код:
#include "cD3D11Font.h"
cD3D11Font::cD3D11Font(string strFontName, DWORD m_dwFontHeight, DWORD m_dwFontFlags, ID3D11Device* pDevice)
{
_tcsncpy(m_strFontName, strFontName.c_str(), sizeof(m_strFontName) / sizeof(TCHAR));
m_strFontName[sizeof(m_strFontName) / sizeof(TCHAR)-1] = _T('\0');
this->m_dwFontHeight = m_dwFontHeight;
this->m_dwFontFlags = m_dwFontFlags;
this->m_pDevice = pDevice;
m_pDevice->GetImmediateContext(&m_pContext);
m_vbuffer = nullptr;
m_vertexBuffer = nullptr;
m_vfontbuffer = nullptr;
m_fontTexture = nullptr;
m_fontVertexBuffer = nullptr;
m_fSpacing = 0;
VerticesResize = false;
FontVerticesResize = false;
maxVertices = 1;
maxFontVertices = 1;
txtCoords = new XMFLOAT4[MAX_CHAR_INDEX + 1 - 32];//
alive = false;
}
cD3D11Font::~cD3D11Font()
{
if (txtCoords)
{
delete[] txtCoords;
txtCoords = nullptr;
}
DestroyObjects();
}
HRESULT cD3D11Font::InitObjects()
{
HRESULT hr = S_OK;
DWORD* pBitmapBits;
alive = false;
if (FAILED(hr = CreateFontObjects( texWidth, txtCoords, &pBitmapBits)))
return hr;
ID3D11Texture2D* buftex;
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, texWidth, texWidth, 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
if (FAILED(hr = m_pDevice->CreateTexture2D(&texdesc, nullptr, &buftex)))
{
free(pBitmapBits);
return hr;
}
D3D11_MAPPED_SUBRESOURCE texmap;
if (FAILED(hr = m_pContext->Map(buftex, 0, D3D11_MAP_WRITE_DISCARD, 0, &texmap)))
{
SafeRelease(buftex);
free(pBitmapBits);
return hr;
}
BYTE bAlpha;
DWORD* pDst32;
BYTE* pDstRow = (BYTE*)texmap.pData;
for (UINT32 y = 0; y < texWidth; y++)
{
pDst32 = (DWORD*)pDstRow;
for (UINT32 x = 0; x < texWidth; x++)
{
bAlpha = BYTE((pBitmapBits[texWidth * y + x] & 0xFF) >> 4);
if (bAlpha > 0)
*pDst32++ = ((bAlpha * 0x11) << 24) | 0xFFFFFF;
else
*pDst32++ = 0x00000000;
}
pDstRow += texmap.RowPitch;
}
m_pContext->Unmap(buftex, 0);
free(pBitmapBits);
if (FAILED(hr = m_pDevice->CreateShaderResourceView(buftex, nullptr, &m_fontTexture)))
{
SafeRelease(buftex);
return hr;
}
ID3DBlob* pVSBlob = NULL;
if (FAILED(hr = CompileShaderFromMemory(vertshader, sizeof(vertshader), "main", "vs_4_0", &pVSBlob)))
{
DestroyObjects();
return hr;
}
if (FAILED(hr = m_pDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_vshader)))
{
DestroyObjects();
pVSBlob->Release();
return hr;
}
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = ARRAYSIZE(layout);
hr = m_pDevice->CreateInputLayout(layout, numElements, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &m_InputLayout);
pVSBlob->Release();
if (FAILED(hr))
{
DestroyObjects();
return hr;
}
if (FAILED(hr = CompileShaderFromMemory(vertshader, sizeof(vertshader), "fontmain", "vs_4_0", &pVSBlob)))
{
DestroyObjects();
return hr;
}
if (FAILED(hr = m_pDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_fontvshader)))
{
DestroyObjects();
pVSBlob->Release();
return hr;
}
hr = m_pDevice->CreateInputLayout(layout, numElements, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &m_fontInputLayout);
pVSBlob->Release();
if (FAILED(hr))
{
DestroyObjects();
return hr;
}
ID3DBlob* pPSBlob = NULL;
if (FAILED(hr = CompileShaderFromMemory(pixshader, sizeof(pixshader), "main", "ps_4_0", &pPSBlob)))
{
DestroyObjects();
return hr;
}
// Create the pixel shader
hr = m_pDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &m_pshader);
pPSBlob->Release();
if (FAILED(hr))
{
DestroyObjects();
return hr;
}
hr = CompileShaderFromMemory(pixshader, sizeof(pixshader), "fontmain", "ps_4_0", &pPSBlob);
if (FAILED(hr))
{
DestroyObjects();
return hr;
}
// Create the pixel shader
hr = m_pDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &m_fontpshader);
pPSBlob->Release();
if (FAILED(hr))
{
DestroyObjects();
return hr;
}
D3D11_BLEND_DESC blenddesc;
blenddesc.AlphaToCoverageEnable = FALSE;
blenddesc.IndependentBlendEnable = FALSE;
blenddesc.RenderTarget[0].BlendEnable = TRUE;
blenddesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
blenddesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blenddesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blenddesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blenddesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blenddesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
blenddesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
hr = m_pDevice->CreateBlendState(&blenddesc, &m_blendstate);
if (FAILED(hr))
{
DestroyObjects();
return hr;
}
D3D11_RASTERIZER_DESC rastdesc = CD3D11_RASTERIZER_DESC(D3D11_FILL_SOLID, D3D11_CULL_NONE, false, 0, 0.f, 0.f, false, false, false, false);
if (FAILED(hr = m_pDevice->CreateRasterizerState(&rastdesc, &m_raststate)))
{
DestroyObjects();
return hr;
}
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(maxVertices * sizeof(D3D11Vertex), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
if (FAILED(hr = m_pDevice->CreateBuffer(&bufdesc, NULL, &m_vbuffer)))
{
DestroyObjects();
return hr;
}
bufdesc = CD3D11_BUFFER_DESC(maxFontVertices * sizeof(D3D11FontVertex), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
if (FAILED(hr = m_pDevice->CreateBuffer(&bufdesc, NULL, &m_vfontbuffer)))
{
DestroyObjects();
return hr;
}
alive = true;
D3D11_VIEWPORT vp;
UINT numViewports = 1;
m_pContext->RSGetViewports(&numViewports, &vp);
width = vp.Width;
height = vp.Height;
return D3D_OK;
}
HRESULT cD3D11Font::CreateFontObjects( UINT32& texWidth, XMFLOAT4 txtCoords[], DWORD** lpBitmapBits)
{
this->m_fSpacing = 0.f;
if (this->m_dwFontHeight > 40)
texWidth = 1024;
else if (this->m_dwFontHeight >20)
texWidth = 512;
else
texWidth = 256;
DWORD* pBitmapBits;
BITMAPINFO bmi;
ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = texWidth;
bmi.bmiHeader.biHeight = -static_cast<int>(texWidth);
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 32;
HDC hDC = CreateCompatibleDC(NULL);
HBITMAP hBitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&pBitmapBits, NULL, 0);
SetMapMode(hDC, MM_TEXT);
HFONT hFont = CreateFontA(CALC_FONT_SIZE(this->m_dwFontHeight), 0, 0, 0, this->m_dwFontFlags, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, m_strFontName);
if (!hFont)
return E_FAIL;
SelectObject(hDC, hBitmap);
SelectObject(hDC, hFont);
SetTextColor(hDC, RGB(0xFF, 0xFF, 0xFF));
SetBkColor(hDC, 0x00000000);
SetTextAlign(hDC, TA_TOP);
float x = 0,
y = 0;
char str[2] = "x";
SIZE sz;
//GetTextExtentPoint32A(hDC, " ", 1, &sz);
//x = m_fSpacing = ceilf(sz.cy * 0.3f);
for (int c = 32; c < MAX_CHAR_INDEX; c++)
{
str[0] = c;
GetTextExtentPoint32A(hDC, str, 1, &sz);
if (x + sz.cx + m_fSpacing > texWidth)
{
x = m_fSpacing;
y += sz.cy + 1;
}
ExtTextOutA(hDC, static_cast<int>(ceilf(x)), static_cast<int>(ceilf(y)), ETO_OPAQUE, NULL, str, 1, NULL);
txtCoords[c - 32] = XMFLOAT4((x - m_fSpacing) / texWidth, y / texWidth, (x + sz.cx + m_fSpacing) / texWidth, (y + sz.cy) / texWidth);
x += sz.cx + (2 * m_fSpacing);
}
DWORD len = sizeof(DWORD)* texWidth * texWidth;
DWORD* buffer = static_cast<DWORD*>(malloc(len));
if (!buffer)
return E_OUTOFMEMORY;
memcpy(buffer, pBitmapBits, len);
*lpBitmapBits = buffer;
DeleteObject(hBitmap);
DeleteObject(hFont);
DeleteDC(hDC);
return S_OK;
}
HRESULT cD3D11Font::CompileShaderFromMemory(const char* szdata, SIZE_T len, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut)
{
HRESULT hr = S_OK;
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif
ID3DBlob* pErrorBlob;
hr = D3DX11CompileFromMemory(szdata, len, NULL, NULL, NULL, szEntryPoint, szShaderModel,
dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL);
if (FAILED(hr))
{
if (pErrorBlob)
pErrorBlob->Release();
return hr;
}
if (pErrorBlob)
pErrorBlob->Release();
return S_OK;
}
bool cD3D11Font::Begin()
{
if (VerticesResize)
{
SafeRelease(m_vbuffer);
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(maxVertices * sizeof(D3D11Vertex), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
if (FAILED(m_pDevice->CreateBuffer(&bufdesc, NULL, &m_vbuffer)))
return false;
VerticesResize = false;
}
if (FontVerticesResize)
{
SafeRelease(m_vfontbuffer);
D3D11_BUFFER_DESC bufdesc = CD3D11_BUFFER_DESC(maxFontVertices * sizeof(D3D11FontVertex), D3D11_BIND_VERTEX_BUFFER, D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
if (FAILED(m_pDevice->CreateBuffer(&bufdesc, NULL, &m_vfontbuffer)))
return false;
FontVerticesResize = false;
}
if (!alive)
InitObjects();
if (!m_vbuffer || !m_vfontbuffer || !m_fontTexture)
return false;
D3D11_MAPPED_SUBRESOURCE map;
m_pContext->Map(m_vbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
m_vertexBuffer = (D3D11Vertex*)map.pData;
m_pContext->Map(m_vfontbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
m_fontVertexBuffer = (D3D11FontVertex*)map.pData;
m_pContext->OMGetBlendState(&m_pUILastBlendState, m_LastBlendFactor, &m_LastBlendMask);
m_pContext->RSGetState(&m_pUILastRasterizerState);
m_pContext->OMGetDepthStencilState(&m_LastDepthState, &m_LastStencilRef);
m_pContext->IAGetInputLayout(&m_LastInputLayout);
m_pContext->IAGetPrimitiveTopology(&m_LastTopology);
m_pContext->IAGetVertexBuffers(0, 8, m_LastBuffers, m_LastStrides, m_LastOffsets);
m_pContext->PSGetShader(&m_LastPSShader, NULL, 0);
m_pContext->GSGetShader(&m_LastGSShader, NULL, 0);
m_pContext->VSGetShader(&m_LastVSShader, NULL, 0);
return true;
}
bool cD3D11Font::End()
{
m_pContext->Unmap(m_vbuffer, 0);
m_vertexBuffer = nullptr;
m_pContext->Unmap(m_vfontbuffer, 0);
m_fontVertexBuffer = nullptr;
if (numVertices > maxVertices)
{
maxVertices = numVertices;
VerticesResize = true;
}
if (numFontVertices > maxFontVertices)
{
maxFontVertices = numFontVertices;
FontVerticesResize = true;
}
m_pContext->RSSetState(m_raststate);
m_pContext->IASetInputLayout(m_InputLayout);
UINT stride = sizeof(D3D11Vertex);
UINT offset = 0;
m_pContext->OMSetBlendState(m_blendstate, NULL, 0xFFFFFFFF);
m_pContext->IASetVertexBuffers(0, 1, &m_vbuffer, &stride, &offset);
m_pContext->PSSetShader(m_pshader, NULL, 0);
m_pContext->VSSetShader(m_vshader, NULL, 0);
m_pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_pContext->Draw(numVertices, 0);
stride = sizeof(D3D11FontVertex);
offset = 0;
m_pContext->IASetInputLayout(m_fontInputLayout);
m_pContext->IASetVertexBuffers(0, 1, &m_vfontbuffer, &stride, &offset);
m_pContext->PSSetShader(m_fontpshader, NULL, 0);
m_pContext->VSSetShader(m_fontvshader, NULL, 0);
m_pContext->PSSetShaderResources(0, 1, &m_fontTexture);
m_pContext->Draw(numFontVertices, 0);
numVertices = 0;
numFontVertices = 0;
m_pContext->OMSetBlendState(m_pUILastBlendState, m_LastBlendFactor, m_LastBlendMask);
m_pContext->RSSetState(m_pUILastRasterizerState);
m_pContext->OMSetDepthStencilState(m_LastDepthState, m_LastStencilRef);
m_pContext->IASetInputLayout(m_LastInputLayout);
m_pContext->IASetPrimitiveTopology(m_LastTopology);
m_pContext->IASetVertexBuffers(0, 8, m_LastBuffers, m_LastStrides, m_LastOffsets);
m_pContext->PSSetShader(m_LastPSShader, NULL, 0);
m_pContext->GSSetShader(m_LastGSShader, NULL, 0);
m_pContext->VSSetShader(m_LastVSShader, NULL, 0);
return true;
}
void cD3D11Font::DestroyObjects()
{
alive = false;
SafeRelease(m_vbuffer);
SafeRelease(m_vfontbuffer);
SafeRelease(m_fontTexture);
SafeRelease(m_InputLayout);
SafeRelease(m_pshader);
SafeRelease(m_vshader);
SafeRelease(m_fontpshader);
SafeRelease(m_fontvshader);
SafeRelease(m_blendstate);
SafeRelease(m_raststate);
}
void cD3D11Font::AddText(FLOAT _x, FLOAT _y, const char* strText, DWORD colour, FLOAT scale, BYTE flag)
{
float scalex = 1 / (float)width * 2.f;
float scaley = 1 / (float)height * 2.f;
register float loc[4] = { (_x - m_fSpacing * scale) * scalex - 1.f, 1.f - _y * scaley, 0, 0 };
if (flag != FONT_LEFT)
{
if (flag == FONT_RIGHT)
{
SIZE sz;
GetTextExtent(strText, scale, sz);
loc[0] -= static_cast<float>(sz.cx) * scalex;
}
else if (flag == FONT_CENTER)
{
SIZE sz;
GetTextExtent(strText, scale, sz);
loc[0] -= static_cast<float>(sz.cx) / 2.0f * scalex;
}
}
float fStartX = loc[0];
while (*strText)
{
unsigned char c = *strText++;
if (c == '\n')
{
loc[0] = fStartX;
loc[1] += (txtCoords[c - 32].y - txtCoords[c - 32].w) * texWidth * scaley * scale;
}
if (CheckChar(c))
continue;
loc[2] = loc[0] + ((txtCoords[c - 32].z - txtCoords[c - 32].x) * texWidth * scalex * scale);
loc[3] = loc[1] + ((txtCoords[c - 32].y - txtCoords[c - 32].w) * texWidth * scaley * scale);
if (c != ' ')
{
c -= 32;
if (numFontVertices + 6 <= maxFontVertices)
{
D3D11FontVertex v[6];
v[0] = { { XMFLOAT3(loc[0], loc[3], 0.5f), colour }, XMFLOAT2(txtCoords[c].x, txtCoords[c].w) };
v[1] = { { XMFLOAT3(loc[0], loc[1], 0.5f), colour }, XMFLOAT2(txtCoords[c].x, txtCoords[c].y) };
v[2] = { { XMFLOAT3(loc[2], loc[3], 0.5f), colour }, XMFLOAT2(txtCoords[c].z, txtCoords[c].w) };
v[3] = { { XMFLOAT3(loc[2], loc[1], 0.5f), colour }, XMFLOAT2(txtCoords[c].z, txtCoords[c].y) };
v[4] = v[2];
v[5] = v[1];
memcpy(m_fontVertexBuffer, v, 6 * sizeof(D3D11FontVertex));
m_fontVertexBuffer += 6;
}
numFontVertices += 6;
}
loc[0] += loc[2] - loc[0] - (2 * m_fSpacing * scalex * scale);
}
}
HRESULT cD3D11Font::GetTextExtent(const char* strText, float scale, SIZE &sz)
{
if (NULL == strText)
return E_FAIL;
register float fRowWidth = 0.0f;
float fRowHeight = (txtCoords[0].y - txtCoords[0].w) * texWidth;
float fWidth = 0.0f;
float fHeight = fRowHeight;
while (*strText)
{
//register char c = (*strText++) - 32;
unsigned char c = *strText++;
if (c == ('\n' - 32))
{
fRowWidth = 0.0f;
fHeight += fRowHeight;
}
// if ((c) < 0 || (c) >= 256 - 32)continue;
if (CheckChar(c))continue;
float tx1 = txtCoords[c].x;
float tx2 = txtCoords[c].z;
fRowWidth += (tx2 - tx1)* texWidth - 2 * m_fSpacing;
if (fRowWidth > fWidth)
fWidth = fRowWidth;
}
sz.cx = static_cast<LONG>(fWidth * scale);
sz.cy = static_cast<LONG>(fHeight * scale);
return S_OK;
}
void cD3D11Font::render_String(FLOAT x, FLOAT y, DWORD colour, BYTE flag, const char* strText,...)
{
char buf[1024] = { '\0' };
va_list va_alist;
va_start(va_alist, strText);
vsprintf_s(buf, strText, va_alist);
va_end(va_alist);
AddText(x, y - 1.0f, buf, 0xFF000000, 1.f, flag);
AddText(x, y + 1.0f, buf, 0xFF000000, 1.f, flag);
AddText(x - 1.0f, y, buf, 0xFF000000, 1.f, flag);
AddText(x + 1.0f, y, buf, 0xFF000000, 1.f, flag);
AddText(x, y, buf, colour, 1.f, flag);
}
Подключаем к основному проекту задав указатель:
Код:
#include "cD3D11Font.h"
cD3D11Font * D3D11Font = nullptr;
Так же заводим указатель на интерфейс устройства:
Код:
ID3D11Device* newDevice = NULL;
Внутри Present() иницализируем - пулучив устройство из IDXGISwapChain и выводим текст
Код:
ID3D11Device* newDevice = NULL;
if (SUCCEEDED(pSwapChain->GetDevice(__uuidof(ID3D11Device), (void **)&newDevice)))
{
if (D3D11Font == nullptr)
{
D3D11Font = new cD3D11Font("Tahoma", 8, FW_BOLD, newDevice);
D3D11Font->InitObjects();
}
D3D11Font->Begin();
D3D11Font->render_String(10, 10, 0xff00ff00, FONT_LEFT, "Hello, world!");
D3D11Font->render_String(10, 23, 0xff00ff00, FONT_LEFT, "Привет, мир!");
D3D11Font->End();
}
_________________________
D3D11 Engine.jpg
________________
-Отложи на послезавтра то что можешь сделать сегодня, и тогда у тебя появятся два свободных дня!
|
|
|
7 пользователя(ей) сказали cпасибо:
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Заявление об ответственности / Список мошенников
Часовой пояс GMT +4, время: 19:53.
|
|