とりあえずフォントを表示

(VS2012)プロジェクトをダウンロード

【DX11_Font.cpp】


//----------------------------------------------------------
//
//  Application
//    DX11_Font
//
//  First Edition : October 21 2016
//  Author Mr.K
//
#include "stdafx.h"
#include <stsdio.h>
#include <crtdbg.h>
#include <D3D11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>

using namespace DirectX;
#include "D3D11Font.h"


//  import libraries
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"d3dcompiler.lib")

#define MAX_LOADSTRING 100

#define SAFE_DELETE(o)       if (o){  delete (o);  o = NULL;    }
#define SAFE_DELETE_ARRAY(o) if (o){  delete [] (o);  o = NULL; }
#define SAFE_RELEASE(o)      if (o){  (o)->Release(); o = NULL; }

//  Globals
TCHAR *g_pDriverType = NULL;
TCHAR *g_pFeatureLevel = NULL;
UINT  g_uiCount=0;

//
//  prototypes
//
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
HRESULT GetBackBufferSize(IDXGISwapChain *pSwapChain, DWORD *pWidth, DWORD *pHeight);
HRESULT    CreateDepthStencilView(
    ID3D11Device *pDevice,
    INT          width,
    INT          height,
    DXGI_FORMAT  fmtDepthStencil,
    ID3D11DepthStencilView    **ppDepthStencilView,
    ID3D11Texture2D           **ppDepthStencilTexture,
    ID3D11ShaderResourceView  **ppDepthStencilShaderResourceView
);
HRESULT CreateRenderTargetView(
    ID3D11Device             *pDevice,
    IDXGISwapChain           *pSwapChain,
    ID3D11RenderTargetView   **ppRenderTargetView,
    ID3D11ShaderResourceView **ppRenderTargetShaderResourceView
);
HRESULT CreateDeviceContextAndSwapChain(
    HWND                  hWnd,
    ID3D11Device          **ppDevice,        
    ID3D11DeviceContext   **ppContext,    
    IDXGISwapChain        **ppSwapChain,
    D3D_DRIVER_TYPE       *pDriverType,
    D3D_FEATURE_LEVEL     *pFeatureLevel
);

TCHAR *GetDriverTypeText(D3D_DRIVER_TYPE dt);
TCHAR *GetFeatureLevelText(D3D_FEATURE_LEVEL fl);

//
//  WinMain
//  the entry point of windows application
//
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    MSG msg;

    //  変数宣言
    WNDCLASSEX wcex;  //  ウィンドウクラス構造体
    HWND hWnd;        //  ウィンドウハンドル
    RECT    bounds,client;  //  RECT 構造体

    //  (1)-a ウィンドウクラスの登録
    wcex.cbSize = sizeof(WNDCLASSEX); 
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;  //  ウィンドウプロシージャの登録
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;  //  アプリケーションインスタンス
    wcex.hIcon          = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
    wcex.hCursor        = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = _T("D3D11_Font");  //  ウィンドウクラス名
    wcex.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);
    RegisterClassEx(&wcex);
 
    //  (1)-b ウィンドウの生成
    hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("D3D11_Font"),
                WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
                CW_USEDEFAULT,0,640,480,NULL,NULL,hInstance,NULL);
    if( !hWnd )
        return FALSE;

    //  ウィンドウサイズの調整
    //  ここは無くても動く
    GetWindowRect(hWnd,&bounds);
    GetClientRect(hWnd,&client);
    MoveWindow(hWnd,bounds.left,bounds.top,
        640 * 2 - client.right,
        480 * 2 - client.bottom,
        false );

    //  ウィンドウの再表示
    ShowWindow( hWnd, nCmdShow );
    UpdateWindow( hWnd );

    //==========Direct3D11 の初期化処理===================

    CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);          //  COM を初期化

    D3D_DRIVER_TYPE DriverType = D3D_DRIVER_TYPE_NULL;

    ID3D11DeviceContext      *pContext = NULL;              //  描画環境
    ID3D11Device             *pDevice = NULL;               //  仮想アダプタ(ハードウエア)
    IDXGISwapChain           *pSwapChain = NULL;            //  スワップチェイン
    ID3D11RenderTargetView   *pRenderTargetView = NULL;     //  レンダーターゲット
    ID3D11DepthStencilView   *pDepthStencilView = NULL;     //  深度ステンシルバッファ

    ID3D11Texture2D          *pDepthStencilTexture = NULL;            //  深度ステンシルサーフェイス
    ID3D11ShaderResourceView *pRenderTargetShaderResourceView = NULL; //  RenderTargetを TextureSampler からアクセス可能にしておく
    ID3D11ShaderResourceView *pDepthStencilShaderResourceView = NULL; //  DepthStencilを TextureSampler からアクセス可能にしておく

    D3D_FEATURE_LEVEL    FeatureLevel;

    DWORD        width, height;     //  Screen width, Screen height
CD3D11Font *pFont = NULL; // D3DFont  
HRESULT hr; // デバイス、デバイスコンテキストそしてスワップチェインを生成 hr = CreateDeviceContextAndSwapChain(hWnd,&pDevice,&pContext,&pSwapChain,&DriverType,&FeatureLevel); if ( FAILED( hr ) ) goto ERROR_EXIT; // RenderTaget を生成 hr = CreateRenderTargetView(pDevice,pSwapChain,&pRenderTargetView,&pRenderTargetShaderResourceView); if ( FAILED( hr ) ) goto ERROR_EXIT; // 深度ステンシルバッファ生成のため Backbuffer のサイズを取得 hr = GetBackBufferSize(pSwapChain,&width, &height); if ( FAILED( hr ) ) goto ERROR_EXIT; // サイズとフォーマットを指定して、深度ステンシルバッファを生成 hr = CreateDepthStencilView(pDevice,width,height,DXGI_FORMAT_D16_UNORM,&pDepthStencilView,&pDepthStencilTexture,&pDepthStencilShaderResourceView); if ( FAILED( hr ) ) goto ERROR_EXIT; // デバイスコンテキストにレンダーターゲットと深度ステンシルを設定 pContext->OMSetRenderTargets( 1, &pRenderTargetView,pDepthStencilView); // ビューポートの設定. D3D11_VIEWPORT vp; vp.Width = (FLOAT)width; vp.Height = (FLOAT)height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; // デバイスコンテキストにビューポートを設定. pContext->RSSetViewports( 1, &vp );
//==========各種オブジェクト生成=================== // フォントの作成 pFont = new CD3D11Font(pContext); // デバッグ表示の用意 g_pDriverType = ::GetDriverTypeText(DriverType); g_pFeatureLevel = GetFeatureLevelText(FeatureLevel);; g_uiCount=0; //=================================================  
// メイン メッセージ ループ: // (2)メッセージループ FLOAT fAngle = 0; while(true){ if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){ if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); }else{ // 指定色で画面クリア float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha pContext->ClearRenderTargetView( pRenderTargetView, ClearColor ); pContext->ClearDepthStencilView( pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
// フォントを描画 FLOAT x = 0.0f, y = 0.0f; TCHAR tmp[32]; int frame, sec, min, hour, day; frame = g_uiCount % 60; sec = (g_uiCount / 60) % 60; min = (g_uiCount / 3600) % 60; hour = (g_uiCount / (3600*60)) % 24; day = (g_uiCount / (3600*60*24)) % 99; _stprintf_s(tmp,_T("%02d:%02d:%02d:%02d:%02d"),day,hour,min,sec,frame); pFont->DrawAnkText(pContext,tmp,XMFLOAT4(1.0f,1.0f,1.0f,0.75f),x,y); pFont->DrawAnkText(pContext,g_pDriverType,XMFLOAT4(1.0f,0.25f,0.25f,1.0f),x,y+=24.f); pFont->DrawAnkText(pContext,g_pFeatureLevel,XMFLOAT4(0.25f,1.0f,0.25f,1.0f),x,y+=24.f);  
g_uiCount++; //結果をウインドウに反映 if (FAILED(hr = pSwapChain->Present( 1, 0 ))){ // デバイスロストへの対処は可能だが、ここでは単に終了する事にする if (hr == DXGI_ERROR_DEVICE_RESET || hr == DXGI_ERROR_DEVICE_REMOVED){ MessageBox(NULL,_T("Device が失われましたので終了します"),_T("Assert"),MB_OK); break; } } } } ERROR_EXIT: if (pContext){ pContext->ClearState(); pContext->Flush(); }
SAFE_DELETE(pFont);
SAFE_RELEASE(pRenderTargetShaderResourceView); SAFE_RELEASE(pDepthStencilTexture); SAFE_RELEASE(pDepthStencilShaderResourceView); SAFE_RELEASE(pRenderTargetView); SAFE_RELEASE(pDepthStencilView); SAFE_RELEASE(pSwapChain); SAFE_RELEASE(pContext); SAFE_RELEASE(pDevice); CoUninitialize(); // COM の終了 return (int) msg.wParam; } // // 関数:WndProc // 説明:ウインドウに渡されたイベントのハンドラ // LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { switch (message){ case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }



以下の関数は前回と同じなので内容省略します。


【CreateDeviceContextAndSwapChain・・・デバイスとスワップチェインの生成】

・・・省略


【CreateRenderTargetView・・・レンダーターゲットの生成】

・・・省略


【CreateDepthStencilView・・・深度ステンシルバッファの生成】

・・・省略


【GetBackBufferSize・・・バックバッファサイズの取得】

・・・省略


【GetBackBufferSize・・・バックバッファサイズの取得】

・・・省略


【デバッグ用関数】

・・・省略


class CD3D11Font



【D3D11Font.h】

#pragma once
#define D3DFONT_BOLD        0x0001
#define D3DFONT_ITALIC      0x0002
#define D3DFONT_SIZE_IN_PIXELS    0x1000

//  フォントのレンダリング時に指定するフラグ
#define D3DFONT_FILTERED    0x0004

__declspec(align(16)) class CD3D11Font
{
public:
    CD3D11Font(ID3D11DeviceContext *pContext);
    virtual ~CD3D11Font(void);
    virtual HRESULT RestoreDeviceObjects(ID3D11DeviceContext *pContext);
    virtual HRESULT ReleaseDeviceObjects(ID3D11DeviceContext *pContext);
    
    virtual void    Render(ID3D11DeviceContext *pContext);
    HRESULT CreateFontTexture();

    virtual void DrawAnkText(ID3D11DeviceContext *pContext,TCHAR *pString, DirectX::XMFLOAT4 color ,FLOAT x, FLOAT y);
    virtual void DrawChar(ID3D11DeviceContext *pContext, char ankCode, DirectX::XMFLOAT4 color, FLOAT *px, FLOAT *py);

    //  keep 16-byte aligned
    void *operator new(size_t size){
        return _mm_malloc(size,16);
    }
    void operator delete(void *p){
        return _mm_free(p);
    }

protected:
    HRESULT CompileShaderFromMemory(BYTE *code, DWORD dwSize, LPCSTR szEntryPoint,LPCSTR szShaderModel, ID3DBlob **ppBlobOut);

    ID3D11DeviceContext     *m_pDeviceContext;
    ID3D11Device            *m_pDevice;
    ID3D11Texture2D         *m_pTexture;
    ID3D11ShaderResourceView    *m_pTextureShaderResourceView;
    ID3D11SamplerState      *m_pTextureSamplerState;
    ID3D11VertexShader      *m_pVertexShader;
    ID3D11PixelShader       *m_pPixelShader;
    ID3D11InputLayout       *m_pInputLayout;
    ID3D11BlendState        *m_pBlendState;

    ID3D11Buffer        *m_pVertexBuffer;
    ID3D11Buffer        *m_pConstantBuffer;

    DWORD               m_dwFontFlags;
    DWORD               m_dwFontHeight;

    DirectX::XMMATRIX   m_matProj;

    DWORD   m_dwTexWidth;
    DWORD   m_dwTexHeight;
    TCHAR   *m_strFontName;
    BOOL    m_bInitialized;
    FLOAT   m_fTexCoords[128-32][4];
};
 


【D3D11Font.cpp】
//
//  class CD3D11Font
//  Desc: Ank Font on Direct3D11
//      Debug purpose
//
#include "stdafx.h"
#include <stdio.h>
#include <D3D11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
#include "D3D11Font.h"

#define SAFE_RELEASE(o) if(o){  (o)->Release(); o = NULL; }

extern HRESULT CompileShaderFromFile(
    WCHAR*      szFileName,
    LPCSTR      szEntryPoint,
    LPCSTR      szShaderModel,
    ID3DBlob    **ppBlobOut
);


static char shadercode[]="\
//-----------------------------------------------------------------------------------\n\
//  texture sampler\n\
//-----------------------------------------------------------------------------------\n\
SamplerState textureSampler : register(s0);\n\
Texture2D    diffuseTexture : register(t0);\n\
\n\
\n\
//-----------------------------------------------------------------------------------\n\
// Constant buffer\n\
//-----------------------------------------------------------------------------------\n\
cbuffer VSConstantBuffer : register( b0 )\n\
{\n\
    matrix  Proj;   //  projection matrix\n\
    float4  Color;  //  font color\n\
};\n\
\n\
\n\
//-----------------------------------------------------------------------------------\n\
// VSInput structure\n\
//-----------------------------------------------------------------------------------\n\
struct VSInput\n\
{\n\
    float3 Position : POSITION;     //  position\n\
    float2 texCoord : TEXCOORD0;    //  texture coordinates\n\
};\n\
\n\
//-----------------------------------------------------------------------------------\n\
// GSPSInput structure\n\
//-----------------------------------------------------------------------------------\n\
struct GSPSInput\n\
{\n\
    float4 Position : SV_POSITION;  //  position\n\
    float2 texCoord : TEXCOORD0;    //  texture coordinates\n\
    float4 diffuse  : COLOR;        //  font color\n\
};\n\
\n\
//-----------------------------------------------------------------------------------\n\
//  Vertex Shader Entry point\n\
//-----------------------------------------------------------------------------------\n\
GSPSInput VSFunc( VSInput input )\n\
{\n\
    GSPSInput output = (GSPSInput)0;\n\
\n\
    // 入力データをfloat4 へ変換.\n\
    float4 pos = float4( input.Position, 1.0f );\n\
\n\
    // 射影空間に変換.\n\
    float4 projPos  = mul( Proj,  pos );\n\
\n\
    output.Position = projPos;\n\
    output.texCoord = input.texCoord;\n\
    output.diffuse  = Color;\n\
    return output;\n\
}\n\
\n\
//------------------------------------------------------------------------------------\n\
//  Pixel shader entry point\n\
//------------------------------------------------------------------------------------\n\
float4 PSFunc( GSPSInput psin ) : SV_TARGET0\n\
{\n\
    float4 pixel = diffuseTexture.Sample(textureSampler, psin.texCoord);\n\
    pixel = psin.diffuse * pixel;\n\
    return pixel;\n\
}\n\
\n";


struct AnkFontVertex
{
    DirectX::XMFLOAT3 position;     //  position
    DirectX::XMFLOAT2 texture;      //  texture coordinates
};

typedef struct{
    DirectX::XMMATRIX    matProj;
    DirectX::XMFLOAT4    color;
}    AnkFontConstantBuffer;


CD3D11Font::CD3D11Font(ID3D11DeviceContext *pContext)
{
    //  いったんすべて NULL で初期化
    m_pDeviceContext = NULL;
    m_pDevice = NULL;
    m_pTexture = NULL;
    m_pTextureShaderResourceView = NULL;
    m_pTextureSamplerState = NULL;
    m_pVertexShader = NULL;
    m_pPixelShader = NULL;
    m_pInputLayout = NULL;
    m_pBlendState = NULL;
    m_pVertexBuffer = NULL;
    m_pConstantBuffer = NULL;
    
    //  デバッグ用デフォルト
    m_strFontName = _T("MS ゴシック");
    m_dwFontHeight = 20;
    m_dwFontFlags = 0;

    m_bInitialized = false;

    RestoreDeviceObjects(pContext);
}


CD3D11Font::~CD3D11Font(void)
{
    ReleaseDeviceObjects(NULL);
}

HRESULT CD3D11Font::RestoreDeviceObjects(ID3D11DeviceContext *pContext){
    ID3DBlob    *pShader = NULL;
    HRESULT hr;

    m_bInitialized = false;

    pContext->AddRef();
    ReleaseDeviceObjects(pContext);

    m_pDeviceContext = pContext;
    m_pDeviceContext->GetDevice(&m_pDevice);
    

    //  頂点シェーダの生成
    hr = CompileShaderFromMemory((BYTE*)shadercode,sizeof(shadercode),"VSFunc","vs_4_0",&pShader);
    if (FAILED(hr)){
        return    hr;
    }
    hr = m_pDevice->CreateVertexShader(pShader->GetBufferPointer(),pShader->GetBufferSize(),NULL,&m_pVertexShader);
    if (FAILED(hr)){
        return    hr;
    }


    // 入力レイアウトの定義.
    D3D11_INPUT_ELEMENT_DESC layout[] = {
        {
            "POSITION", 
            0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 
        },
        {
            "TEXCOORD", 
            0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 
        }
    };
    UINT numElements = ARRAYSIZE( layout );

    // 入力レイアウトを生成.
    hr = m_pDevice->CreateInputLayout( 
        layout,
        numElements,
        pShader->GetBufferPointer(),
        pShader->GetBufferSize(),
        &m_pInputLayout
    );
    SAFE_RELEASE(pShader);
    if ( FAILED( hr ) )
    {
        return hr;
    }

    // 入力アセンブラに入力レイアウトを設定.
    m_pDeviceContext->IASetInputLayout( m_pInputLayout );

    //  ピクセルシェーダの生成
    hr = CompileShaderFromMemory((BYTE*)shadercode,sizeof(shadercode),"PSFunc","ps_4_0",&pShader);
    if (FAILED(hr))
        return hr;
    hr = m_pDevice->CreatePixelShader(pShader->GetBufferPointer(),pShader->GetBufferSize(),NULL,&m_pPixelShader);
    SAFE_RELEASE(pShader);
    if (FAILED(hr))
        return    hr;

    hr = CreateFontTexture();

    if (FAILED(hr))
        return hr;

    // シェーダリソースビューを生成.
    {
        D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
        D3D11_TEXTURE2D_DESC    texDesc;
        ZeroMemory( &srvd, sizeof( D3D11_SHADER_RESOURCE_VIEW_DESC ) );
        m_pTexture->GetDesc(&texDesc);
        srvd.Format                     = texDesc.Format;
          srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
        srvd.Texture2D.MipLevels = texDesc.MipLevels;
        srvd.Texture2D.MostDetailedMip = 0;
        hr = m_pDevice->CreateShaderResourceView( m_pTexture, &srvd, &m_pTextureShaderResourceView);
        if (FAILED(hr))
            return hr;
    }

    //  サンプラ―のセットアップ
    {
        D3D11_SAMPLER_DESC samplerDesc;
        samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC;         // サンプリング時に使用するフィルタ。ここでは異方性フィルターを使用する。
        samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;     // 0 〜 1 の範囲外にある u テクスチャー座標の描画方法
        samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;     // 0 〜 1 の範囲外にある v テクスチャー座標
        samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;     // 0 〜 1 の範囲外にある w テクスチャー座標
        samplerDesc.MipLODBias = 0;                            // 計算されたミップマップ レベルからのバイアス
        samplerDesc.MaxAnisotropy = 16;                        // サンプリングに異方性補間を使用している場合の限界値。有効な値は 1 〜 16 。
        samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;  // 比較オプション。
        memcpy((void*)&samplerDesc.BorderColor,(void*)&DirectX::XMFLOAT4(0,0,0,0),4*sizeof(FLOAT));
        samplerDesc.MinLOD = 0;                                // アクセス可能なミップマップの下限値
        samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;                // アクセス可能なミップマップの上限値
        // ID3D11Device::CreateSamplerState
        hr = m_pDevice->CreateSamplerState( &samplerDesc, &m_pTextureSamplerState );
        if( FAILED( hr ) )
            return    hr;

    }
    // 頂点バッファの設定.
    {
            // 頂点の定義.
            AnkFontVertex vertices[] = {
                {  DirectX::XMFLOAT3( -0.5f,  0.5f, 0.0f ),  DirectX::XMFLOAT2(  0.0f,  0.0f ) },
                {  DirectX::XMFLOAT3(  0.5f,  0.5f, 0.0f ),  DirectX::XMFLOAT2(  1.0f,  0.0f ) },
                {  DirectX::XMFLOAT3( -0.5f, -0.5f, 0.0f ),  DirectX::XMFLOAT2(  0.0f,  1.0f ) },
                {  DirectX::XMFLOAT3(  0.5f, -0.5f, 0.0f ),  DirectX::XMFLOAT2(  1.0f,  1.0f ) },
            };
  
        D3D11_BUFFER_DESC bd;
        ZeroMemory( &bd, sizeof( D3D11_BUFFER_DESC ) );
        bd.Usage          = D3D11_USAGE_DEFAULT;
        bd.ByteWidth      = sizeof( AnkFontVertex ) * 4;
        bd.BindFlags      = D3D11_BIND_VERTEX_BUFFER;
        bd.CPUAccessFlags = 0;

        // サブリソースの設定.
        D3D11_SUBRESOURCE_DATA initData;
        ZeroMemory( &initData, sizeof( D3D11_SUBRESOURCE_DATA ) );
        initData.pSysMem = vertices;

        // 頂点バッファの生成.
        hr = m_pDevice->CreateBuffer( &bd, &initData, &m_pVertexBuffer );
        if ( FAILED( hr ) )
        {
            return    hr;
        }
    }
    // 定数バッファの生成.
    {
        // 定数バッファの設定.
        D3D11_BUFFER_DESC bd;
        ZeroMemory( &bd, sizeof( D3D11_BUFFER_DESC ) );
        bd.ByteWidth        = sizeof( AnkFontConstantBuffer );
        bd.Usage            = D3D11_USAGE_DEFAULT;
        bd.BindFlags        = D3D11_BIND_CONSTANT_BUFFER;
        bd.CPUAccessFlags   = 0;

        // 定数バッファを生成.
        hr = m_pDevice->CreateBuffer( &bd, NULL, &m_pConstantBuffer );
        if ( FAILED( hr ) )
        {
            return    hr;
        }
    }
    {
        //  アルファ抜きブレンドステートの生成
        D3D11_BLEND_DESC BlendDesc;
        ZeroMemory( &BlendDesc, sizeof( BlendDesc ) );
        BlendDesc.AlphaToCoverageEnable = FALSE;
        BlendDesc.IndependentBlendEnable = FALSE;
        BlendDesc.RenderTarget[0].BlendEnable = TRUE;
        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_ONE;
        BlendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
        BlendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
        BlendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
        for (int i = 1 ; i < 8 ; ++i){
            BlendDesc.RenderTarget[i] = BlendDesc.RenderTarget[0];
        }
        hr = m_pDevice->CreateBlendState( &BlendDesc, &m_pBlendState );
        if ( FAILED( hr ) )
        {
            return    hr;
        }
    }
    // 行列の設定.
    {
        //  non scaled ortho matrix (2D)
        m_matProj = DirectX::XMMatrixIdentity();
        m_matProj.r[0].m128_f32[0] = 1.0f;
        m_matProj.r[1].m128_f32[1] = 1.0f;
        m_matProj.r[2].m128_f32[2] = 0.0f;
        m_matProj.r[2].m128_f32[3] = 1.0f;
        m_matProj.r[3].m128_f32[2] = 0.0f;
        m_matProj.r[3].m128_f32[3] = 0.0f;
    }
    m_bInitialized = true;
    return S_OK;
}

//
//  ANK フォント用テクスチャの生成
//
HRESULT CD3D11Font::CreateFontTexture(){
    HDC        hDC = NULL;
    HBITMAP hbmBitmap = NULL;
    HFONT hFont = NULL;
    hDC        = CreateCompatibleDC( NULL );
    HRESULT hr;
    INT    nHeight;

    DWORD dwBold   = (m_dwFontFlags&D3DFONT_BOLD)   ? FW_BOLD : FW_NORMAL;
    DWORD dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE    : FALSE;


    if (m_dwFontFlags & D3DFONT_SIZE_IN_PIXELS){
        nHeight = (INT)(m_dwFontHeight);
    }else{
        __int64    tmp64 = m_dwFontHeight;
        tmp64 *= (INT)(GetDeviceCaps(hDC, LOGPIXELSY));
        nHeight    = (INT)(tmp64 / 72);    //  フォント高 * dpi * testScale / 72
    }

    // Large fonts need larger textures
    if( nHeight > 64 )
        m_dwTexWidth = m_dwTexHeight = 1024;
    else if( nHeight > 32 )
        m_dwTexWidth = m_dwTexHeight = 512;
    else
        m_dwTexWidth  = m_dwTexHeight = 256;

    D3D11_TEXTURE2D_DESC td;
    ZeroMemory( &td, sizeof( D3D11_TEXTURE2D_DESC ) );
    td.Width                = m_dwTexWidth;
    td.Height               = m_dwTexHeight;
    td.MipLevels            = 1;
    td.ArraySize            = 1;
    td.Format               = DXGI_FORMAT_R8G8B8A8_UNORM;
    td.SampleDesc.Count     = 1;    //  MULTI SAMPLE COUNT
    td.SampleDesc.Quality   = 0;    //  MULtI SAMPLE QUALITY
    td.Usage                = D3D11_USAGE_DYNAMIC;    //  Make it writeable
    td.BindFlags            = D3D11_BIND_SHADER_RESOURCE;
    td.CPUAccessFlags       = D3D11_CPU_ACCESS_WRITE;
    td.MiscFlags            = 0;
  
    // 2Dテクスチャの生成
    hr = m_pDevice->CreateTexture2D( &td, NULL, &this->m_pTexture );
    if ( FAILED( hr ) )
        return hr;

    
    DWORD*      pBitmapBits;
    BITMAPINFO bmi;
    ZeroMemory( &bmi.bmiHeader,  sizeof(BITMAPINFOHEADER) );
    bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth       =  (int)m_dwTexWidth;
    bmi.bmiHeader.biHeight      = -(int)m_dwTexHeight;
    bmi.bmiHeader.biPlanes      = 1;
    bmi.bmiHeader.biCompression = BI_RGB;
    bmi.bmiHeader.biBitCount    = 32;

    // ビットマップの作成
    hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
                                        (VOID**)&pBitmapBits, NULL, 0 );
    SetMapMode( hDC, MM_TEXT );

    //  ANTIALIASED_QUALITYを指定してフォントを生成する。
    //  アンチエイリアスを効かせたフォントを得ようとするが、
    //  アンチエイリアスがかかるとは保証されない。
    hFont    = CreateFont( -nHeight, 0, 0, 0, dwBold, dwItalic,
                        FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
                        CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
                        VARIABLE_PITCH, m_strFontName );
    if( NULL==hFont ){
        hr = E_FAIL;
    }else{
        SelectObject( hDC, hbmBitmap );
        SelectObject( hDC, hFont );

        // テキストプロパティーの設定
        SetTextColor( hDC, RGB(255,255,255) );
        SetBkColor(   hDC, 0x00000000 );
        SetTextAlign( hDC, TA_TOP );

        //  texture coordinatesを保存しながら、出力可能な文字をビットマップに
        //  出力してゆく。
        DWORD x = 0;
        DWORD y = 0;
        TCHAR str[2] = _T("x");
        SIZE size;

        for( TCHAR c=32; c<127; c++ )
        {
            str[0] = c;
            GetTextExtentPoint32( hDC, str, 1, &size );

            if( (DWORD)(x+size.cx+1) > m_dwTexWidth )
            {
                x  = 0;
                y += size.cy+1;
            }

            ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, str, 1, NULL );

            m_fTexCoords[c-32][0] = ((FLOAT)(x+0))/m_dwTexWidth;
            m_fTexCoords[c-32][1] = ((FLOAT)(y+0))/m_dwTexHeight;
            m_fTexCoords[c-32][2] = ((FLOAT)(x+0+size.cx))/m_dwTexWidth;
            m_fTexCoords[c-32][3] = ((FLOAT)(y+0+size.cy))/m_dwTexHeight;

            x += size.cx+1;
        }

        // Lock the surface and write the alpha values for the set pixels
        D3D11_MAPPED_SUBRESOURCE hMappedResource;
        hr = m_pDeviceContext->Map( 
            m_pTexture,
            0,
            D3D11_MAP_WRITE_DISCARD,
            0,
            &hMappedResource );
        if (SUCCEEDED(hr)){
            // ここで書き込む
            BYTE* pBits = (BYTE*)hMappedResource.pData;

            BYTE bAlpha; // 4-bit measure of pixel intensity

            for( y=0; y < m_dwTexHeight; y++ )
            {
                DWORD* pDst32 = (DWORD*)(pBits+(y*hMappedResource.RowPitch));
                for( x=0; x < m_dwTexWidth; x++ )
                {
                    bAlpha = (BYTE)(pBitmapBits[m_dwTexWidth*y + x] & 0xff);
                    if (bAlpha > 0){
                        *pDst32++ = 0x00ffffff | (bAlpha<<24);
                    }
                    else
                    {
                        *pDst32++ = 0x00000000;
                    }
                }
            }
            m_pDeviceContext->Unmap(m_pTexture,0);
        }
    }

    if (hbmBitmap)
        DeleteObject( hbmBitmap );
    if (hFont)
        DeleteObject( hFont );
    if (hDC)
        DeleteDC( hDC );

    return S_OK;
}

HRESULT CD3D11Font::ReleaseDeviceObjects(ID3D11DeviceContext *pContext){

    SAFE_RELEASE(m_pDeviceContext);
    SAFE_RELEASE(m_pDevice);
    SAFE_RELEASE(m_pTexture);
    SAFE_RELEASE(m_pTextureShaderResourceView);
    SAFE_RELEASE(m_pTextureSamplerState);
    SAFE_RELEASE(m_pVertexShader);
    SAFE_RELEASE(m_pPixelShader);
    SAFE_RELEASE(m_pInputLayout);
    SAFE_RELEASE(m_pBlendState);
    SAFE_RELEASE(m_pVertexBuffer);
    SAFE_RELEASE(m_pConstantBuffer);
    return    S_OK;

}


void    CD3D11Font::Render(ID3D11DeviceContext *pContext){

    if (!m_bInitialized)
        return;

    // シェーダを設定して描画.
    pContext->VSSetShader( m_pVertexShader, NULL, 0 );
    pContext->GSSetShader( NULL,            NULL, 0 );
    pContext->PSSetShader( m_pPixelShader,  NULL, 0 );

    // 定数バッファの設定.
    AnkFontConstantBuffer cb;
    cb.matProj  = m_matProj;
    //memcpy((void*)&cb.matProj,(void*)&m_matProj,sizeof(DirectX::XMMATRIX));
    cb.color = DirectX::XMFLOAT4(1.0,1.0,1.0,1.0);
    // サブリソースを更新.
    pContext->UpdateSubresource( m_pConstantBuffer, 0, NULL, &cb, 0, 0 );

    // ジオメトリシェーダに定数バッファを設定.
    pContext->VSSetConstantBuffers( 0, 1, &m_pConstantBuffer );

    // 入力アセンブラに頂点バッファを設定.
    UINT stride = sizeof( AnkFontVertex );
    UINT offset = 0;
    pContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

    // プリミティブの種類を設定.
    pContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );

    ID3D11ShaderResourceView* ppShaderResourceViews[] = { m_pTextureShaderResourceView, 0 };
    ID3D11SamplerState    *ppSamplerStates[] = { m_pTextureSamplerState, 0 };
    pContext->PSSetShaderResources(0, 1, ppShaderResourceViews);
    pContext->PSSetSamplers( 0, 1, ppSamplerStates );

    pContext->Draw(4,0);    //  Draw 4 vertices.

    ppSamplerStates[0] = NULL;
    ppShaderResourceViews[0] = NULL;
    pContext->PSSetSamplers( 0, 1, ppSamplerStates );
    pContext->PSSetShaderResources(0, 1, ppShaderResourceViews);
}

#define D3D_COMPILE_STANDARD_FILE_INCLUDE ((ID3DInclude*)(UINT_PTR)1)

HRESULT CD3D11Font::CompileShaderFromMemory(BYTE* pCode, DWORD dwSize, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob **ppBlobOut){
    // リターンコードを初期化.
    HRESULT hr = S_OK;

    // コンパイルフラグ.
    DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;

#if defined(DEBUG) || defined(_DEBUG)
    dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif//defiend(DEBUG) || defined(_DEBUG)

#if defined(NDEBUG) || defined(_NDEBUG)
    //dwShaderFlags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
#endif//defined(NDEBUG) || defined(_NDEBUG)

    ID3DBlob* pErrorBlob = NULL;

    // シェーダをコンパイル.
    hr = D3DCompile(pCode,dwSize,NULL,NULL,D3D_COMPILE_STANDARD_FILE_INCLUDE,
        szEntryPoint,szShaderModel,dwShaderFlags,0,ppBlobOut,&pErrorBlob);

    // エラーチェック.
    if ( FAILED( hr ) )
    {
        // エラーメッセージを出力.
        if ( pErrorBlob != NULL )
        { OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() ); }
    }

    // 解放処理.
    if ( pErrorBlob )
    {
        pErrorBlob->Release();
        pErrorBlob = NULL;
    }

    // リターンコードを返却.
    return hr;
}

void CD3D11Font::DrawChar(ID3D11DeviceContext *pContext,  char ankCode, DirectX::XMFLOAT4 color, FLOAT *px, FLOAT *py){
    
    if (!m_bInitialized)
        return;

    if (m_pDeviceContext != pContext)
        return;


    char c = ankCode;
    if (c < ' ')
        return;
    FLOAT fTexWidth = (FLOAT)m_dwTexWidth;
    FLOAT fTexHeight = (FLOAT)m_dwTexHeight;
    FLOAT fTexWidthInv = 1.0f / fTexWidth;
    FLOAT fTexHeightInv = 1.0f / fTexHeight;

    FLOAT tx1 = m_fTexCoords[c-32][0];
    FLOAT ty1 = m_fTexCoords[c-32][1];
    FLOAT tx2 = m_fTexCoords[c-32][2];
    FLOAT ty2 = m_fTexCoords[c-32][3];
    FLOAT w = (tx2-tx1) * fTexWidth;
    FLOAT h = (ty2-ty1) * fTexHeight;


    D3D11_VIEWPORT  vp;
    UINT            uiNumViewport = 1;
    m_pDeviceContext->RSGetViewports(&uiNumViewport,&vp);
    if (uiNumViewport != 1)
        return;

    //  transform 2D -> clipping space
    FLOAT l = *px;
    FLOAT t = *py;
    FLOAT r = l + w;
    FLOAT b = t + h;
    FLOAT z = 1.0f;
    l /= vp.Width*0.5f;
    t /= vp.Height*0.5f;
    r /= vp.Width*0.5f;
    b /= vp.Height*0.5f;
    l -= 1.0f;
    r -= 1.0f;
    t = 1.0f - t;
    b = 1.0f - b;
    
    *px += w;

    // 頂点バッファの設定.
    {
        // 頂点の定義.
        AnkFontVertex vertices[] = {
            {  DirectX::XMFLOAT3( l, t, z ),  DirectX::XMFLOAT2(  tx1,  ty1 ) },
            {  DirectX::XMFLOAT3( r, t, z ),  DirectX::XMFLOAT2(  tx2,  ty1 ) },
            {  DirectX::XMFLOAT3( l, b, z ),  DirectX::XMFLOAT2(  tx1,  ty2 ) },
            {  DirectX::XMFLOAT3( r, b, z ),  DirectX::XMFLOAT2(  tx2,  ty2 ) },
        };
  
        pContext->UpdateSubresource( m_pVertexBuffer, 0, NULL, vertices, 0, 0 );
        
    }

    // シェーダを設定
    pContext->VSSetShader( m_pVertexShader,   NULL, 0 );
    pContext->GSSetShader( NULL, NULL, 0 );
    pContext->PSSetShader( m_pPixelShader,    NULL, 0 );

    // 定数バッファの設定.
    AnkFontConstantBuffer cb;
    cb.matProj  = m_matProj;
    //memcpy((void*)&cb.matProj,(void*)&m_matProj,sizeof(DirectX::XMMATRIX));
    cb.color = DirectX::XMFLOAT4(color.x,color.y,color.z,color.w);
    DirectX::XMMatrixTranspose(cb.matProj);
    // サブリソースを更新.
    pContext->UpdateSubresource( m_pConstantBuffer, 0, NULL, &cb, 0, 0 );

    // ジオメトリシェーダに定数バッファを設定.
    pContext->VSSetConstantBuffers( 0, 1, &m_pConstantBuffer );

    // 入力アセンブラに頂点バッファを設定.
    UINT stride = sizeof( AnkFontVertex );
    UINT offset = 0;
    pContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

    // 入力アセンブラに入力レイアウトを設定.
    pContext->IASetInputLayout( m_pInputLayout );

    // プリミティブの種類を設定.
    pContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );

    ID3D11ShaderResourceView* ppShaderResourceViews[] = { m_pTextureShaderResourceView, 0 };
    ID3D11SamplerState    *ppSamplerStates[] = { m_pTextureSamplerState, 0 };
    pContext->PSSetShaderResources(0, 1, ppShaderResourceViews);
    pContext->PSSetSamplers( 0, 1, ppSamplerStates );

    pContext->Draw(4,0);    //  Draw 4 vertices.

    ppSamplerStates[0] = NULL;
    ppShaderResourceViews[0] = NULL;
    pContext->PSSetSamplers( 0, 1, ppSamplerStates );
    pContext->PSSetShaderResources(0, 1, ppShaderResourceViews);

}

void CD3D11Font::DrawAnkText(ID3D11DeviceContext *pContext,TCHAR *pString, DirectX::XMFLOAT4 color, FLOAT x, FLOAT y){
    FLOAT tmpx = x;
    FLOAT tmpy = y;

    float blendFactor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
    pContext->OMSetBlendState( m_pBlendState, blendFactor, 0xffffffff );

    TCHAR *p = pString;
    while(*p != (TCHAR)0){
        DrawChar(pContext,(char)(*p & 0x7f),color, &tmpx,&tmpy);
        p++;
    }

    pContext->OMSetBlendState( NULL, blendFactor, 0xffffffff );
}