4.4 How to render a geometrical shape on Direct3D11?

Direct3D 10 has ID3DX10Mesh interface to store vertices and indices data of geometrical shapes, and to draw the shapes by using ID3D10Effect and related ID3D10EffectVaraible interfaces, but, Direct3D 11 has no corresponding interface something like ID3DX11Mesh.
Direct3D10 Sample C++ programs also provides some optional APIs based on ID3DX11Mesh to create typical shapes such as Box, Cylinder, Polygon, Sphere, Torus, Teapost (See: Microsoft DirectX SDK (June 2010)\Samples\C++\DXUT\Optional\DXUTShape.h) , but Direct3D 11 has no optional creation APIs for such shapes.
Fortunately, in almost all cases, the ID3DXMesh interface will be replaced by a pair of vertexBuffer and indexBuffer which are Direct3D11 ID3D11Buffers respectively.
On Direct3D11 environment. you will be able to write APIs to draw the typical geometrical shapes, by using ID3D11Buffer interface.
In fact, on the latest SOL9.2.0.41 library, we have implemented the following C++ classes based on the DXUT\Optional\DXUTShape.cpp for Direct3D 11:
Direct3DX11Object
Direct3DX11Shape
Direct3DX11Box
Direct3DX11Cylinder
Direct3DX11Sphere
Direct3DX11Torus
The following 'Direct3DX11SphereBuffer' example shows how to render a sphere on Direct3D11 environment.


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



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

#define COMMONCONTROLS_V6

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

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

#include <sol/direct3d11/Direct3D11PixelShader.h>
#include <sol/direct3d11/Direct3DX11Sphere.h>

#include <sol/direct3d11/Direct3D11Texture2D.h>

#include <sol/direct3d11/D3D11Texture2DDesc.h>
#include <sol/direct3d11/Direct3D11Buffer.h>
#include <sol/direct3d11/Direct3D11Blob.h>

#include <sol/direct3d11/D3D11PosColorVertex.h>
#include <sol/direct3d11/D3D11ConstantBuffer.h>
#include <sol/direct3d11/D3D11DepthStencilViewDesc.h>
#include <sol/direct3d11/D3D11InputElements.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<Direct3D11RasterizerState>    rasterizerState;
    SmartPtr<Direct3DX11Sphere>            sphere;
    SmartPtr<Direct3D11Blob>               vertexShaderBlob;
    SmartPtr<Direct3D11Blob>               pixelShaderBlob;
    SmartPtr<Direct3D11VertexShader>       vertexShader;
    SmartPtr<Direct3D11PixelShader>        pixelShader;
    SmartPtr<Direct3D11Buffer>             constantBuffer;
    
    XMMatrix                      world;
    XMMatrix                      view;
    XMMatrix                      projection;

    StringT<TCHAR>                directory;
    float                         angle;

  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* targets[1];
        targets[0]= *renderTargetView; 
        //6 Set renderTargetView and depthStencilView to id3d11Device
        d3d11ImmediateContext ->setOMRenderTargets(1, targets, *depthStencilView);
      } catch (Exception& ex) {
        caught(ex);
      }
    }
  
     void createVertexShader()
    {
      Direct3D11Device* d3d11Device = getD3D11Device();
      TCHAR fullpath[MAX_PATH];
      _stprintf_s(fullpath, CountOf(fullpath), _T("%s\\..\\fx\\%s"), 
                    (const TCHAR*)directory, 
                    _T("shader.fx"));
      try {
        vertexShaderBlob = new Direct3D11Blob(fullpath, "VS", "vs_4_0");
        if (vertexShaderBlob) {
          vertexShader = new Direct3D11VertexShader(*d3d11Device, *vertexShaderBlob);
        }
      } catch (Exception& ex) {
        caught(ex);
      }
    }
    
    void createPixelShader()
    {
      Direct3D11Device* d3d11Device = getD3D11Device();
      TCHAR fullpath[MAX_PATH];
      _stprintf_s(fullpath, CountOf(fullpath), _T("%s\\..\\fx\\%s"), 
                    (const TCHAR*)directory, 
                    _T("shader.fx"));

      try {
        pixelShaderBlob = new Direct3D11Blob(fullpath, "PS", "ps_4_0");
        if (pixelShaderBlob) {
          pixelShader = new Direct3D11PixelShader(*d3d11Device, *pixelShaderBlob);
        }
      } catch (Exception& ex) {
        caught(ex);
      }
    }

    void createRasterizerState()
    {
      try {
        Direct3D11Device* d3d11Device = getD3D11Device();
        Direct3D11ImmediateContext* d3d11ImmediateContext = getD3D11ImmediateContext();

        D3D11_RASTERIZER_DESC desc;
        memset(&desc, 0, sizeof(desc));
        desc.CullMode               = D3D11_CULL_FRONT;
        desc.FillMode               = D3D11_FILL_WIREFRAME;

        desc.FrontCounterClockwise  = true;
        desc.DepthBias              = false;
        //desc.DepthBiasClamp         = 0;
        //desc.SlopeScaledDepthBias   = 0;
        desc.DepthClipEnable        = true;
        desc.ScissorEnable          = false;
        desc.MultisampleEnable      = false;
        desc.AntialiasedLineEnable  = true;

        rasterizerState = new Direct3D11RasterizerState (*d3d11Device, &desc);

        d3d11ImmediateContext->setRSState(*rasterizerState);

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


    void createSphereBuffer()
    {
      try {
        Direct3D11Device* d3d11Device = getD3D11Device();
        Direct3D11ImmediateContext* d3d11ImmediateContext = getD3D11ImmediateContext();
        sphere = new Direct3DX11Sphere(d3d11Device, d3d11ImmediateContext, vertexShaderBlob,
          1.0f, 20, 20);

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


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

        D3D11_BUFFER_DESC constantBufferDesc;
        memset(&constantBufferDesc, 0, sizeof(constantBufferDesc));
        constantBufferDesc.Usage     = D3D11_USAGE_DEFAULT;
        constantBufferDesc.ByteWidth = sizeof(D3D11ConstantBuffer); 
        constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;

        // Create a constantBuffer from above parameters.
        constantBuffer = new Direct3D11Buffer(*d3d11Device, &constantBufferDesc, NULL);  
      } catch (Exception& ex) {
        caught(ex);
      }
    }

    void setShaderMatrices()
    {
      int width = 0;
      int height = 0;
      getClientSize(width, height);

      try {
        
          XMVECTOR  eye = XMVectorSet(  0.0f,  2.0f, -5.0f,  0.0f );
          XMVECTOR  at  = XMVectorSet(  0.0f,  0.0f,  0.0f,  0.0f );
          XMVECTOR  up  = XMVectorSet(  0.0f,  1.0f,  0.0f,  0.0f );
          view = XMMatrix::lookAtLH( (XMVECTOR)eye, (XMVECTOR)at, (FXMVECTOR)up );

           projection = XMMatrix::perspectiveFovLH( XM_PIDIV2*0.3f, width / (FLOAT)height, 0.01f, 100.0f );
       
      } catch (Exception& ex) {
        caught(ex);
      }
    }

    virtual void initialize()
    {
      try {
        createVertexShader();

        createPixelShader();
        
        createSphereBuffer();

        createRasterizerState();  

        createConstantBuffer();
        
        setShaderMatrices();

        createViews();

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

    virtual void display()
    {
      try {
        Direct3D11Device*  d3d11Device = getD3D11Device();
        DirectXGISwapChain* swapChain = getSwapChain();
        Direct3D11ImmediateContext*  d3d11ImmediateContext = getD3D11ImmediateContext();
        
        if (renderTargetView && depthStencilView && sphere) {
          d3d11ImmediateContext -> clear(*renderTargetView, XMColor(0.0f, 0.1f, 0.2f, 0.0f));

          d3d11ImmediateContext -> clear(*depthStencilView);

          world = XMMatrix::rotationY( angle );

          D3D11ConstantBuffer cb;
            cb.world      = XMMatrix::transpose(world );
            cb.view       = XMMatrix::transpose(view );
            cb.projection = XMMatrix::transpose(projection );
            d3d11ImmediateContext -> updateSubresource(*constantBuffer, 0, NULL, &cb, 0, 0 );
          
          d3d11ImmediateContext -> setVSShader( *vertexShader, NULL, 0 );
          
          ID3D11Buffer* cbuffer =  *constantBuffer;
            d3d11ImmediateContext -> setVSConstantBuffers( 0, 1, &cbuffer );
            d3d11ImmediateContext -> setPSShader( *pixelShader, NULL, 0 );
          sphere -> drawIndexed(); 
          
        }
        swapChain -> present();

      } catch (Exception& ex) {
        caught(ex);
      }
    }
    
  public:
    // Constructor
    SimpleView(DirectX3D11MainView* parent, const TCHAR* name, Args& args)
   :DirectX3D11View(parent, name, args),
    directory(_T("")),
    angle(0.5f)
    {
      directory = (const TCHAR*)args.get(XmNapplicationDirectory);
    }

    ~SimpleView()
    {    
    }
    
  private:
    void resize(int width, int height)
    {
      Direct3D11Device*   device = getD3D11Device();
      DirectXGISwapChain* swapChain = getSwapChain();
      if (device           == NULL && 
          swapChain        == NULL && 
          renderTargetView == 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) )
  {
    DWORD interval = (DWORD)args.get(XmNrenderingInterval);

    const TCHAR* directory = (const TCHAR*)args.get(XmNapplicationDirectory);
    // 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(XmNapplicationDirectory, directory);
    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(XmNapplicationDirectory, directory);
    args.set(XmNwidth,  640);
    args.set(XmNheight, 480);
    MainView mainv(applet, appClass, args);
    
    mainv.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.