SOL9 Sample: Direct3D12ScintillaStarSystem
|
1 Screenshot
2 Source code
/*
* Direct3D12ScintillaStarSystem.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/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/Direct3D12RootSignature.h>
#include <sol/direct3d12/Direct3D12GraphicsCommandList.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/Direct3DX12Sphere.h>
#include <sol/direct3d12/Direct3DX12Circle.h>
#include <sol/direct3d12/DirectXTransformLight.h>
#include <sol/direct3d12/DirectX3D12TimerThread.h>
#include "resource.h"
namespace SOL {
class MainView :public DirectX3D12MainView {
private:
static const int NUMBER_OF_SPHERES = 5;
static const int NUMBER_OF_PLANETS = 4;
static const int NUMBER_OF_CONSTANT_BUFFER_VIEWS = NUMBER_OF_SPHERES;
static const int NUMBER_OF_SHADER_RESOURCE_VIEWS = 1;
//Inner class starts.
class SimpleView :public DirectX3D12View {
private:
SmartPtr<Direct3D12CommandAllocator> commandAllocator;
SmartPtr<Direct3D12RenderTargetView> renderTargetView;
SmartPtr<Direct3D12DepthStencilView> depthStencilView;
SmartPtr<Direct3D12RootSignature> rootSignature;
SmartPtr<Direct3D12CommonDescriptorHeap> commonDescriptorHeap;
SmartPtr<Direct3D12TransformLightConstantBufferView> sunConstantBufferView;
SmartPtr<Direct3D12TransformLightConstantBufferView> planetConstantBufferViews[NUMBER_OF_PLANETS];
SmartPtr<Direct3D12GraphicsCommandList> graphicsCommandList;
SmartPtr<Direct3D12PipelineState> pipelineState;
SmartPtr<Direct3D12Synchronizer> synchronizer;
SmartPtr<Direct3DX12Sphere> sun;
SmartPtr<Direct3DX12Sphere> planets[NUMBER_OF_PLANETS];
SmartPtr<Direct3DX12Circle> orbits [NUMBER_OF_PLANETS];
UINT frameIndex;
SmartPtr<DirectX3D12TimerThread> timerThread;
int renderingInterval;
DirectXTransformLight sunWorldViewProjection;
DirectXTransformLight planetWorldViewProjections[NUMBER_OF_PLANETS];
float angles[NUMBER_OF_PLANETS];
StringT<TCHAR> directory;
static const int CIRCLE_ANGLE = 360;
private:
void createPipelineStates(ID3D12Device* device)
{
D3D12RasterizerDesc solid( D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE, true);
D3D12BlendDesc blendDesc;
UINT count = 0;
const D3D12_INPUT_ELEMENT_DESC* inputElements = sun->getInputElementDesc(count);
StringT<TCHAR> vsshaderFile = getShaderFilePath(directory, _T("VertexShader.cso"));
StringT<TCHAR> psshaderFile = getShaderFilePath(directory, _T("PixelShader.cso"));
//Create a pipelineState by using a new constructor(2017/01/10).
pipelineState = new Direct3D12PipelineState(
device,
*rootSignature,
inputElements,
count,
solid,
blendDesc,
vsshaderFile,
psshaderFile);
}
XMFLOAT3 getPlanetOrbitPosition(int pindex, float angle)
{
if (pindex >= 0 && pindex <NUMBER_OF_PLANETS) {
return orbits[pindex]->getOrbitPosition(angle);
} else {
throw IException("Invalid planet index.");
}
}
//Set the constantBufferView to the sun of sphere[0].
void setSunDirectXTransform()
{
int width = 0;
int height = 0;
getClientSize(width, height);
int index = 0;
try {
XMVECTOR eye = XMVectorSet(0.0f, 2.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);
sunWorldViewProjection.world = DirectXMatrix::rotationY((float)0.0f);
sunWorldViewProjection.view = DirectXMatrix::lookAtLH(eye, at, up);
sunWorldViewProjection.projection = DirectXMatrix::perspectiveFovLH( XM_PIDIV2*0.3f,
width / (FLOAT)height, 0.01f, 100.0f );
sunWorldViewProjection.lightDirection = XMFLOAT4( 0.0f, 1.0f, 0.0f, 1.0f );
sunWorldViewProjection.lightColor = XMFLOAT4(1.0f, 0.2f, 0.0f, 1.0f);
if (sunConstantBufferView) {
sunConstantBufferView->update(sunWorldViewProjection);
}
} catch (Exception& ex) {
caught(ex);
}
}
//Set a constantBufferView to each planet (index-th sphere).
void setPlanetDirectXTransform(int index, float angle)
{
int width = 0;
int height = 0;
getClientSize(width, height);
if (index >=0 && index < NUMBER_OF_PLANETS) {
try {
// Get a position on an orbit.
XMFLOAT3 position = getPlanetOrbitPosition(index, angle);
//Translate the position of the planet.
DirectXMatrix world = DirectXMatrix::scaling( 1.0f, 1.0f, 1.0f);
DirectXMatrix m = DirectXMatrix::translation(position.x, position.y, position.z);
world += m;
planetWorldViewProjections[index].world = world;
XMVECTOR eye = XMVectorSet(2.0f, 4.0f, -8.0f, 0.0f);
XMVECTOR at = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
XMVECTOR up = XMVectorSet(0.0f, 1.0f, 1.0f, 0.0f);
planetWorldViewProjections[index].view = DirectXMatrix::lookAtLH(eye, at, up);
planetWorldViewProjections[index].projection = DirectXMatrix::perspectiveFovLH( XM_PIDIV2*0.3f,
width / (FLOAT)height, 0.01f, 100.0f );
planetWorldViewProjections[index].lightDirection = XMFLOAT4( 0.0f, -0.0f, 1.0f, 1.0f );
XMFLOAT4 planetColors[NUMBER_OF_PLANETS] = {
XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f),
XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f),
XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f),
XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f)
};
planetWorldViewProjections[index].lightColor = planetColors[index];
if (planetConstantBufferViews[index]) {
planetConstantBufferViews[index]->update(planetWorldViewProjections[index]);
}
} 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)
graphicsCommandList->setOMRenderTargets(0, nullptr, FALSE, nullptr);
renderTargetView = NULL;
depthStencilView = NULL;
}
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);
renderTargetView = new Direct3D12RenderTargetView(*device, *swapChain);
depthStencilView = new Direct3D12DepthStencilView(*device, width, height);
graphicsCommandList = new Direct3D12GraphicsCommandList(*device, *commandAllocator);
//1 Create rootSignature specified parameters:
// NUMBER_OF_CONSTANT_BUFFER_VIEWS and NUMBER_OF_SHADER_RESOURCE_VIEWS
rootSignature = new Direct3D12RootSignature(*device,
NUMBER_OF_CONSTANT_BUFFER_VIEWS, NUMBER_OF_SHADER_RESOURCE_VIEWS);
//2 Create commonDescriptorHeap of size of NUMBER_OF_SPHERES.
commonDescriptorHeap = new Direct3D12CommonDescriptorHeap(*device, NUMBER_OF_SPHERES);
//3 Create constantBufferViews for the spheres of NUMBER_OF_SPHERES.
sunConstantBufferView = new Direct3D12TransformLightConstantBufferView(*device,
commonDescriptorHeap->getCPUHandle(CBV_HANDLE));
for (size_t i = 0; i < NUMBER_OF_PLANETS; i++) {
planetConstantBufferViews[i] = new Direct3D12TransformLightConstantBufferView(*device,
commonDescriptorHeap->getCPUHandle(CBV_HANDLE + 1 + i));
}
synchronizer = new Direct3D12Synchronizer(*device, *commandQueue);
//4 Create a renderTargetView and depthStencilView
createViews(*device, *swapChain, width, height);
//5 Create orbits for 4 planets.
int index = 0;
orbits[index++] = new Direct3DX12Circle(*device, 0.0f, 0.0f, 0.0f, 1.9f);
orbits[index++] = new Direct3DX12Circle(*device, 0.0f, 0.0f, 0.0f, 2.6f);
orbits[index++] = new Direct3DX12Circle(*device, 0.0f, 0.0f, 0.0f, 3.4f);
orbits[index] = new Direct3DX12Circle(*device, 0.0f, 0.0f, 0.0f, 3.9f);
//6 Creat a shperes for sun.
sun = new Direct3DX12Sphere(*device, 0.38f, 20, 20);
//7 Create 4 spheres for planets.
index = 0;
planets[index++] = new Direct3DX12Sphere(*device, 0.10f, 20, 20);
planets[index++] = new Direct3DX12Sphere(*device, 0.18f, 20, 20);
planets[index++] = new Direct3DX12Sphere(*device, 0.18f, 20, 20);
planets[index] = new Direct3DX12Sphere(*device, 0.12f, 20, 20);
//8 Create a pipelineState from the sphere.
createPipelineStates(*device);
//9 Set world, view and projection to the constantBuffer.
setSunDirectXTransform();
for (size_t i = 0; i < NUMBER_OF_PLANETS; i++) {
setPlanetDirectXTransform(i, angles[i]);
}
//10 Create a rendering TimerThread.
timerThread = new DirectX3D12TimerThread(this, renderingInterval, true); // queuing
timerThread -> start();
} 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 ||
graphicsCommandList == nullptr ||
pipelineState == nullptr ||
timerThread == 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();
static const float INCREMENT[NUMBER_OF_PLANETS] = { 2.0f, 1.5f, 1.0f, 0.5f };
for (int i = 0; i < NUMBER_OF_PLANETS; i++) {
if (angles[i] < CIRCLE_ANGLE - INCREMENT[i]) {
angles[i] += INCREMENT[i];
}
else {
angles[i] = INCREMENT[i];
}
}
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 -> setRSViewport(0, 0, width, height);
graphicsCommandList -> setRSScissorRect(0, 0, 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, D3D12_CLEAR_FLAG_DEPTH);
graphicsCommandList->setOMRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
//Draw the sun.
setSunDirectXTransform();
graphicsCommandList->setGraphicsRootDescriptorTable(CBV_HANDLE,
commonDescriptorHeap->getGPUHandle(CBV_HANDLE));
sun -> drawIndexedInstanced(graphicsCommandList);
//Draw the planets on the worldViewProjection.
for (size_t i = 0; i<NUMBER_OF_PLANETS; i++) {
setPlanetDirectXTransform(i, angles[i]);
graphicsCommandList->setGraphicsRootDescriptorTable(CBV_HANDLE,
commonDescriptorHeap->getGPUHandle(CBV_HANDLE + 1 + i));
planets[i] -> 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);
}
}
public:
//Constructor
SimpleView(DirectX3D12MainView* parent, const TCHAR* name, Args& args)
:DirectX3D12View(parent, name, args),
//angle (30),
frameIndex(0),
directory(_T("")),
renderingInterval(100)
{
for (size_t i = 0; i < NUMBER_OF_PLANETS; i++) {
angles[i] = 30.0f * i;
}
directory = (const TCHAR*)args.get(XmNapplicationDirectory);
renderingInterval = (int)args.get(XmNrenderingInterval);
postResizeRequest();
}
~SimpleView()
{
}
};
// Inner class ends.
private:
SmartPtr<SimpleView> view;
public:
/**
* Constructor
*/
MainView(Application& applet, const TCHAR* name, Args& args)
:DirectX3D12MainView(applet, name,
args.set(XmNstyle, (ulong)WS_CLIPCHILDREN|WS_CLIPSIBLINGS) ),
view(NULL)
{
const TCHAR* directory = (const TCHAR*)args.get(XmNapplicationDirectory);
int renderingInterval = (int) args.get(XmNrenderingInterval);
// 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(XmNrenderingInterval, renderingInterval);
ar.set(XmNstyle, WS_BORDER|WS_CHILD|WS_VISIBLE);
view = new SimpleView(this, _T(""), ar);
// 3 Post a resize request to this MainView.
postResizeRequest();
}
public:
~MainView()
{
}
void resize(int width, int height)
{
if (view != nullptr) {
view -> reshape(0, 0, width, height);
}
}
};
}
//////////////////////////////////////////////
//
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, 480);
args.set(XmNheight, 480);
args.set(XmNapplicationDirectory, directory);
args.set(XmNrenderingInterval, 30); //30ms
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.