SOL9 Sample: Direct3D12SphereWithColorEyeAndLightPositioner

SOL9 2.0 Samples

1 Screenshot


2 Source code

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


// 2016/10/10
// 2017/01/28 Updated to use ModuleFileName class and caught macro.

#define COMMONCONTROLS_V6
#define WIN10

#include <sol/Vector3.h>
#include <sol/ColorPositioner.h>
#include <sol/EyePositioner.h>
#include <sol/LightPositioner.h>

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

#include <sol/direct3d12/Direct3D12TransformLightConstantBufferView.h>

#include <sol/direct3d12/Direct3D12ConstantBufferViewRootSignature.h>
#include <sol/direct3d12/Direct3D12GraphicsCommandList.h>

#include <sol/direct3d12/Direct3D12PipelineState.h>

#include <sol/direct3d12/D3D12RasterizerDesc.h>
#include <sol/direct3d12/D3D12AdditiveBlendDesc.h>
#include <sol/direct3d12/D3D12AlphaBlendDesc.h>

#include <sol/direct3d12/D3D12GraphicsPipelineStateDesc.h>
#include <sol/direct3d12/D3D12ResourceBarrier.h>
#include <sol/direct3d12/D3D12TransformLight.h>

#include <sol/direct3d12/D3D12GraphicsPipelineStateDesc.h>

#include <sol/direct3d12/Direct3D12Synchronizer.h>

#include <sol/direct3d12/Direct3DX12Sphere.h>
#include <sol/direct3d12/DirectXTransformLight.h>

#include "resource.h"

namespace SOL {
  
class MainView :public DirectX3D12MainView {
  //Inner class 
  class SimpleView :public DirectX3D12View {
  private:
    SmartPtr<Direct3D12CommandAllocator>     commandAllocator;
    
    SmartPtr<Direct3D12RenderTargetView>     renderTargetView;
    
    SmartPtr<Direct3D12DepthStencilView>     depthStencilView;

    SmartPtr<Direct3D12RootSignature>        rootSignature;
    
    SmartPtr<Direct3D12CommonDescriptorHeap> commonDescriptorHeap;
    
    SmartPtr<Direct3D12TransformLightConstantBufferView>   constantBufferView;
    
    SmartPtr<Direct3D12GraphicsCommandList>  graphicsCommandList;
    
    SmartPtr<Direct3D12PipelineState>        pipelineState;
    
    SmartPtr<Direct3D12Synchronizer>         synchronizer;
  
    SmartPtr<Direct3DX12Sphere>              sphere;
    
    UINT                            frameIndex;
        
    DirectXTransformLight           lightedConstantBuffer;
 
    float                           angle;
    
    StringT<TCHAR>                  directory;

    XMFLOAT4                        eye;
    XMFLOAT4                        at;
    XMFLOAT4                        up;
    XMFLOAT4                        lightColor;
    XMFLOAT4                        lightDirection;
    
  private:
        
    virtual void createPipelineState(ID3D12Device* device, Direct3DX12Shape* shape)
    {
      //Create a graphicPipelineStateDes.
      D3D12GraphicsPipelineStateDesc graphicsPipelineStateDesc(*rootSignature);

      UINT count = 0;
      const D3D12_INPUT_ELEMENT_DESC* inputElements = sphere->getInputElementDesc(count);
      
      D3D12RasterizerDesc  rasterDesc(
        D3D12_FILL_MODE_SOLID, 
        //D3D12_FILL_MODE_WIREFRAME,  
        D3D12_CULL_MODE_NONE, 
        true);

      D3D12AlphaBlendDesc       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 e = XMVectorSet(eye.x, eye.y, eye.z, 0.0f);
        XMVECTOR a = XMVectorSet(at.x, at.y, at.z, 0.0f);
        XMVECTOR u = XMVectorSet(up.x, up.y, up.z, 0.0f);

        lightedConstantBuffer.world      = DirectXMatrix::rotationY( angle );
        lightedConstantBuffer.view       = DirectXMatrix::lookAtLH( e, a,  u);
        lightedConstantBuffer.projection = DirectXMatrix::perspectiveFovLH( XM_PIDIV2*0.3f, width / (FLOAT)height, 0.01f, 100.0f );
        lightedConstantBuffer.lightDirection = lightDirection;
        lightedConstantBuffer.lightColor     = lightColor;
        
        if (constantBufferView) {
          constantBufferView->update( lightedConstantBuffer);
        }
      } catch (Exception& ex) {
        caught(ex);      
      }
    }
    
    //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()
    {
      graphicsCommandList->setOMRenderTargets(0, nullptr, FALSE, nullptr);
    
      renderTargetView = NULL;
      depthStencilView = NULL;
    }
    
  public:    
    virtual void initialize()
    {
      int width  = 0;
      int height = 0;
      validateClientSize(width, height);
      Direct3D12Device*    device    = getD3D12Device();
      DirectXGISwapChain3* swapChain = getSwapChain3();
      Direct3D12CommandQueue* commandQueue = getCommandQueue();
      
      try {
        
        commandAllocator         = new Direct3D12CommandAllocator(*device);

        graphicsCommandList      = new Direct3D12GraphicsCommandList(*device, *commandAllocator);

        //rootSignature            = new Direct3D12ConstantBufferViewRootSignature(*device);
        rootSignature            = new Direct3D12RootSignature(*device);

        commonDescriptorHeap     = new Direct3D12CommonDescriptorHeap(*device, 1);

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

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

        createViews(*device, *swapChain, width, height);
        
        //1 Create your own shape
        sphere                     = new Direct3DX12Sphere(*device, 1.0f, 30, 30);
        //2 Create a pipelineState from the cube.
        createPipelineState(*device, sphere);

        eye = XMFLOAT4(  0.0f,  1.0f, -8.0f,  0.0f );
        at  = XMFLOAT4(  0.0f,  0.0f,  0.0f,  0.0f );
        up  = XMFLOAT4(  0.0f,  1.0f,  0.0f,  0.0f );
        lightDirection = XMFLOAT4( -0.8f, 0.8f, 0.3f, 1.0f );
        lightColor     = XMFLOAT4(  0.3f, 0.8f, 0.0f, 1.0f );

        //3 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 ||
        sphere                     == 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();

        //constantBufferView -> update(lightedConstantBuffer);
        setDirectXTransformLight();

        commandAllocator    -> reset();
        
        graphicsCommandList -> reset(*commandAllocator, *pipelineState);
        
        frameIndex = swapChain -> getCurrentBackBufferIndex();
        
        D3D12ResourceBarrier barrier(renderTargetView->getResource(frameIndex));
        
        barrier.startRendering();

        graphicsCommandList->resourceBarrier(1, barrier);

        graphicsCommandList->setDescriptorHeap(*commonDescriptorHeap);

        graphicsCommandList->setGraphicsRootSignature(*rootSignature);

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

        graphicsCommandList-> setRSViewport(width, height);

        graphicsCommandList-> setRSScissorRect(width, height);

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

        D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = *depthStencilView;
        
        graphicsCommandList->clearDepthStencilView(dsvHandle);
        
        graphicsCommandList->setOMRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
        
        sphere -> drawIndexedInstanced(graphicsCommandList);

        barrier.endRendering();
        
        graphicsCommandList->resourceBarrier(1, barrier);

        graphicsCommandList->close();

        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 ;
      }
      
      try {
        deleteViews();
        
        swapChain->resizeBuffers(width, height);

        createViews(*device, *swapChain, width, height);
        
      } catch (Exception& ex) {
        caught(ex);
      }
    }
    
    void setLightColor(XMFLOAT4 color)
    {
      lightColor = color;
      setDirectXTransformLight();
      invalidateAll();
      update();
    }
    
  public:
    //Constructor
    SimpleView(DirectX3D12MainView* parent, const TCHAR* name, Args& args)
    :DirectX3D12View(parent, name, args),
    angle (0.6f),
    frameIndex(0),
    directory(_T(""))
    {
      directory = (const TCHAR*)args.get(XmNapplicationDirectory);
      
      postResizeRequest();
    }
    
    ~SimpleView()
    {
    }

    void setColorPosition(int x, int y, int z)
    {
      lightColor.x = (float)x / 255.0f;
      lightColor.y = (float)y / 255.0f;
      lightColor.z = (float)z / 255.0f;
      postRenderRequest();
    }
    
    void setEyePosition(int x, int y, int z)
    {
      eye.x = (float)x;
      eye.y = (float)y;
      eye.z = (float)z;
      postRenderRequest();
    }

    void setLightPosition(int x, int y, int z)
    {
      lightDirection.x = (float)x;
      lightDirection.y = (float)y;
      lightDirection.z = (float)z;
      postRenderRequest();
    }
  
  };
  // Inner class ends.
  
private:
  
  SmartPtr<SimpleView> view;
  SmartPtr<ColorPositioner> colorPositioner;
  SmartPtr<EyePositioner>   eyePositioner;
  SmartPtr<LightPositioner> lightPositioner;
    
public:
  virtual long colorPositionChanged(Event& event)
  {    
    view -> setColorPosition(colorPositioner->getX(), 
                           colorPositioner->getY(),
                           colorPositioner->getZ());
    
    return 0;
  }
  
  virtual long eyePositionChanged(Event& event)
  {    
    view -> setEyePosition(eyePositioner->getX(), 
                           eyePositioner->getY(),
                           eyePositioner->getZ());
    
    return 0;
  }

  virtual long lightPositionChanged(Event& event)
  {
    view -> setLightPosition(lightPositioner->getX(),
                             lightPositioner->getY(),
                             lightPositioner->getZ());
    return 0;
  }

  /**
   * Constructor
   */
  MainView(Application& applet, const TCHAR* name, Args& args)
  :DirectX3D12MainView(applet, name,
                 args.set(XmNstyle, (ulong)WS_CLIPCHILDREN|WS_CLIPSIBLINGS) )
  {
    const TCHAR* directory = (const TCHAR*)args.get(XmNapplicationDirectory);

    // 1 Restore the replacement of MainView 
    restorePlacement();

    // 2 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, (const TCHAR*)directory);

    ar.set(XmNstyle, WS_BORDER|WS_CHILD|WS_VISIBLE);
    view = new SimpleView(this, _T(""), ar);

   //3 ColorPositioner
    ar.reset();
    colorPositioner = new ColorPositioner(this, _T(""), ar);
    int red   = 42;
    int green = 30;
    int blue  = 225;
    colorPositioner->setThumbPosition(red, green, blue);
    view -> setColorPosition(red, green, blue);
    
    //4 Create EyePositioner
    ar.reset();
    ar.set(XmNminimum, 0);
    ar.set(XmNmaximum, 40);
    eyePositioner = new EyePositioner(this, _T(""), ar);
    int eyeX = 8;
    int eyeY = 3;
    int eyeZ = 5;
    
    eyePositioner->setThumbPosition(eyeX, eyeY, eyeZ);
    view -> setEyePosition(eyeX, eyeY, eyeZ);

    //5 Create LightPositioner
    ar.reset();
    ar.set(XmNminimum, 0);
    ar.set(XmNmaximum, 40);
    lightPositioner = new LightPositioner(this, _T(""), ar);
    int lightX = 5;
    int lightY = 0;
    int lightZ = 7;
    
    lightPositioner->setThumbPosition(lightX, lightY, lightZ);
    view -> setLightPosition(lightX, lightY, lightZ);

    //6 Add eventHandlers to handle positionChangeMessage for the positionas.
    addEventHandler(colorPositioner->getPositionChangedMessage(), this, 
      (Handler)&MainView::colorPositionChanged, NULL);

    addEventHandler(eyePositioner->getPositionChangedMessage(), this, 
      (Handler)&MainView::eyePositionChanged, NULL);

    addEventHandler(lightPositioner->getPositionChangedMessage(), this, 
      (Handler)&MainView::lightPositionChanged, NULL);

    //7 Post the position change messages.
    post(WM_COLOR_POSITION_CHANGED);

    post(WM_EYE_POSITION_CHANGED);

    post(WM_LIGHT_POSITION_CHANGED);

    // 8 Post a resize request to this MainView.
    postResizeRequest();
  }

public:
  ~MainView()
  {
  }
    
  long picked(Event& event)
  {
    COLORREF rgb = (COLORREF)event.getLParam();
    BYTE r = GetRValue(rgb);
    BYTE g = GetGValue(rgb);
    BYTE b = GetBValue(rgb);
    
    XMFLOAT4 lightColor;
    lightColor.x = (float)r/(float)0xff;
    lightColor.y = (float)g/(float)0xff;
    lightColor.z = (float)b/(float)0xff;
    lightColor.w = 1.0f;
    view->setLightColor(lightColor);
        
    return 0L;
  }

  long size(Event& event)
  {
    int w, h;
    event.getSize(w, h);
    if (view && colorPositioner && eyePositioner && lightPositioner) {
      int posw = colorPositioner->getDefaultWidth();
      int posh = lightPositioner->getDefaultHeight();

      view->reshape(0, 0, w - posw - 4, h);
      view->postResizeRequest(w - posw - 4, h);

      colorPositioner->reshape(w - posw - 2, 2, posw, posh);
      eyePositioner->reshape(w - posw - 2, 4 + posh, posw, posh);
      lightPositioner->reshape(w - posw - 2, 6 + posh * 2, posw, posh);
    }
    return 1L;
  }
  
};
}


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

  try {    
    Application applet(appClass, argc, argv);

    Args args;
    args.set(XmNwidth,  680);
    args.set(XmNheight, 480);
    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.