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

【DX11_Sprite.cpp】

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

using namespace DirectX;
#include "TextureLoader.h" #include "D3D11Sprite.h"  
#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_Sprite"); // ウィンドウクラス名 wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&wcex); // (1)-b ウィンドウの生成 hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("D3D11_Sprite"), 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; // ID3D11ShaderResourceView *pDepthStencilShaderResourceView = NULL; // D3D_FEATURE_LEVEL FeatureLevel; DWORD width, height; // Screen width, Screen height CD3D11Font *pFont = NULL; // D3DFont
CD3D11Sprite *pSprite = NULL; // Sprite  
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 ); //==========各種オブジェクト生成===================
// スプライトの作成 CTextureLoader::Initialize(); pSprite = new CD3D11Sprite(); pSprite->SetTexture(0,_T("res\\smile2.rle.tga")); pSprite->RestoreDeviceObjects(pContext);  
// フォントの作成 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 );
// スプライト描画 static int k = 0, animframe; pSprite->SetDiffuse(1.0f,1.0f,1.0f,1.0f); pSprite->Render(pContext,64.0f,100.0f,256.0f,256.0f,0); // 画像全体描画 // 画像一部描画(アニメーション) k = (k+1) % 120; animframe = 0; if (k >= 96){ animframe = (k - 96)/6; if (animframe >= 4){ animframe = 6 - animframe; } } pSprite->Render(pContext,400.0f,210.0f,64.0f,64.0f,animframe*64.0f,0.0f,64.0f,64.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: CTextureLoader::Destroy();
SAFE_DELETE(pSprite);
SAFE_DELETE(pFont); if (pContext){ pContext->ClearState(); pContext->Flush(); } 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・・・バックバッファサイズの取得】

・・・省略


【デバッグ用関数】

・・・省略


クラス CD3D11Sprite

【D3D11Sprite.h】

#pragma once
struct SpriteDataContext;
class CD3D11Sprite
{
public:
    CD3D11Sprite(void);
    virtual ~CD3D11Sprite(void);
    virtual void    SetTexture(INT no, TCHAR *pFilename);
    virtual HRESULT RestoreDeviceObjects(ID3D11DeviceContext *pContext);
    virtual HRESULT ReleaseDeviceObjects(ID3D11DeviceContext *pContext);
    virtual void    Render(ID3D11DeviceContext *pContext, FLOAT x, FLOAT y, FLOAT w, FLOAT h, INT no);
    virtual void    Render(ID3D11DeviceContext *pContext, FLOAT x, FLOAT y, FLOAT w, FLOAT h, FLOAT tx, FLOAT ty, FLOAT tw, FLOAT th, INT no);
    virtual void    SetDiffuse(FLOAT r, FLOAT g, FLOAT b, FLOAT a);
    virtual INT     GetNumTextures();

    //  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);

    void InitFields();
    SpriteDataContext   *m_pDataContext;
    ID3D11DeviceContext *m_pDeviceContext;
    ID3D11Device        *m_pDevice;
    ID3D11SamplerState  *m_pTextureSamplerState;
    ID3D11VertexShader  *m_pVertexShader;
    ID3D11PixelShader   *m_pPixelShader;
    ID3D11PixelShader   *m_pPixelShaderNoTex;
    ID3D11InputLayout   *m_pInputLayout;
    ID3D11BlendState    *m_pBlendState;

    ID3D11Buffer        *m_pVertexBuffer;
    ID3D11Buffer        *m_pConstantBuffer;

    DirectX::XMMATRIX   m_matProj;
    DirectX::XMFLOAT4   m_vecDiffuse;
};



【D3D11Sprite.cpp】

//
//  class CD3D11Sprite
//  Desc: This class implements 2D sprites on Direct3D11
//  
#include "stdafx.h"
#include <d3d11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
#include "D3D11Sprite.h"
#include "TextureLoader.h"
#include <vector>

//  
#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; }

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;   //  射影行列\n\
    float4  Color;  //  モジュレ―トする色\n\
};\n\
\n\
\n\
//-----------------------------------------------------------------------------------\n\
// VSInput structure\n\
//-----------------------------------------------------------------------------------\n\
struct VSInput\n\
{\n\
    float3 Position : POSITION;     //  位置座標\n\
    float2 texCoord : TEXCOORD0;    //  テクスチャ座標\n\
};\n\
\n\
//-----------------------------------------------------------------------------------\n\
// GSPSInput structure\n\
//-----------------------------------------------------------------------------------\n\
struct GSPSInput\n\
{\n\
    float4 Position : SV_POSITION;  //  位置座標\n\
    float2 texCoord : TEXCOORD0;    //  テクスチャ座標\n\
    float4 diffuse  : COLOR;        //  文字色\n\
};\n\
\n\
//-----------------------------------------------------------------------------------\n\
//  頂点シェーダエントリーポイント\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\
//  ピクセルシェーダエントリーポイント\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\
float4 PSFuncNoTex( GSPSInput psin ) : SV_TARGET0\n\
{\n\
    return psin.diffuse;\n\
}\n\
\n";

//  テクスチャ管理用のノード構造体
struct SpriteTexture{
    TCHAR                *pFilename;
    ID3D11Texture2D        *pTexture;
    ID3D11ShaderResourceView    *pTextureShaderResourceView;
    DWORD                dwSrcWidth;
    DWORD                dwSrcHeight;

    SpriteTexture(){
        pFilename = NULL;
        pTexture = NULL;
        pTextureShaderResourceView = NULL;
    }
    ~SpriteTexture(){
        SAFE_DELETE(pFilename);
        SAFE_RELEASE(pTexture);
        SAFE_RELEASE(pTextureShaderResourceView);
    }
};

//  テクスチャ管理用データ
//  stl の展開を局所化するためローカルデータ構造としておく
struct SpriteDataContext{
    std::vector<SpriteTexture *>    pSpriteTextures;
};

//  Vertex Structure
typedef struct {
    DirectX::XMFLOAT3 position;     //  位置座標
    DirectX::XMFLOAT2 texture;      //  テクスチャ座標
}    SpriteVertex;

//  Constant buffer structure
typedef struct {
    DirectX::XMMATRIX    matProj;
    DirectX::XMFLOAT4    color;
}    SpriteConstantBuffer;

//
//  constructor
//
CD3D11Sprite::CD3D11Sprite(void)
{
    InitFields();
    m_pDataContext = new SpriteDataContext;
}

//
//  destructor
//
CD3D11Sprite::~CD3D11Sprite(void)
{
    ReleaseDeviceObjects(m_pDeviceContext);
    std::vector<SpriteTexture *>::iterator it;
    it = m_pDataContext->pSpriteTextures.begin();
    while(it != m_pDataContext->pSpriteTextures.end()){
        SAFE_DELETE(*it);
        ++it;
    }
    SAFE_DELETE(m_pDataContext);
}

//  全フィールドの初期化
void CD3D11Sprite::InitFields(){

    m_pDataContext = NULL;
    m_pDeviceContext = NULL;
    m_pDevice = NULL;
    m_pTextureSamplerState = NULL;
    m_pVertexShader = NULL;
    m_pPixelShader = NULL;
    m_pPixelShaderNoTex = NULL;
    m_pInputLayout = NULL;
    m_pBlendState = NULL;
    m_pVertexBuffer = NULL;
    m_pConstantBuffer = NULL;

}

//
//  Restore device dependent objects.
//
HRESULT CD3D11Sprite::RestoreDeviceObjects(ID3D11DeviceContext *pContext){
    ID3DBlob    *pShader = NULL;
    HRESULT hr = E_FAIL;

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

    m_pDeviceContext = pContext;
    m_pDeviceContext->GetDevice(&m_pDevice);
    
    if (m_pDataContext){
        std::vector<SpriteTexture*>::iterator it;
        it = m_pDataContext->pSpriteTextures.begin();
        while (it != m_pDataContext->pSpriteTextures.end()){
            if (*it != NULL){
                ID3D11Texture2D        *pTexture = NULL;
                ID3D11ShaderResourceView    *pTextureShaderResourceView = NULL;
                
                hr = CTextureLoader::CreateTextureFromFile(pContext,
                    (*it)->pFilename,   &pTexture,
                    &(*it)->dwSrcWidth, &(*it)->dwSrcHeight
                );
                // シェーダリソースビューを生成.
                if (SUCCEEDED(hr)){
                    D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
                    D3D11_TEXTURE2D_DESC    texDesc;
                    ZeroMemory( &srvd, sizeof( D3D11_SHADER_RESOURCE_VIEW_DESC ) );
                    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( pTexture, &srvd, &pTextureShaderResourceView);
                }
                if (FAILED(hr)){
                    SAFE_RELEASE(pTexture);
                    SAFE_RELEASE(pTextureShaderResourceView);
                }
                (*it)->pTexture = pTexture;
                (*it)->pTextureShaderResourceView = pTextureShaderResourceView;
            }
            ++it;
        }
    }

    //  頂点シェーダの生成
    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 = CompileShaderFromMemory((BYTE*)shadercode,sizeof(shadercode),"PSFuncNoTex","ps_4_0",&pShader);
    if (FAILED(hr))
        return hr;
    hr = m_pDevice->CreatePixelShader(pShader->GetBufferPointer(),pShader->GetBufferSize(),NULL,&m_pPixelShaderNoTex);
    SAFE_RELEASE(pShader);
    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;

    }
    // 頂点バッファの設定.
    {
        // 頂点の定義.
        SpriteVertex 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( SpriteVertex ) * 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( SpriteConstantBuffer );
        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;
    }

    hr = S_OK;
    return hr;
}
//
//  Release device dependent objects.
//
HRESULT CD3D11Sprite::ReleaseDeviceObjects(ID3D11DeviceContext *pContext){

    if (m_pDataContext){
        std::vector<SpriteTexture*>::iterator it;
        it = m_pDataContext->pSpriteTextures.begin();
        while (it != m_pDataContext->pSpriteTextures.end()){
            if (*it != NULL){
                SAFE_RELEASE((*it)->pTexture);
                SAFE_RELEASE((*it)->pTextureShaderResourceView);
            }
            ++it;
        }
    }
    SAFE_RELEASE(m_pDeviceContext);
    SAFE_RELEASE(m_pDevice);
    SAFE_RELEASE(m_pTextureSamplerState);
    SAFE_RELEASE(m_pVertexShader);
    SAFE_RELEASE(m_pPixelShader);
    SAFE_RELEASE(m_pPixelShaderNoTex);
    SAFE_RELEASE(m_pInputLayout);
    SAFE_RELEASE(m_pBlendState);
    SAFE_RELEASE(m_pVertexBuffer);
    SAFE_RELEASE(m_pConstantBuffer);

    return S_OK;
}

//
//  method : SetTexture
//  @param:
//      no : texture no
//      pFilename : filename
//
void CD3D11Sprite::SetTexture(INT no, TCHAR *pFilename){
    int count = m_pDataContext->pSpriteTextures.size();
    int len;
    SpriteTexture *pTextureNode;
    if (no >= count){
        int add = count - no + 1;
        for ( int i = 0; i < add ; ++i){
            m_pDataContext->pSpriteTextures.push_back(NULL);
        }
    }
    pTextureNode = m_pDataContext->pSpriteTextures[no];
    if (pTextureNode == NULL){
        pTextureNode = new SpriteTexture;
        m_pDataContext->pSpriteTextures[no] = pTextureNode;
    }else{
        SAFE_DELETE_ARRAY(pTextureNode->pFilename);
        SAFE_RELEASE(pTextureNode->pTexture);
        SAFE_RELEASE(pTextureNode->pTextureShaderResourceView);
    }
    len = _tcslen(pFilename) + 1;
    len = (len + 3)&0xfffffffc;
    pTextureNode->pFilename = new TCHAR[len];
    _tcscpy_s(pTextureNode->pFilename,len,pFilename);
}

INT CD3D11Sprite::GetNumTextures(){
    INT num = 0;
    if (m_pDataContext){
        num = m_pDataContext->pSpriteTextures.size();
    }
    return num;
}

//
//  method : Render
//  @param : 
//      pContext : D3D11 context
//      x : position - x
//      y : position - y
//      w : sprite width
//      h : sprire height
//      no : texture no
//
void    CD3D11Sprite::Render(ID3D11DeviceContext *pContext, FLOAT x, FLOAT y, FLOAT w, FLOAT h, INT no){
    Render(pContext,x,y,w,h,0.0f,0.0f,FLT_MAX,FLT_MAX,no);
}

//
//  method : Render
//  @param : 
//      pContext : D3D11 context
//      x : position - x
//      y : position - y
//      w : sprite width
//      h : sprire height
//      tx : texture-coord.x
//      ty : texture-coord.y
//      tw : texture width
//      th : texture height
//      no : texture no
//
void    CD3D11Sprite::Render(ID3D11DeviceContext *pContext, FLOAT x, FLOAT y, FLOAT w, FLOAT h,
                        FLOAT tx, FLOAT ty, FLOAT tw, FLOAT th, INT no){

    SpriteTexture            *pSpriteTexture = NULL;
    ID3D11Texture2D            *pTexture = NULL;
    ID3D11ShaderResourceView *pTextureShaderResourceView = NULL;

    if (m_pDataContext == NULL)
        return;

    if (no >= 0 && no < (INT)m_pDataContext->pSpriteTextures.size()){
        pSpriteTexture = m_pDataContext->pSpriteTextures[no];
        if (pSpriteTexture != NULL){
            pTexture = pSpriteTexture->pTexture;
            pTextureShaderResourceView = pSpriteTexture->pTextureShaderResourceView;
        }
    }
    if (pSpriteTexture == NULL)
        return;

    // シェーダを設定して描画.
    pContext->VSSetShader( m_pVertexShader, NULL, 0 );
    pContext->GSSetShader( NULL,            NULL, 0 );
    if (pTextureShaderResourceView == NULL){
        pContext->PSSetShader( m_pPixelShaderNoTex,  NULL, 0 );    //  テクスチャ無し
    }else{
        pContext->PSSetShader( m_pPixelShader,  NULL, 0 );        //  テクスチャ有り
    }

    // 定数バッファの設定.
    SpriteConstantBuffer cb;
    cb.matProj  = m_matProj;
    cb.color = m_vecDiffuse;

    // サブリソースを更新.
    pContext->UpdateSubresource( m_pConstantBuffer, 0, NULL, &cb, 0, 0 );

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

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

    // 頂点バッファの設定.
    {
        D3D11_VIEWPORT  vp;
        UINT            uiNumViewport = 1;
        m_pDeviceContext->RSGetViewports(&uiNumViewport,&vp);
        if (uiNumViewport != 1)
            return;
        //  transform 2D -> clipping space
        FLOAT l = x;
        FLOAT t = y;
        FLOAT r = l + w;
        FLOAT b = t + h;
        FLOAT z = 1.0f;
        FLOAT tx1, ty1;
        FLOAT tx2, ty2;

        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;

        tx1 = ty1 = 0.0f;
        tx2 = ty2 = tx1;

        if (pTexture != NULL){
            D3D11_TEXTURE2D_DESC desc;
            FLOAT texW, texH;
            pTexture->GetDesc(&desc);
            texW = (FLOAT)desc.Width;
            texH = (FLOAT)desc.Height;
            tx1 = tx / texW;
            ty1 = ty / texH;
            if (tw == FLT_MAX){
                tx2 = (FLOAT)pSpriteTexture->dwSrcWidth / texW;
                ty2 = (FLOAT)pSpriteTexture->dwSrcHeight / texH;
            }else{
                tx2 = tx1 + tw / texW;
                ty2 = ty1 + th / texH;
            }
        }

        // 頂点の定義.
        SpriteVertex 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 );
        
    }
    // 入力アセンブラに頂点バッファを設定.
    UINT stride = sizeof( SpriteVertex );
    UINT offset = 0;
    pContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

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

    ID3D11ShaderResourceView* ppShaderResourceViews[] = { 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);

    //  ブレンドステートを元に戻す
    pContext->OMSetBlendState( NULL, blendFactor, 0xffffffff );
}

//
//  Set diffuse color.
//
void    CD3D11Sprite::SetDiffuse(FLOAT r, FLOAT g, FLOAT b, FLOAT a){
    m_vecDiffuse.x = r;
    m_vecDiffuse.y = g;
    m_vecDiffuse.z = b;
    m_vecDiffuse.w = a;
}

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

HRESULT CD3D11Sprite::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;
}



クラス CTextureLoader

【TextureLoader.h】

#pragma once
struct IWICImagingFactory;
class CTextureLoader
{
private:
    CTextureLoader(void);
    virtual ~CTextureLoader(void);

public:
    static void Initialize();
    static CTextureLoader *GetInstance();
    static void Destroy();
    static HRESULT CreateTextureFromFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight);
protected:
    IWICImagingFactory *m_pFactory;
private:
    static CTextureLoader *m_pInstance;
};



【TextureLoader.cpp】

//
//  class CTextureLoader
//
//  Desc : This program loads images via 
//      WIC ( Windows Imaging Component ) and 
//      creates 2D Textures
//
#include "stdafx.h"
#include <stdio.h>
#include <D3D11.h>
#include <D2D1.h>
#include <ddraw.h>
#include <wincodec.h>
#include "TextureLoader.h"
#include "ddsfunctions.h"
#include "tgafunctions.h"

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


CTextureLoader *CTextureLoader::m_pInstance = NULL;

CTextureLoader::CTextureLoader(void)
{
    HRESULT hr = CoCreateInstance(
        CLSID_WICImagingFactory,
        nullptr,
        CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&m_pFactory)
        );
}


CTextureLoader::~CTextureLoader(void)
{
    if (m_pFactory != NULL){
        m_pFactory->Release();
        m_pFactory = NULL;
    }
    //SAFE_RELEASE(m_pFactory);
}

void CTextureLoader::Initialize(){
    if (m_pInstance != NULL)
        return;
    m_pInstance = new CTextureLoader();
}

CTextureLoader *CTextureLoader::GetInstance(){
    if (m_pInstance == NULL){
        Initialize();
    }
    return m_pInstance;
}

void CTextureLoader::Destroy(){

    if (m_pInstance != NULL){
        delete m_pInstance;
        m_pInstance = NULL;
    }
}
//
//  function CopyBitmapSourceToTexture2D
//    @param :
//      pContext : Device's context
//      pBitmapSource   : BitmapSource to copy
//      pTexture : The Texture to copy to
//      stride   : Texture's vertical stride
//      size     : Texture's size
//
HRESULT CopyBitmapSourceToTexture2D(ID3D11DeviceContext *pContext, IWICBitmapSource *pBitmapSource, ID3D11Texture2D *pTexture, UINT stride, UINT size){
    D3D11_MAPPED_SUBRESOURCE hMappedResource;
    HRESULT hr;
    hr = pContext->Map( 
        pTexture,
        0,
        D3D11_MAP_WRITE_DISCARD,
        0,
        &hMappedResource );
    if (SUCCEEDED(hr)){
        // ここで書き込む
        BYTE* pBits = (BYTE*)hMappedResource.pData;
        hr = pBitmapSource->CopyPixels(NULL,stride, size, pBits);
        pContext->Unmap(pTexture,0);
    }
    return hr;
}

//
//  method: CreateTextureFromFile
//    @param :
//      pContext  : (in)Device's context
//      pFilename : (in)pathname of the image file
//      ppTexture : (out) Load result
//      pSrcWidth : (out) width of the source image  ( != texture width )
//      pSrcHight : (out)  height of the source image ( != texture height )
//
//   @return
//      S_OK : succeeded
//
HRESULT CTextureLoader::CreateTextureFromFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight){
    IWICBitmapDecoder *pDecoder = NULL;
    IWICBitmapFrameDecode *pFrame = NULL;
    WICPixelFormatGUID pixelFormat;
    ID3D11Texture2D *pOutput = NULL;
    ID3D11Device *pDevice = NULL;
    //IWICImagingFactory *pFactory;
    HRESULT hr;

    //  Check if TGA
    int len = _tcslen(pFilename);
    if (len > 3){
        TCHAR *pTale = pFilename;
        pTale = pFilename + (len - 4);
#ifdef _TARGA_SUPPORTED_
        if (0 == _tcsicmp(pTale,_T(".tga"))){
            return CreateTextureFromTgaFile(pContext,pFilename,ppTexture,pSrcWidth,pSrcHeight);
        }
#endif
#ifdef _DDS_SUPPORTED_
        if (0 == _tcsicmp(pTale,_T(".dds"))){
            //  create texture from dds file
            return CreateTextureFromDdsFile(pContext,pFilename,ppTexture,pSrcWidth,pSrcHeight);
        }
#endif
    }

    //  create texture using WIC
    CTextureLoader *pInstance = GetInstance();


    hr = pInstance->m_pFactory->CreateDecoderFromFilename(pFilename,0,
        GENERIC_READ,WICDecodeMetadataCacheOnDemand,&pDecoder);
    if (FAILED(hr))
        goto ERROR_EXIT;
    hr = pDecoder->GetFrame(0,&pFrame);
    if (FAILED(hr))
        goto ERROR_EXIT;

    UINT width, height;
    pFrame->GetSize(&width, &height);

    //  テクスチャの生成
    D3D11_TEXTURE2D_DESC td;
    UINT texWidth = 4, texHeight = 4;
    while(texWidth < width)
        texWidth <<= 1;
    while(texHeight < height)
        texHeight <<= 1;
    
    ZeroMemory( &td, sizeof( D3D11_TEXTURE2D_DESC ) );
    td.Width                = texWidth;
    td.Height               = texHeight;
    td.MipLevels            = 1;
    td.ArraySize            = 1;
    td.Format               = DXGI_FORMAT_B8G8R8A8_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;

    pContext->GetDevice(&pDevice);
    hr = pDevice->CreateTexture2D(&td,NULL,&pOutput);
    if (FAILED(hr))
        goto ERROR_EXIT;

    //  読み込んだ画像のピクセルフォーマットを取得
    hr = pFrame->GetPixelFormat(&pixelFormat);
    if (FAILED(hr))
        goto ERROR_EXIT;
    
    if (pixelFormat != GUID_WICPixelFormat32bppBGRA){
        IWICFormatConverter *pFC;
        hr = m_pInstance->m_pFactory->CreateFormatConverter(&pFC);
        if (FAILED(hr))
            goto ERROR_EXIT;
        
        //  画像変換の用意
        hr = pFC->Initialize(pFrame,GUID_WICPixelFormat32bppBGRA, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
        if (FAILED(hr)){
            SAFE_RELEASE(pFC);
            goto ERROR_EXIT;
        }
        //  テクスチャに流し込み
        CopyBitmapSourceToTexture2D(pContext,pFC,pOutput, 4*texWidth, 4 * texWidth* texHeight );
        SAFE_RELEASE(pFC);
    }else{
        //  変換不要な時
        CopyBitmapSourceToTexture2D(pContext,pFrame,pOutput, 4*texWidth, 4 * texWidth* texHeight );
    }
ERROR_EXIT:
    SAFE_RELEASE(pDevice);
    if (FAILED(hr)){
        SAFE_RELEASE(pOutput);
    }else{
        *ppTexture = pOutput;
        *pSrcWidth = width;
        *pSrcHeight = height;
    }
    SAFE_RELEASE(pFrame);
    SAFE_RELEASE(pDecoder)
    return hr;
}



Targa ファイルモジュール

【tgafunctions.h】

#pragma once

//  Prototypes
HRESULT CreateTextureFromTgaFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight);

#define _TARGA_SUPPORTED_



【tgafunctions.cpp】

//
//  TrueVision Targa format module
//
#include "stdafx.h"
#include <stdio.h>
#include <D3D11.h>
#include <D2D1.h>
#include <ddraw.h>
#include <wincodec.h>
#include "tgafunctions.h"

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

//
//  prototypes
//
HRESULT CopyTgaSourceToTexture2D(ID3D11DeviceContext *pContext, ID3D11Texture2D *pTexture, DWORD *pSource, UINT width, UINT height, UINT pitch, BYTE flags);
HRESULT DecodeTgaHeader(BYTE *pHeader, int *pPixelBits, BOOL *pRLE, BOOL *pBW, DWORD *pSrcWidth, DWORD *pSrcHeight, BYTE *pFlags);
HRESULT ConvertPixelsFromTgaFile(FILE *fp,DWORD *pBuffer, DWORD numPixels, BOOL bRLE, BOOL bBW, INT numBitsPerPixel);

//
//  function CreateTextureFromTgaFile
//    @param :
//      pContext  : (in)Device's context
//      pFilename : (in)pathname of the image file
//      ppTexture : (out) Load result
//      pSrcWidth : (out) width of the source image  ( != texture width )
//      pSrcHight : (out)  height of the source image ( != texture height )
//
HRESULT CreateTextureFromTgaFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight){
    FILE *fp = NULL;
    errno_t err;
    unsigned char header[256];
    DWORD srcwidth,srcheight;
    int pixelbits, row_pitch;
    BOOL    bRLE = false, bBW = false;
    DWORD    *pBuffer = NULL;
    int        num_elements = 0;
    ID3D11Device *pDevice = NULL;
    ID3D11Texture2D *pOutput = NULL;
    HRESULT    hr = E_FAIL;
    int idlength;
    BYTE src_descriptor;

    err = _tfopen_s(&fp,pFilename,_T("rb"));

    if (fp== NULL)
        goto ERROR_EXIT;

    //  read the header;
    fread_s(header,sizeof(header),1,1,fp);
    idlength = ((int)header[0]) & 255;
    if (idlength == 0)
        idlength = 18;
    fread_s(header+1,sizeof(header)-1,idlength-1,1,fp);

    hr = DecodeTgaHeader(header,&pixelbits,&bRLE,&bBW,&srcwidth,&srcheight, &src_descriptor);
    if (FAILED(hr)){
        goto ERROR_EXIT;
    }

    num_elements = srcwidth * srcheight;
    pBuffer = new DWORD[num_elements];
    row_pitch = srcwidth * sizeof(DWORD);

    //  convert pixels
    hr = ConvertPixelsFromTgaFile(fp,pBuffer,num_elements,bRLE,bBW,pixelbits);
    if (FAILED(hr))
        goto ERROR_EXIT;

    //  create an texture
    D3D11_TEXTURE2D_DESC td;
    UINT texWidth = 4, texHeight = 4;
    while(texWidth < srcwidth)
        texWidth <<= 1;
    while(texHeight < srcheight)
        texHeight <<= 1;
    
    ZeroMemory( &td, sizeof( D3D11_TEXTURE2D_DESC ) );
    td.Width                = texWidth;
    td.Height               = texHeight;
    td.MipLevels            = 1;
    td.ArraySize            = 1;
    td.Format               = DXGI_FORMAT_B8G8R8A8_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;

    pContext->GetDevice(&pDevice);
    hr = pDevice->CreateTexture2D(&td,NULL,&pOutput);
    if (FAILED(hr))
        goto ERROR_EXIT;

    SAFE_RELEASE(pDevice);

    //  copy bits
    hr = CopyTgaSourceToTexture2D(pContext,pOutput,pBuffer,srcwidth,srcheight,row_pitch, src_descriptor);
    if (FAILED(hr))
        goto ERROR_EXIT;
    *pSrcWidth = srcwidth;
    *pSrcHeight = srcheight;
    *ppTexture = pOutput;
    pOutput = NULL;

ERROR_EXIT:
    if (fp != NULL)
        fclose(fp);

    SAFE_RELEASE(pOutput);
    SAFE_RELEASE(pDevice);
    SAFE_DELETE_ARRAY(pBuffer);
    
    return hr;
}

//
//  Decode TGA header
//  @param:
//      pHeader : (in)17 byte header
//      pPixelBits : (out)bits per pixel
//      pRLE    : (out) is run length encoding
//      pBW     : (out) is black and white
//      pSrcWidth  : (out) width of source image.
//      pSrcHeight : (out) height of source image.
//
HRESULT    DecodeTgaHeader(BYTE *pHeader, int *pPixelBits, BOOL *pRLE, BOOL *pBW, DWORD *pSrcWidth, DWORD *pSrcHeight,BYTE *pFlags){

    BOOL    bRLE = false, bBW = false;
    DWORD srcwidth,srcheight;
    int pixelbits;

    switch(pHeader[2] & 0xff){
    case    0:
    case    1:
    case    9:
        return E_FAIL;
    case    2:
        break;
    case    3:
        bBW = true;
        break;
    case    11:
        bBW = true;
    case    10:
        bRLE = true;
        break;
    }
    if (pHeader[1] != 0){
        //  we don't support color maps
        return E_FAIL;
    }

    //  picture size
    srcwidth  = ((DWORD)(*(unsigned short*)(pHeader+12)))&0xffffL;
    srcheight = ((DWORD)(*(unsigned short*)(pHeader+14)))&0xffffL;

    pixelbits = ((int)(pHeader[16])) & 0xff;
    *pRLE = bRLE;
    *pBW = bBW;
    *pSrcWidth = srcwidth;
    *pSrcHeight = srcheight;
    *pPixelBits = pixelbits;
    *pFlags = pHeader[17];

    return S_OK;
}

//
//  Convert pixels from TGA file
//  @param:
//      fp : FILE pointer
//      pBuffer : (in-out) target buffer
//      numPixels : (in) number of pixels
//      bRLE      : (in) iss run length encoding active
//      bBW       : (in) is black and white
//      numBitsPerPixel : (in) number of bits per pixel
//      flags     : (in) tga's descriptor
//
HRESULT ConvertPixelsFromTgaFile(FILE *fp,DWORD *pBuffer, DWORD numPixels, BOOL bRLE, BOOL bBW, INT numBitsPerPixel){
    DWORD    current = 0;
    int r, g, b, a;
    if (!bRLE){  //  without run length encoding
        DWORD current = 0;
        if (bBW){
            BYTE pixel;
            if (numBitsPerPixel != 8)
                return E_FAIL;
            while(current < numPixels){
                if (1!= fread_s((void*)&pixel,1,1,1,fp))
                    return E_FAIL;
                r = pixel & 255;
                b = g = r;
                a = 255;
                pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
            }
        }else{
            switch(numBitsPerPixel){
            case    8:
                return E_FAIL;
            case    16:
                while(current < numPixels){
                    USHORT    pixel;
                    if (1!= fread_s((void*)&pixel,2,2,1,fp))
                        return E_FAIL;
                    r = (((pixel >> 10) & 0x1f)*255)/31;
                    g = (((pixel >> 5 ) & 0x1f)*255)/31;
                    b = ((pixel & 0x1f) * 255) / 31;
                    a = ((pixel >> 15 ) & 0x1) * 255;
                    pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
                }
                break;
            case    24:
                while(current < numPixels){
                    DWORD pixel = 0;
                    if (1!= fread_s((void*)&pixel,4,3,1,fp))
                        return E_FAIL;
                    r = (pixel >> 16) & 255;
                    g = (pixel >> 8) & 255;
                    b = pixel & 255;
                    a = 255;
                    pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
                }
                break;
            case    32:
                while(current < numPixels){
                    DWORD pixel;
                    if (1!= fread_s((void*)&pixel,4,4,1,fp))
                        return E_FAIL;
                    r = (pixel >> 16) & 255;
                    g = (pixel >> 8) & 255;
                    b = pixel & 255;
                    a = (pixel >> 24) & 255;
                    pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
                }
                break;
            }
        }
    }else{    //  with run length encodings.
        BYTE    byte;
        int repeat;
        DWORD    targetPixel;
        if (bBW){
            BYTE pixel;
            if (numBitsPerPixel != 8)
                return E_FAIL;
            while(current < numPixels){
                if (1!= fread_s((void*)&byte,1,1,1,fp))
                    return E_FAIL;
                repeat = byte & 0x7f;
                ++repeat;
                if (byte & 0x80){
                    if (1!= fread_s((void*)&pixel,1,1,1,fp))
                        return E_FAIL;
                    r = pixel & 255;
                    b = g = r;
                    a = 255;
                    targetPixel = (a << 24) + (r << 16) + (g << 8) + b;
                    for (int i = 0; i < repeat && current < numPixels; ++i){
                        pBuffer[current++] = targetPixel;
                    }
                }else{
                    for (int i = 0; i < repeat && current < numPixels; ++i){
                        if (1!= fread_s((void*)&pixel,1,1,1,fp))
                            return E_FAIL;
                        r = pixel & 255;
                        b = g = r;
                        a = 255;
                        pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
                    }
                }
            }
        }else{
            switch(numBitsPerPixel){
            case    8:
                return E_FAIL;
            case    16:
                while(current < numPixels){
                    USHORT    pixel;
                    if (1!= fread_s((void*)&byte,1,1,1,fp))
                        return E_FAIL;
                    repeat = byte & 0x7f;
                    ++repeat;
                    if (byte & 0x80){
                        if (1!= fread_s((void*)&pixel,2,2,1,fp))
                            return E_FAIL;
                        r = (((pixel >> 10) & 0x1f)*255)/31;
                        g = (((pixel >> 5 ) & 0x1f)*255)/31;
                        b = ((pixel & 0x1f) * 255) / 31;
                        a = ((pixel >> 15 ) & 0x1) * 255;
                        targetPixel = (a << 24) + (r << 16) + (g << 8) + b;
                        for (int i = 0; i < repeat && current < numPixels; ++i){
                            pBuffer[current++] = targetPixel;
                        }
                    }else{
                        for (int i = 0; i < repeat && current < numPixels; ++i){
                            if (1!= fread_s((void*)&pixel,2,2,1,fp))
                                return E_FAIL;
                            r = (((pixel >> 10) & 0x1f)*255)/31;
                            g = (((pixel >> 5 ) & 0x1f)*255)/31;
                            b = ((pixel & 0x1f) * 255) / 31;
                            a = ((pixel >> 15 ) & 0x1) * 255;
                            pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
                        }
                    }
                }
                break;
            case    24:
                while(current < numPixels){
                    DWORD pixel = 0;
                    if (1!= fread_s((void*)&byte,1,1,1,fp))
                        return E_FAIL;
                    repeat = byte & 0x7f;
                    ++repeat;
                    if (byte & 0x80){
                        if (1!= fread_s((void*)&pixel,4,3,1,fp))
                            return E_FAIL;
                        r = (pixel >> 16) & 255;
                        g = (pixel >> 8) & 255;
                        b = pixel & 255;
                        a = 255;
                        targetPixel = (a << 24) + (r << 16) + (g << 8) + b;
                        for (int i = 0; i < repeat && current < numPixels; ++i){
                            pBuffer[current++] = targetPixel;
                        }
                    }else{
                        for (int i = 0; i < repeat && current < numPixels; ++i){
                            if (1!= fread_s((void*)&pixel,4,3,1,fp))
                                return E_FAIL;
                            r = (pixel >> 16) & 255;
                            g = (pixel >> 8) & 255;
                            b = pixel & 255;
                            a = 255;
                            pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
                        }
                    }
                }
                break;
            case    32:
                while(current < numPixels){
                    DWORD pixel;
                    if (1!= fread_s((void*)&byte,1,1,1,fp))
                        return E_FAIL;
                    repeat = byte & 0x7f;
                    ++repeat;
                    if (byte & 0x80){
                        if (1!= fread_s((void*)&pixel,4,4,1,fp))
                            return E_FAIL;
                        r = (pixel >> 16) & 255;
                        g = (pixel >> 8) & 255;
                        b = pixel & 255;
                        a = (pixel >> 24) & 255;
                        targetPixel = (a << 24) + (r << 16) + (g << 8) + b;
                        for (int i = 0; i < repeat && current < numPixels; ++i){
                            pBuffer[current++] = targetPixel;
                        }
                    }else{
                        for (int i = 0; i < repeat && current < numPixels; ++i){
                            if (1!= fread_s((void*)&pixel,4,4,1,fp))
                                return E_FAIL;
                            r = (pixel >> 16) & 255;
                            g = (pixel >> 8) & 255;
                            b = pixel & 255;
                            a = (pixel >> 24) & 255;
                            pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
                        }
                    }
                }
                break;
            }
        }
    }
    return S_OK;
}

//
//  function CopyTgaSourceToTexture2D
//    @param :
//      pContext : Device's context
//      pTexture : The Texture to copy to
//      pSource  : Source to copy
//      width    : width of source image
//      height   : height of source image
//      flags    : tga flags
//
HRESULT CopyTgaSourceToTexture2D(ID3D11DeviceContext *pContext, ID3D11Texture2D *pTexture, DWORD *pSource, UINT width, UINT height, UINT pitch, BYTE flags){
    D3D11_MAPPED_SUBRESOURCE hMappedResource;
    HRESULT hr;
    D3D11_TEXTURE2D_DESC td;
    BYTE *pRawSource = (BYTE*)pSource;

    pTexture->GetDesc(&td);
    hr = pContext->Map( 
        pTexture,
        0,
        D3D11_MAP_WRITE_DISCARD,
        0,
        &hMappedResource );
    if (SUCCEEDED(hr)){
        // ここで書き込む
        BYTE* pBits = (BYTE*)hMappedResource.pData;

        UINT    x, y;
        INT sourceX=0, sourceY=0;
        int diffX=1, diffY=1;
        INT    x2;
        if (flags&0x10){
            diffX = -1;
            sourceX = width-1;
        }
        if (0 == (flags&0x20)){
            sourceY = height - 1;
            diffY = -1;
        }

        for(y=0; y < height; y++ )
        {
            DWORD* pDst32 = (DWORD*)(pBits+(y * hMappedResource.RowPitch));
            x2 = sourceX;
            for(x = 0; x < width; x++ )
            {
                *pDst32++ = *((DWORD*)(pRawSource+(x2*sizeof(DWORD))+(sourceY * pitch)));
                x2 += diffX;
            }
            while(x < td.Width){
                *pDst32++ = 0L;
                ++x;
            }
            sourceY += diffY;
        }
        while( y < td.Height){
            DWORD* pDst32 = (DWORD*)(pBits+(y * hMappedResource.RowPitch));
            for(x = 0; x < td.Width; x++ )
            {
                *pDst32++ = 0L;
            }
            ++y;
        }
        pContext->Unmap(pTexture,0);
    }
    return hr;
}



DDS ファイルモジュール

【ddsfunctions.h】

#pragma once

//
//prototypes 
//
HRESULT CreateTextureFromDdsFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight);

#define _DDS_SUPPORTED_




【ddsfunctions.cpp】

//
//  DDS file format module
//
//  Cube map is not supported now
//
#include "stdafx.h"
#include <stdio.h>
#include <D3D11.h>
#include <D2D1.h>
#include <ddraw.h>
#include <wincodec.h>

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

//
//  prototypes.
//
DXGI_FORMAT    GetCompressedPixelFormatFromDdsHeader(DDSURFACEDESC2 *pddsc);
HRESULT CreateTextureFromDdsRgbImage(ID3D11DeviceContext *pContext, DDSURFACEDESC2 *pddsc, VOID *pBuffer, ID3D11Texture2D **ppTexture);
HRESULT CreateTextureFromDdsLinearImage(ID3D11DeviceContext *pContext, DDSURFACEDESC2 *pddsc, DXGI_FORMAT fmt, VOID *pBuffer, DWORD dwLinearSize, ID3D11Texture2D **ppTexture);

//
//  function CreateTextureFromDdsFile
//    @param :
//      pContext  : (in)Device's context
//      pFilename : (in)pathname of the image file
//      ppTexture : (out) Load result
//      pSrcWidth : (out) width of the source image  ( != texture width )
//      pSrcHight : (out)  height of the source image ( != texture height )
//
HRESULT CreateTextureFromDdsFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight){
    FILE *fp = NULL;
    errno_t err;
    unsigned char header[256];
    DWORD    *pBuffer = NULL;
    ID3D11Texture2D *pOutput = NULL;
    HRESULT    hr = E_FAIL;
    int idlength;
    DDSURFACEDESC2    *pddsc = NULL;
    DWORD        dwLinearSize = 0L;
    DXGI_FORMAT    texFormat = DXGI_FORMAT_UNKNOWN;

    err = _tfopen_s(&fp,pFilename,_T("rb"));

    if (fp== NULL)
        goto ERROR_EXIT;

    //  read the header;
    fread_s(header,sizeof(header),4,1,fp);
    if (*(DWORD*)header != 0x20534444L)    //  check FOURCC "DDS "
        goto ERROR_EXIT;

    fread_s(header,sizeof(header),1,1,fp);
    idlength = ((int)header[0]) & 255;
    if (idlength != 0x7c)
        goto ERROR_EXIT;
    fread_s(header+1,sizeof(header)-1,idlength-1,1,fp);

    pddsc = (DDSURFACEDESC2*)header;

    if (pddsc->dwFlags & DDSD_PITCH){
        dwLinearSize = (DWORD)pddsc->lPitch;
        dwLinearSize *= pddsc->dwHeight;
        pBuffer = new DWORD[(dwLinearSize+3) >> 2];
        fread((void*)pBuffer,1,dwLinearSize, fp);
        hr = CreateTextureFromDdsRgbImage(pContext,pddsc,pBuffer,&pOutput);
        if (SUCCEEDED(hr)){
            *pSrcWidth = pddsc->dwWidth;
            *pSrcHeight = pddsc->dwHeight;
            *ppTexture = pOutput;
            pOutput = NULL;
        }
    }else if (pddsc->dwFlags & DDSD_LINEARSIZE){
        dwLinearSize = (DWORD)pddsc->dwLinearSize;
        texFormat = GetCompressedPixelFormatFromDdsHeader(pddsc);
        if (texFormat == DXGI_FORMAT_UNKNOWN){
            goto ERROR_EXIT;
        }
        pBuffer = new DWORD[(dwLinearSize+3) >> 2];
        fread((void*)pBuffer,1,dwLinearSize, fp);
        
        hr = CreateTextureFromDdsLinearImage(pContext,pddsc,texFormat,pBuffer,dwLinearSize,&pOutput);

        SAFE_DELETE_ARRAY(pBuffer);
        if (FAILED(hr))
            goto ERROR_EXIT;

        *pSrcWidth = pddsc->dwWidth;
        *pSrcHeight = pddsc->dwHeight;
        *ppTexture = pOutput;
        pOutput = NULL;

    }else if ((pddsc->dwFlags & DDSD_WIDTH) && (pddsc->dwFlags & DDSD_HEIGHT)){
        //  no pitch no linear size
        texFormat = GetCompressedPixelFormatFromDdsHeader(pddsc);
        if (texFormat != DXGI_FORMAT_UNKNOWN){

            //  compressed format
            switch(texFormat){
            case    DXGI_FORMAT_BC1_UNORM:
                dwLinearSize = pddsc->dwWidth * pddsc->dwHeight;
                dwLinearSize = (dwLinearSize+1) >> 1;
                break;
            case    DXGI_FORMAT_BC2_UNORM:
                dwLinearSize = pddsc->dwWidth * pddsc->dwHeight;
                break;
            case    DXGI_FORMAT_BC3_UNORM:
                dwLinearSize = pddsc->dwWidth * pddsc->dwHeight;
                break;
            default:
                goto ERROR_EXIT;
            }
            pBuffer = new DWORD[(dwLinearSize+3) >> 2];
            fread((void*)pBuffer,1,dwLinearSize, fp);

            hr = CreateTextureFromDdsLinearImage(pContext,pddsc,texFormat,pBuffer,dwLinearSize,&pOutput);

            SAFE_DELETE_ARRAY(pBuffer);
            if (FAILED(hr))
                goto ERROR_EXIT;

            *pSrcWidth = pddsc->dwWidth;
            *pSrcHeight = pddsc->dwHeight;
            *ppTexture = pOutput;
            pOutput = NULL;

        }else{

            //  uncompressed format

            DWORD pixelSize = pddsc->ddpfPixelFormat.dwRGBBitCount;
            pixelSize = (pixelSize + 7) >> 3;    //  byte size.

            dwLinearSize = pixelSize * pddsc->dwWidth * pddsc->dwHeight;
            pBuffer = new DWORD[(dwLinearSize+3) >> 2];
            fread((void*)pBuffer,1,dwLinearSize, fp);
            hr = CreateTextureFromDdsRgbImage(pContext,pddsc,pBuffer,&pOutput);
            if (SUCCEEDED(hr)){
                *pSrcWidth = pddsc->dwWidth;
                *pSrcHeight = pddsc->dwHeight;
                *ppTexture = pOutput;
                pOutput = NULL;
            }
        }
        
    }else
        goto ERROR_EXIT;    //  can't calculate the size

ERROR_EXIT:
    if (fp != NULL)
        fclose(fp);
    
    SAFE_RELEASE(pOutput);
    SAFE_DELETE_ARRAY(pBuffer);

    return hr;
}

//
//  Create texture from DDS linear image
//  @param
//      pContext : (in) Device's context
//      pddsc     : (in) pointer to the direct draw surface
//      fmt      : (in) pixel format
//      pBuffer  : (in) image buffer
//      dwLinearSize : (in) image data size
//      ppTexture : (out) result texture.
//
HRESULT CreateTextureFromDdsLinearImage(ID3D11DeviceContext *pContext, DDSURFACEDESC2 *pddsc, DXGI_FORMAT fmt, VOID *pBuffer, DWORD dwLinearSize, ID3D11Texture2D **ppTexture){
    HRESULT  hr = E_FAIL;
    D3D11_TEXTURE2D_DESC     td;
    D3D11_MAPPED_SUBRESOURCE hMappedResource;
    ID3D11Device     *pDevice = NULL;
    ID3D11Texture2D  *pOutput = NULL;

    ZeroMemory( &td, sizeof( D3D11_TEXTURE2D_DESC ) );
    td.Width                = pddsc->dwWidth;
    td.Height               = pddsc->dwHeight;
    td.MipLevels            = (pddsc->dwFlags&DDSD_MIPMAPCOUNT)?pddsc->dwMipMapCount:1;
    td.ArraySize            = 1;
    td.Format               = fmt;
    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;        

    pContext->GetDevice(&pDevice);

    hr = pDevice->CreateTexture2D(&td,NULL,&pOutput);

    if (SUCCEEDED(hr)){
        hr = pContext->Map( 
            pOutput,
            0,
            D3D11_MAP_WRITE_DISCARD,
            0,
            &hMappedResource );
        if (SUCCEEDED(hr)){
            memcpy(hMappedResource.pData,pBuffer,dwLinearSize);

            pContext->Unmap(pOutput,0);        
            *ppTexture = pOutput;
            pOutput = NULL;
        }
    }
    SAFE_RELEASE(pOutput);
    SAFE_RELEASE(pDevice);
    return hr;
}

//
//  Get compressed pixel format from DDS Header
//  @param
//      pddsc : Direct Draw Surface Desc
//  @return
//      DXGI_FORMAT
//  Note.
//      if the format is uncompressed format returns DXGI_FORMAT_UNKNOWN
//
DXGI_FORMAT    GetCompressedPixelFormatFromDdsHeader(DDSURFACEDESC2 *pddsc){
    DXGI_FORMAT    format = DXGI_FORMAT_UNKNOWN;

    if (pddsc->ddpfPixelFormat.dwFlags & DDPF_FOURCC){
        switch(pddsc->ddpfPixelFormat.dwFourCC){
        case    FOURCC_DXT1:
            format = DXGI_FORMAT_BC1_UNORM;
            break;
        case    FOURCC_DXT2:
        case    FOURCC_DXT3:
            format = DXGI_FORMAT_BC2_UNORM;
            break;
        case    FOURCC_DXT4:
        case    FOURCC_DXT5:
            format = DXGI_FORMAT_BC3_UNORM;
            break;
        }
    }
    return format;
}

//
//  function CreateTextureFromDdsRgbImage
//  @param
//      pContext  : (in)Device's context
//      pddsc     : (in)direct draw surface desc
//      pBuffer   : (in)image data
//      ppTexture : (out) Load result
//
//  Note:
//      Create texture and put image with uncompressed format.
//      converting pixel formats to DXGI_FORMAT_B8G8R8A8_UNORM
//
HRESULT CreateTextureFromDdsRgbImage(ID3D11DeviceContext *pContext, DDSURFACEDESC2 *pddsc, VOID *pBuffer, ID3D11Texture2D **ppTexture){
    D3D11_TEXTURE2D_DESC    td;
    DWORD texWidth = 4;
    DWORD texHeight = 4;
    HRESULT hr = E_FAIL;
    ID3D11Device *pDevice = NULL;
    ID3D11Texture2D *pOutput = NULL;
    D3D11_MAPPED_SUBRESOURCE hMappedResource;

    if (0 == (pddsc->ddpfPixelFormat.dwFlags & DDPF_RGB)){
        goto ERROR_EXIT;
    }
    while(texWidth < pddsc->dwWidth)
        texWidth <<= 1;

    while(texHeight < pddsc->dwHeight)
        texHeight <<= 1;
    
    ZeroMemory( &td, sizeof( D3D11_TEXTURE2D_DESC ) );
    td.Width                = texWidth;
    td.Height               = texHeight;
    td.MipLevels            = 1;
    td.ArraySize            = 1;
    td.Format               = DXGI_FORMAT_B8G8R8A8_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;
    pContext->GetDevice(&pDevice);
    pDevice->CreateTexture2D(&td,NULL,&pOutput);

    INT bitCount = (INT)pddsc->ddpfPixelFormat.dwRGBBitCount;
    hr = pContext->Map( 
        pOutput,
        0,
        D3D11_MAP_WRITE_DISCARD,
        0,
        &hMappedResource );
    if (FAILED(hr))
        goto ERROR_EXIT;
    hr = E_FAIL;

    int r, g, b, a;
    DWORD srcPitch;
    DWORD srcWidth  = pddsc->dwWidth;
    DWORD srcHeight = pddsc->dwHeight;
    DWORD x, y;
    if (pddsc->dwFlags & DDSD_PITCH){
        srcPitch = (DWORD)pddsc->lPitch;
    }else{
        DWORD pixelByte = (bitCount+7)>>3;
        srcPitch = (DWORD)pddsc->dwWidth * ((bitCount+7)>>3);
    }
    BYTE *pDest = (BYTE*)hMappedResource.pData;
    BYTE *pByte, *pSrc;

    switch(bitCount){
    case    32:
        //  A8R8G8B8  Just copy pixels
        if (   (pddsc->ddpfPixelFormat.dwRBitMask == 0x00ff0000L)
            && (pddsc->ddpfPixelFormat.dwGBitMask == 0x0000ff00L)
            && (pddsc->ddpfPixelFormat.dwBBitMask == 0x000000ffL)
            && (pddsc->ddpfPixelFormat.dwRGBAlphaBitMask == 0xff000000L)){
            //  A8R8G8B8
            for (y = 0; y < srcHeight ; ++y){
                pByte = pDest + (y * hMappedResource.RowPitch);
                pSrc = (BYTE*)pBuffer + (y * srcPitch);
                for (x = 0; x < srcWidth ; ++x){
                    *(DWORD*)pByte = *(DWORD*)pSrc;
                    pSrc  += sizeof(DWORD);
                    pByte += sizeof(DWORD);
                }
                while(x < texWidth){
                    *(DWORD*)pByte = 0L;
                    pByte += sizeof(DWORD);
                    ++x;
                }
            }
            while(y < texHeight){
                pByte = pDest + (y * hMappedResource.RowPitch);
                for (x = 0; x < texWidth ; ++x){
                    *(DWORD*)(pByte+sizeof(DWORD)*x) = 0L;
                }
                ++y;
            }
            hr = S_OK;
        }else if (   (pddsc->ddpfPixelFormat.dwRBitMask == 0x000000ffL)
            && (pddsc->ddpfPixelFormat.dwGBitMask == 0x0000ff00L)
            && (pddsc->ddpfPixelFormat.dwBBitMask == 0x00ff0000L)
            && (pddsc->ddpfPixelFormat.dwRGBAlphaBitMask == 0xff000000L)){
            //  A8B8G8R8 -> A8R8G8B8
            for (y = 0; y < srcHeight ; ++y){
                pByte = pDest + (y * hMappedResource.RowPitch);
                pSrc = (BYTE*)pBuffer + (y * srcPitch);
                for (x = 0; x < srcWidth ; ++x){
                    r = 0xff & (int)*pSrc++;
                    g = 0xff & (int)*pSrc++;
                    b = 0xff & (int)*pSrc++;
                    a = 0xff & (int)*pSrc++;
                    *(DWORD*)pByte = (a << 24)+(r << 16)+(g << 8) + b;
                    pByte += sizeof(DWORD);
                }
                while(x < texWidth){
                    *(DWORD*)pByte = 0L;
                    pByte += sizeof(DWORD);
                    ++x;
                }
            }
            while(y < texHeight){
                pByte = pDest + (y * hMappedResource.RowPitch);
                for (x = 0; x < texWidth ; ++x){
                    *(DWORD*)(pByte+sizeof(DWORD)*x) = 0L;
                }
                ++y;
            }
            hr = S_OK;
        }
        break;
    case    24:
        if (    (pddsc->ddpfPixelFormat.dwRBitMask == 0xff0000L)
            &&    (pddsc->ddpfPixelFormat.dwGBitMask == 0x00ff00L)
            &&    (pddsc->ddpfPixelFormat.dwBBitMask == 0x0000ffL)
        ){
            //  R8G8B8 -> A8R8G8B8
            for (y = 0; y < srcHeight ; ++y){
                pByte = pDest + (y * hMappedResource.RowPitch);
                pSrc = (BYTE*)pBuffer + (y * srcPitch);
                for (x = 0; x < srcWidth ; ++x){
                    b = 0xff & (int)*pSrc++;
                    g = 0xff & (int)*pSrc++;
                    r = 0xff & (int)*pSrc++;
                    a = 255;
                    *(DWORD*)pByte = (a << 24)+(r << 16)+(g << 8) + b;
                    pByte += sizeof(DWORD);
                }
                while(x < texWidth){
                    *(DWORD*)pByte = 0L;
                    pByte += sizeof(DWORD);
                    ++x;
                }
            }
            while(y < texHeight){
                pByte = pDest + (y * hMappedResource.RowPitch);
                for (x = 0; x < texWidth ; ++x){
                    *(DWORD*)(pByte+sizeof(DWORD)*x) = 0L;
                }
                ++y;
            }
            hr = S_OK;
        }
        break;
    case    16:
        if (    (pddsc->ddpfPixelFormat.dwRBitMask == 0x7c00L)
            &&    (pddsc->ddpfPixelFormat.dwGBitMask == 0x03e0L)
            &&    (pddsc->ddpfPixelFormat.dwBBitMask == 0x001fL)
            &&    (pddsc->ddpfPixelFormat.dwRGBAlphaBitMask == 0x8000L)
        ){
            //  A1R5G5B5 -> A8R8G8B8
            USHORT usPixel;
            for (y = 0; y < srcHeight ; ++y){
                pByte = pDest + (y * hMappedResource.RowPitch);
                pSrc = (BYTE*)pBuffer + (y * srcPitch);
                for (x = 0; x < srcWidth ; ++x){
                    usPixel = *(USHORT*)pSrc;
                    r = (((usPixel >> 10)&0x1f)*255)/31;
                    g = (((usPixel >> 5) & 0x1f) * 255) / 31;
                    b = ((usPixel & 0x1f) * 255) / 31;
                    a = ((usPixel >> 15)&1) * 255;
                    
                    *(DWORD*)pByte = (a << 24)+(r << 16)+(g << 8) + b;
                    pSrc  += sizeof(USHORT);
                    pByte += sizeof(DWORD);
                }
                while(x < texWidth){
                    *(DWORD*)pByte = 0L;
                    pByte += sizeof(DWORD);
                    ++x;
                }
            }
            while(y < texHeight){
                pByte = pDest + (y * hMappedResource.RowPitch);
                for (x = 0; x < texWidth ; ++x){
                    *(DWORD*)(pByte+sizeof(DWORD)*x) = 0L;
                }
                ++y;
            }
            hr = S_OK;
        }else if (    (pddsc->ddpfPixelFormat.dwRBitMask == 0xf800L)
            &&    (pddsc->ddpfPixelFormat.dwGBitMask == 0x07e0L)
            &&    (pddsc->ddpfPixelFormat.dwBBitMask == 0x001fL)
        ){
            //  R5G6B5 -> A8R8G8B8
            USHORT usPixel;
            for (y = 0; y < srcHeight ; ++y){
                pByte = pDest + (y * hMappedResource.RowPitch);
                pSrc = (BYTE*)pBuffer + (y * srcPitch);
                for (x = 0; x < srcWidth ; ++x){
                    usPixel = *(USHORT*)pSrc;
                    r = (((usPixel >> 11)&0x1f)*255)/31;
                    g = (((usPixel >> 5) & 0x3f) * 255) / 63;
                    b = ((usPixel & 0x1f) * 255) / 31;
                    a = 255;
                    
                    *(DWORD*)pByte = (a << 24)+(r << 16)+(g << 8) + b;
                    pSrc  += sizeof(USHORT);
                    pByte += sizeof(DWORD);
                }
                while(x < texWidth){
                    *(DWORD*)pByte = 0L;
                    pByte += sizeof(DWORD);
                    ++x;
                }
            }
            while(y < texHeight){
                pByte = pDest + (y * hMappedResource.RowPitch);
                for (x = 0; x < texWidth ; ++x){
                    *(DWORD*)(pByte+sizeof(DWORD)*x) = 0L;
                }
                ++y;
            }
            hr = S_OK;
        }
    }
    pContext->Unmap(pOutput,0);
    if (SUCCEEDED(hr)){
        *ppTexture = pOutput;
        pOutput = NULL;
    }
ERROR_EXIT:
    SAFE_RELEASE(pOutput);
    SAFE_RELEASE(pDevice);
    return hr;
}



クラス CFont

Font のページを参照