SOL9 Sample: Direct3D12FullScreenLightedTorusWithColorChooser

SOL9 2.0 Samples

1 Screenshot


2 Source code

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


// 2016/11/10
// This is a fullscreen version of the sample program  
//in "usr/src/direct3d12/Direct3D12LightedTorusWithColorChooser".
// 2017/01/28 Updated to use ModuleFileName class and caught macro.


#define COMMONCONTROLS_V6
#define WIN10

#include <sol/Stdio.h>
#include <sol/PushButton.h>
#include <sol/ColorChooser.h>
#include <sol/CriticalSection.h>
#include <sol/SystemMetrics.h>
#include <sol/CharModuleFileName.h>

#include <sol/direct3d12/DirectX3D12MainView.h>
#include <sol/direct3d12/DirectX3D12View.h>
#include <sol/direct3d12/DirectXMatrix.h>
#include <sol/direct3d12/Direct3D12CommandAllocator.h>
#include <sol/direct3d12/Direct3D12RenderTargetView.h>
#include <sol/direct3d12/Direct3D12DepthStencilView.h>

#include <sol/direct3d12/Direct3D12TransformLightConstantBufferView.h>

#include <sol/direct3d12/Direct3D12TextureRootSignature.h>
#include <sol/direct3d12/Direct3D12BarrieredGraphicsCommandList.h>

#include <sol/direct3d12/Direct3D12PipelineState.h>

#include <sol/direct3d12/D3D12RasterizerDesc.h>
#include <sol/direct3d12/D3D12BlendDesc.h>
#include <sol/direct3d12/D3D12GraphicsPipelineStateDesc.h>
#include <sol/direct3d12/D3D12ResourceBarrier.h>
#include <sol/direct3d12/D3D12Transform.h>

#include <sol/direct3d12/D3D12GraphicsPipelineStateDesc.h>

#include <sol/direct3d12/Direct3D12Synchronizer.h>
#include <sol/direct3d12/Direct3DX12Torus.h>

#include <sol/direct3d12/DirectXTransformLight.h>
#include <sol/direct3d12/Direct3D12CommonDescriptorHeap.h>
#include <sol/direct3d12/DirectX3D12TimerThread.h>
#include "resource.h"

namespace SOL {
  
class MainView :public DirectX3D12MainView {
private:

    SmartPtr<PushButton>                     quit;
    SmartPtr<ColorChooser>                   chooser;
    SmartPtr<Direct3D12CommandQueue>         commandQueue;
    SmartPtr<DirectXGISwapChain3>            swapChain;
    SmartPtr<Direct3D12CommandAllocator>     commandAllocator;
    SmartPtr<Direct3D12RenderTargetView>     renderTargetView;
    SmartPtr<Direct3D12DepthStencilView>     depthStencilView;
    SmartPtr<Direct3D12RootSignature>        rootSignature;
    SmartPtr<Direct3D12CommonDescriptorHeap>  commonDescriptorHeap;
    SmartPtr<Direct3D12TransformLightConstantBufferView>   constantBufferView;
    SmartPtr<Direct3D12BarrieredGraphicsCommandList>  graphicsCommandList;
    SmartPtr<Direct3D12PipelineState>        pipelineState;
    SmartPtr<Direct3D12Synchronizer>         synchronizer;
    SmartPtr<Direct3DX12Torus>               torus;
    
    UINT                            frameIndex;
    int                             renderingInterval;
    DirectXTransformLight           lightedConstantBuffer;
    float                           angle;
    StringT<TCHAR>                  directory;
    XMFLOAT4                        lightColor;

private:
  DirectXGISwapChain3* getSwapChain3()
  {
    return swapChain;
  }

  Direct3D12CommandQueue* getCommandQueue()
  {
    return commandQueue;
  }

    
  virtual void createPipelineState(ID3D12Device* device, Direct3DX12Shape* shape)
  {
    //Create a graphicPipelineStateDes.
    D3D12GraphicsPipelineStateDesc graphicsPipelineStateDesc(*rootSignature);
      
    UINT count = 0;
    const D3D12_INPUT_ELEMENT_DESC* inputElements = torus->getInputElementDesc(count);
      
    D3D12RasterizerDesc  rasterDesc(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE,  true);
      
    D3D12BlendDesc       blendDesc;
            
    graphicsPipelineStateDesc.setInputLayput(inputElements, count);
      
    graphicsPipelineStateDesc.setRasterizerState(rasterDesc);
    graphicsPipelineStateDesc.setBlendState(blendDesc);
      
    StringT<TCHAR> vsshaderFile = getShaderFilePath(directory, _T("VertexShader.cso"));
    StringT<TCHAR> psshaderFile = getShaderFilePath(directory, _T("PixelShader.cso"));

    graphicsPipelineStateDesc.setVertexShader(vsshaderFile);
    graphicsPipelineStateDesc.setPixelShader(psshaderFile);

    pipelineState = new Direct3D12PipelineState(device, graphicsPipelineStateDesc);
  }

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

    try {
      XMVECTOR eye = XMVectorSet(0.0f, 1.0f, -8.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);

      lightedConstantBuffer.world      = DirectXMatrix::rotationY(angle);
      lightedConstantBuffer.view       = DirectXMatrix::lookAtLH(eye, at, up);
      lightedConstantBuffer.projection = DirectXMatrix::perspectiveFovLH(XM_PIDIV2*0.3f, 
                width / (FLOAT)height, 0.01f, 100.0f);
      lightedConstantBuffer.lightDirection = XMFLOAT4(-0.8f, 0.8f, 0.3f, 1.0f);

      lightedConstantBuffer.lightColor = lightColor; 
      if (constantBufferView != nullptr) {
        constantBufferView->update(lightedConstantBuffer);
      }
    }
    catch (Exception& ex) {
      caught(ex);
    }
  }

public:
  //Create a renderTargetView and a depthStencilView.
  void createViews(ID3D12Device* device, IDXGISwapChain3* swapChain,
                  int width, int height)
  {
    renderTargetView = new Direct3D12RenderTargetView(device, swapChain);
    depthStencilView = new Direct3D12DepthStencilView(device,  width, height);
   }
    
   //Delete a renderTargetView and a depthStencilView.
   void deleteViews()
   {
    if (graphicsCommandList == nullptr) {
      throw IException("GraphicsCommandList is NULL.")
    }
    graphicsCommandList->setOMRenderTargets(0, nullptr, FALSE, nullptr);

    renderTargetView = NULL;
    depthStencilView = NULL;
  }
    
  virtual void initialize()
  {
    int width  = 0;
    int height = 0;
    validateClientSize(width, height);

    DirectXGIFactory4* factory = getDXGIFactory4(); //From DirectX3D12MainView

    Direct3D12Device*  device  = getD3D12Device();  //From DirectX3D12MainView

    try {
      commandQueue = new Direct3D12CommandQueue(*device);
 
      bool enableFullscreen = true;
      swapChain = new DirectXGISwapChain3(*factory, *commandQueue, 2,
                            getWindow(), width, height, enableFullscreen);

      commandAllocator         = new Direct3D12CommandAllocator(*device);

      renderTargetView         = new Direct3D12RenderTargetView(*device, *swapChain);

      depthStencilView         = new Direct3D12DepthStencilView(*device,  width, height);
          
      graphicsCommandList      = new Direct3D12BarrieredGraphicsCommandList(*device, *commandAllocator);
        
      rootSignature            = new Direct3D12RootSignature(*device);

      commonDescriptorHeap     = new Direct3D12CommonDescriptorHeap(*device, 1);

      constantBufferView       = new Direct3D12TransformLightConstantBufferView(*device,
                                            commonDescriptorHeap->getCPUHandle(CBV_HANDLE) );

      synchronizer             = new Direct3D12Synchronizer(*device, *commandQueue);

      //1 Create a renderTargetView and depthStencilView
      createViews(*device, *swapChain, width, height);
        
      //2 Define your own specific initialization procedures.
      // Create your own shape
        
      torus                    = new Direct3DX12Torus(*device, 0.2f, 1.0f, 30, 30);
        
      //3 Create two pipelineState(wireframe and solid) from the sphere. 
        
      createPipelineState(*device, torus);

      //4 Set world, view and projection to the constantBuffer.
      setDirectXTransformLight();

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

  bool ready()
  {
    Direct3D12Device*    device          = getD3D12Device();
    DirectXGISwapChain3* swapChain       = getSwapChain3();
    Direct3D12CommandQueue* commandQueue = getCommandQueue();
      
    if (
        device                    == nullptr ||
        commandQueue              == nullptr ||
        swapChain                 == nullptr ||
        
        commandAllocator          == nullptr ||
        renderTargetView          == nullptr ||
        depthStencilView          == nullptr ||

        rootSignature             == nullptr ||
        commonDescriptorHeap      == nullptr ||
        constantBufferView        == nullptr ||
        torus                     == nullptr ||

        graphicsCommandList       == nullptr ||
        pipelineState             == nullptr ||
        synchronizer              == nullptr ) {

        return false;
    }
    return true;
  }
    
  virtual void display()
  {
    int width  = 0;
    int height = 0;
    validateClientSize(width, height);
    if ( !ready() ) {
      return;
    }
      
    try {
      DirectXGISwapChain3*    swapChain = getSwapChain3();
      Direct3D12CommandQueue* commandQueue = getCommandQueue();
        
      setDirectXTransformLight();

      frameIndex = swapChain -> getCurrentBackBufferIndex();
        
      graphicsCommandList->startRendering(renderTargetView->getResource(frameIndex));

      graphicsCommandList->setDescriptorHeap(*commonDescriptorHeap);

      graphicsCommandList->setGraphicsRootSignature(*rootSignature);

      graphicsCommandList->setPipelineState(*pipelineState);
        
      graphicsCommandList->setGraphicsRootDescriptorTable(CBV_HANDLE, 
                commonDescriptorHeap->getGPUHandle(CBV_HANDLE));

      graphicsCommandList-> setRSViewport(0, 0, width, height);

      graphicsCommandList-> setRSScissorRect(0, 0, width, height);

      D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = renderTargetView->getHandle(frameIndex);
                 
      graphicsCommandList->clearRenderTargetView(rtvHandle, XMColor(0.2f, 0.2f, 0.6f, 1.0f));

      D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = *depthStencilView;
        
      graphicsCommandList->clearDepthStencilView(dsvHandle, D3D12_CLEAR_FLAG_DEPTH);
        
      graphicsCommandList->setOMRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
       
      //Draw the torus on the worldViewProjection by solid mode. 
      torus->drawIndexedInstanced(graphicsCommandList);

      graphicsCommandList->endRendering();
          
      commandQueue->executeCommandList(*graphicsCommandList);

      swapChain->present(1, 0);
        
      synchronizer->waitForCompletion();
       
    } catch (Exception& ex) {
      caught(ex);
    }
  }
    
  virtual void resize(int width, int height)
  {
    Direct3D12Device*   device = getD3D12Device();
    DirectXGISwapChain3* swapChain = getSwapChain3();
    if (device           == NULL || 
        swapChain        == NULL) { 
      return ;
    }
   
    int cw = 0;
    int ch = 0;
      
    try {
      if (chooser != nullptr) {
        cw = chooser->get(XmNwidth);
        ch = chooser->get(XmNheight);
        chooser -> reshape(width - cw-10, 10, cw, ch);
      }

      deleteViews();
        
      swapChain->resizeBuffers(width, height);

      createViews(*device, *swapChain, width, height);
        
    } catch (Exception& ex) {
      caught(ex);
    }
  }

  long picked(Event& event)
  {
    COLORREF rgb = (COLORREF)event.getLParam();
    BYTE r = GetRValue(rgb);
    BYTE g = GetGValue(rgb);
    BYTE b = GetBValue(rgb);

    lightColor.x = (float)r / (float)0xff;
    lightColor.y = (float)g / (float)0xff;
    lightColor.z = (float)b / (float)0xff;
    lightColor.w = 1.0f;
    
    invalidateAll();
    update();

    return 0L;
  }

  virtual void keyDown(Event& event)
  {
    WPARAM wparam = event.getWParam();
    switch (wparam) {
    case VK_LEFT:
      angle -= 0.1f;
      invalidateAll();
      update();
      break;

    case VK_RIGHT:
      angle += 0.1f;
      invalidateAll();
      update();
      break;
    }
  }

public:
  MainView(Application& applet, const TCHAR* name, Args& args)
  :DirectX3D12MainView(applet, name, args),
    angle(1.0),
    frameIndex(0),
    directory(_T(""))
  {
    // Change a style of this window to be no-captiion.    
    LONG style = getWindowLong(GWL_STYLE);
    style &= ~WS_CAPTION;
    setWindowLong(GWL_STYLE, style| WS_POPUP);

    directory = (const TCHAR*)args.get(XmNapplicationDirectory);
      
    lightColor = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);

    //Create a quit pushbutton.
    Args ar;
    ar.set(XmNx, 10);
    ar.set(XmNy, 10);
    ar.set(XmNwidth, 120);
    ar.set(XmNheight, 30);
    quit = new PushButton(this, _T("QUIT"), ar);
    quit->addCallback(XmNactivateCallback, this,
        (Callback)&MainView::exit, NULL);
    
   //Create a colorChooser.
    ar.reset();
    ar.set(XmNstyle, WS_VISIBLE);
    chooser = new ColorChooser(this, NULL, ar);
    addEventHandler(WM_COLORCHOOSER_PICKED, this,
          (Handler)&MainView::picked, NULL);
    
    post(WM_COLORCHOOSER_PICKED, 0, RGB(0xff, 0xff, 0xff));
    
    postResizeRequest();
  }
    
  ~MainView()
  {
  }

};
}

//////////////////////////////////////////////
//
void  Main(int argc, TCHAR** argv)
{
  ModuleFileName module(argv[0]);
  const TCHAR* directory = module.getDirectory();
  const TCHAR* appClass =  module.getAppName(); 

  try {    
    SystemMetrics metrics;
    int width  = metrics.fullScreenWidth();
    int height = metrics.fullScreenHeight();

    Application applet(appClass, argc, argv);

    Args args;
    args.set(XmNx, 0);
    args.set(XmNy, 0);
    args.set(XmNwidth,  width);
    args.set(XmNheight, height);
    args.set(XmNapplicationDirectory, directory);

    MainView mainView(applet, appClass, args);

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


Last modified: 1 Feb 2017

Copyright (c) 2017 Antillia.com ALL RIGHTS RESERVED.