4.3 How to render an image on Direct3D11?

Direct3D10 has ID3DX10Sprite interface to draw an image, but Direct3D11 has no corresponding interface something like a ID3DX11Sprite. On Direct3D11, to read image files, you will use the following WIC (Windows Imaging Component) interfaces,

IWICImagingFactory,
IWICBitmapDecoder,
IWICBitmapFrameDecode,
IWICBitmapScaler,
IWICFormatConverter,

, and to display the read images, an instance of ID2D1Bitmap created by WIC interfaces, and ID2D1RenderTarget created by ID2D1Factory interface. See aslo our directx samples: Direct2DBitmap. and WICBitmapScaler.

The following 'Direct3DX11ImageRendering' example based on SOL Direct2D1, WIC, Direct3D11 classes shows how to render an image file on Direct3D11 environment. This is just another simple surface sharing example between Direct2D1 and Direct3D11.


/*
 * Direct3DX11ImageRendering.cpp 
 * Copyright (c) 2015 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


// 2016/01/10
#pragma warning(disable : 4005) 
#pragma warning(disable : 4838) 

#define COMMONCONTROLS_V6

#include <sol/StringConverter.h>

#include <sol/StringT.h>

#include <sol/direct3d11/DirectX3D11MainView.h>
#include <sol/direct3d11/DirectX3D11View.h>

#include <sol/direct3d11/Direct3D11RenderTargetView.h>
#include <sol/direct3d11/Direct3D11DepthStencilView.h>

#include <sol/direct3d11/Direct3D11Texture2D.h>
#include <sol/direct3d11/D3D11Texture2DDesc.h>
#include <sol/direct3d11/D3D11DepthStencilViewDesc.h>

#include <sol/directx/Direct2D1Factory.h>
#include <sol/directx/Direct2D1RenderTarget.h>
#include <sol/dxgi/DirectXGISurface.h>

#include <sol/wic/WICImagingFactory.h>
#include <sol/wic/WICFormatConverter.h>
#include <sol/wic/WICBitmapDecoder.h>
#include <sol/wic/WICBitmapFrameDecode.h>
#include <sol/wic/WICBitmapFileReader.h>
#include <sol/directx/DirectXView.h>
#include <sol/directx/DirectXMainView.h>

#include <sol/directx/Direct2D1Factory.h>
#include <sol/directx/Direct2D1HwndRenderTarget.h>
#include <sol/directx/Direct2D1Bitmap.h>

#include "resource.h"

namespace SOL {
  
class MainView :public DirectX3D11MainView {
  
private:
  //////////////////////////////////////////////
  //Inner class starts
  class SimpleView : public DirectX3D11View {
  private:
    SmartPtr<Direct3D11RenderTargetView>  renderTargetView;
    SmartPtr<Direct3D11DepthStencilView>  depthStencilView;

    SmartPtr<DirectXGISurface>            dxgiSurface;
    SmartPtr<Direct2D1Factory>            d2d1Factory;
    SmartPtr<Direct2D1RenderTarget>       d2d1RenderTarget;
    
    SmartPtr<WICImagingFactory>           imagingFactory;
    SmartPtr<Direct2D1Bitmap>             bitmap;
    StringT<wchar_t>             url;

  public:
    void deleteViews()
    {
      Direct3D11ImmediateContext* d3d11ImmediateContext = getD3D11ImmediateContext();
      d3d11ImmediateContext -> setOMRenderTargets(0, NULL, NULL);
 
      renderTargetView = NULL;
      depthStencilView = NULL;
    }

    virtual void createViews()
    {
      int width  = 0;
      int height = 0;
     
      validateClientSize(width, height);

      try {
        Direct3D11Device*   d3d11Device  = getD3D11Device();
        Direct3D11ImmediateContext* d3d11ImmediateContext = getD3D11ImmediateContext();
        
        DirectXGISwapChain* swapChain = getSwapChain();

        d3d11ImmediateContext -> setOMRenderTargets(0, NULL, NULL);

        //1 Create an instance of Direct3D11RenderTargetView
        Direct3D11Texture2D renderTargetViewTexture(*swapChain); ; 

        renderTargetView = new Direct3D11RenderTargetView(*d3d11Device, renderTargetViewTexture, NULL);

        //2 Create a temporary depthDesc(D3D11Texture2DDesc).
        D3D11Texture2DDesc depthDesc;
        depthDesc.width(width);
        depthDesc.height(height);
        depthDesc.mipLevels(1);
        depthDesc.arraySize(1);
        depthDesc.format(DXGI_FORMAT_D32_FLOAT);
        depthDesc.sampleDescCount(1);
        depthDesc.sampleDescQuality(0);
        depthDesc.usage(D3D11_USAGE_DEFAULT);
        depthDesc.bindFlags(D3D11_BIND_DEPTH_STENCIL);

        //3 Create a temporary depthStencilTexture(Direct3D11Texture2D) from texture2DDesc.
        Direct3D11Texture2D depthStencilTexute(*d3d11Device, depthDesc); 

        //4 Create a temporary depthStencilViewDesc(D3D11DepthStencilViewDesc) 
        D3D11DepthStencilViewDesc depthStencilViewDesc(DXGI_FORMAT_D32_FLOAT, D3D11_DSV_DIMENSION_TEXTURE2D);

        //5 Create an instance of Direct3DDepthStencilView from depthStencilTexture and depthStencilViewDesc
        depthStencilView = new Direct3D11DepthStencilView(*d3d11Device, depthStencilTexute, depthStencilViewDesc);

        ID3D11RenderTargetView* targetView   = *renderTargetView; 

        //6 Set renderTargetView and depthStencilView to id3d11Device
        d3d11ImmediateContext ->setOMRenderTargets(1, &targetView, *depthStencilView);
        
      } catch (Exception& ex) {
        caught(ex);
      }
    }

    virtual void initialize()
    {
      try {
        Direct3D11Device* d3d11Device = getD3D11Device();

        // 1 Create rendarTargetView and depthStencilView.
        createViews();

        //
        DirectXGISwapChain* swapChain = getSwapChain();

        // 2 Create an instance of DirectXGISurface;
        dxgiSurface = new DirectXGISurface(*swapChain);

        d2d1Factory = new Direct2D1Factory();

        FLOAT dpiX = 0.0f;
        FLOAT dpiY = 0.0f;
        d2d1Factory->getDesktopDpi(&dpiX, &dpiY);

        D2D1_RENDER_TARGET_PROPERTIES props =D2D1::RenderTargetProperties(
                D2D1_RENDER_TARGET_TYPE_DEFAULT,
                D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
                dpiX,
                dpiY
                );
        // 3 Create an instance of Direct2D1RenderTarget.
        d2d1RenderTarget = new Direct2D1RenderTarget(*d2d1Factory, *dxgiSurface, &props);
        
        imagingFactory = new WICImagingFactory();
        WICBitmapFileReader reader(*imagingFactory, url);

        //4 Create a Direct2D1Bitmap by using WICBitmapReader.
        bitmap = reader.read(*d2d1RenderTarget);

      } catch (Exception& ex) {
        caught(ex);
      }
    }

    // Draw a wchar_t string on the d2d1RenderTarget.
    void drawBitmap()
    {
      try {
        d2d1RenderTarget -> beginDraw();

        d2d1RenderTarget -> setTransform(D2D1::Matrix3x2F::Identity());
        d2d1RenderTarget -> clear(D2D1::ColorF(D2D1::ColorF::White));

        auto size = d2d1RenderTarget->getSize();
        auto rectangle = D2D1::RectF(0.0f, 0.0f, size.width, size.height);

        d2d1RenderTarget -> drawBitmap(*bitmap, rectangle);
        
        d2d1RenderTarget -> endDraw();
        
      } catch (Exception& ex) {
        caught(ex);
      }
    }
    
    virtual void display()
    {
      try {
        Direct3D11Device*  d3d11Device = getD3D11Device();
        DirectXGISwapChain* swapChain = getSwapChain();
        Direct3D11ImmediateContext* d3d11ImmediateContext = getD3D11ImmediateContext();

        if (renderTargetView && 
            depthStencilView &&
            d2d1RenderTarget) {
          d3d11ImmediateContext -> clear(*renderTargetView, XMColor(0.0f, 0.3f, 0.3f, 0.0f));
          d3d11ImmediateContext -> clear(*depthStencilView);
        
          drawBitmap();
        }
        swapChain -> present();

      } catch (Exception& ex) {
        caught(ex);
      }
    }

  public:
    // Constructor
    SimpleView(DirectX3D11MainView* parent, const TCHAR* name, Args& args)
   :DirectX3D11View(parent, name, args )
    {
      //XmNurl is a fullpath for an image file.
      url = (const wchar_t*)args.get(XmNurl);
    }

    ~SimpleView()
    {
    }
    
  private:
    void resize(int width, int height)
    {
      Direct3D11Device*   device = getD3D11Device();
      DirectXGISwapChain* swapChain = getSwapChain();
      if (device           == NULL && 
          swapChain        == NULL && 
          renderTargetView == NULL &&
          depthStencilView == NULL) {
        return ;
      }
    
      try {
        // 1 Delete existing rendarTargetView and depthStencilView.
        deleteViews();

        // 2 ResizeBuffers swapChain(IDXGISwapChain)
        swapChain -> resizeBuffers(width, height); 
     
        // 3 Recreate rendarTargetView and depthStencilView.
        createViews();
      
        // 4 SetViewPort
        setViewPort(width, height);

      } catch (Exception& ex) {
        caught(ex);
      }
    }  
  };
  //////////////////////////////////////////////
  // Inner class ends.
  
private:
  SmartPtr<SimpleView> view;
  
public:
  // Constructor
  MainView(Application& applet, const TCHAR* name, Args& args)
  :DirectX3D11MainView(applet, name,
                 args.set(XmNstyle, (ulong)WS_CLIPCHILDREN|WS_CLIPSIBLINGS) )
  {
    const TCHAR* directory = (const TCHAR*)args.get(XmNapplicationDirectory);
    StringConverter converter;
    
    wchar_t* dir = converter.toWideChar(directory);

    wchar_t url[MAX_PATH];
    swprintf_s(url, CountOf(url),  L"%s\\..\\images\\%s", dir, L"flower1.jpg");
    delete [] dir;
    
    // 1 Create a view of SimpleView.
    Args ar;
    int width  = 0;
    int height = 0;
    getClientSize(width, height);

    ar.set(XmNwidth, width);
    ar.set(XmNheight,height);
    ar.set(XmNurl,  url);
    ar.set(XmNstyle, WS_BORDER|WS_CHILD|WS_VISIBLE);
    view = new SimpleView(this, _T(""), ar);

    // 2 Post a resize request to this MainView.
    postResizeRequest();
  }
  
public:
  ~MainView()
  {
  }

private:
  void resize(int width, int height)
  {
    if (view != nullptr) {
      view -> reshape(0, 0, width, height);
      view -> postResizeRequest(width, height);
    }
  }
};
  
}

//////////////////////////////////////////////
//
void  Main(int argc, TCHAR** argv)
{
  const TCHAR* appClass = appName(argv[0]); 
  
  TCHAR directory[MAX_PATH];
  appDirectory(argv[0], directory, CountOf(directory));
  
  try {
    Application applet(appClass, argc, argv);

    Args args;
    args.set(XmNwidth,  700);
    args.set(XmNheight, 480);
    args.set(XmNapplicationDirectory, directory);

    MainView imageViewer(applet, appClass, args);
    
    imageViewer.realize();

    applet.run();
  } catch (Exception& ex) {
    caught(ex);
  }
}


Last modified: 8 Dec 2016

 Last modified: 8 Dec 2016

Copyright (c) 2000-2016 Antillia.com ALL RIGHTS RESERVED.