画像表示を含む自分用アプリの雛形(7) DirectXTk -SpriteBatchの利用

グリグリ動かすようなときには、3Dの方に描いちゃったほうがいいでしょう、ということで
調べてみました。

前回の
[画像表示を含む自分用アプリの雛形(4) Direct2D化-3, DXGI](https://qiita.com/tanakah/items/d88bcaa4536d8a1cdf1e)
を修正する形で書いてみました。

## ヘッダー、グローバル変数の設定

SpliteBatch が、DirectXTkからのものです。
前回のDXGI利用の描画に対して、USE_DIRECTXTKで追加コードを挿入していきます。

```
#define USE_DIRECTXTK

#ifdef USE_DIRECTXTK
ID3D11DeviceContext   *pD3D_DC;
ID3D11Texture2D       *pD3D_RT;
ID3D11RenderTargetView *pD3D_RenderTargetView;
ID3D11ShaderResourceView *pD3D_ShaderResourceView;

#include "DirectXTK/SpriteBatch.h"
#include "DirectXTK/WICTextureLoader.h"
#pragma comment(lib, "DirectXTK.lib")
DirectX::SpriteBatch *pSpriteBatch;
#endif
```

## Initialize
スワップチェーンの設定として、DXGI_SWAP_EFFECT_DISCARDを使用します。
(DXGI描画のときも、DXGI_SWAP_EFFECT_DISCARDのほうがいいんじゃね？と思います。)

```
  pD2D_Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, reinterpret_cast<ID2D1DeviceContext **>(&pDC));

  CreateDXGIFactory2(0, IID_PPV_ARGS(&pDXGI_Factory));
  DXGI_SWAP_CHAIN_DESC1 swapChainDesc={};
  swapChainDesc.Format=DXGI_FORMAT_B8G8R8A8_UNORM;
  swapChainDesc.BufferUsage=DXGI_USAGE_RENDER_TARGET_OUTPUT;
  swapChainDesc.SwapEffect=DXGI_SWAP_EFFECT_DISCARD; //DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;  
  swapChainDesc.BufferCount=2;
  swapChainDesc.SampleDesc.Count=1;
  pDXGI_Factory->CreateSwapChainForHwnd(pDXGI_Device, hDlgImg, &swapChainDesc, NULL, NULL, &pDXGI_SwapChain);
  pDXGI_SwapChain->GetBuffer(0, IID_PPV_ARGS(&pDXGI_Surface));

  D2D1_BITMAP_PROPERTIES1 bitmapPropsDXGI=D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_NONE, D2D_PixelFormat);
  bitmapPropsDXGI.bitmapOptions|=(D2D1_BITMAP_OPTIONS_TARGET|D2D1_BITMAP_OPTIONS_CANNOT_DRAW);
  pDC->CreateBitmapFromDxgiSurface(pDXGI_Surface, &bitmapPropsDXGI, &pD2D_BitmapDXGI);
  pDC->SetTarget(pD2D_BitmapDXGI);

#ifdef USE_DIRECTXTK
  pD3D_Device->GetImmediateContext(&pD3D_DC);
  pDXGI_SwapChain->GetBuffer(0, IID_PPV_ARGS(&pD3D_RT));

  pD3D_Device->CreateRenderTargetView(pD3D_RT, NULL, &pD3D_RenderTargetView);
  pD3D_DC->OMSetRenderTargets(1, &pD3D_RenderTargetView, NULL);
  D3D11_VIEWPORT vp;
  vp.Width=(float)FrameWidth;
  vp.Height=(float)FrameHeight;
  vp.MinDepth=0.0f; vp.MaxDepth=1.0f; vp.TopLeftX=0; vp.TopLeftY=0;
  pD3D_DC->RSSetViewports(1, &vp);

  pSpriteBatch=new DirectX::SpriteBatch(pD3D_DC);
#endif
```

## pngファイル読み込み

pngファイルから、テクスチャを生成します。

```
      char ffilename[MAX_PATH];
      sprintf(ffilename, "%s\\%s", HomeFolderName, filename);

      IStream *pIStream;
      HRESULT hr=SHCreateStreamOnFile(ffilename, STGM_READ, &pIStream);
      if(hr==S_OK){
        IWICBitmapDecoder *pDecoder=NULL;
        IWICBitmapFrameDecode *pDecodedFrame=NULL;

        pWIC_Factory->CreateDecoderFromStream(pIStream, NULL, WICDecodeMetadataCacheOnLoad, &pDecoder);
        pDecoder->GetFrame(0, &pDecodedFrame);

        IWICBitmapSource *pWIC_BS=NULL;
        WICPixelFormatGUID WIC_PixelFormat=GUID_WICPixelFormat32bppPBGRA;
        WICConvertBitmapSource(WIC_PixelFormat, pDecodedFrame, &pWIC_BS);
        
        pDecodedFrame->Release();
        pDecoder->Release();
        pIStream->Release();

        pWIC_BS->GetSize((UINT *)&ImageWidth1, (UINT *)&ImageHeight1);

        if(pD2D_Bitmap!=NULL){ pD2D_Bitmap->Release(); pD2D_Bitmap=NULL; }
        if(pRT!=NULL) pRT->CreateBitmapFromWicBitmap(pWIC_BS, (ID2D1Bitmap **)&pD2D_Bitmap);
        if(pDC!=NULL) pDC->CreateBitmapFromWicBitmap(pWIC_BS, &pD2D_Bitmap);
        pWIC_BS->Release();
      }

#ifdef USE_DIRETXTK
      wchar_t wbuf[256]; MultiByteToWideChar(CP_ACP, 0, ffilename, -1, wbuf, 256);
      if(pD3D_ShaderResourceView!=NULL) pD3D_ShaderResourceView->Release();
      ID3D11Resource *pD3D_Resource;
      DirectX::CreateWICTextureFromFile(pD3D_Device, wbuf, &pD3D_Resource, &pD3D_ShaderResourceView);
      ID3D11Texture2D *pD3D_Texture2D; pD3D_Resource->QueryInterface(IID_PPV_ARGS(&pD3D_Texture2D));
      CD3D11_TEXTURE2D_DESC TextureDesc; pD3D_Texture2D->GetDesc(&TextureDesc);
      pD3D_Resource->Release();
#endif
```

## 描画
D2DDeviceContextのかわりに、SpriteBatchを使用します。

```
#ifdef USE_DIRECTXTK
  pSpriteBatch->Begin();
  if(pD3D_ShaderResourceView!=NULL) pSpriteBatch->Draw(pD3D_ShaderResourceView, DirectX::XMFLOAT2(0, 0));
  pSpriteBatch->End();
#else
  pDC->BeginDraw();
  if(pD2D_Bitmap!=NULL){
    pDC->DrawBitmap(pD2D_Bitmap, D2D1::RectF(0.f, 0.f, (float)ImageWidth1, (float)ImageHeight1),
                    1.f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
  }
#endif
  pDXGI_SwapChain->Present(1, 0);
```