#ifndef DXD3D
#define DXD3D
#include <windows.h>
#include <d3d10.h>
#include <d3dx10.h>
#include "dxGeometry.h"
#include <vector>
//Macros for releasing objects safely
#define SAFE_DELETE(p) { if (p) { delete (p); (p)=NULL; } }
#define SAFE_DELETE_SHUTDOWN(p) { if (p) { (p)->shutDown(); delete(p); (p)=NULL; } }
#define RETURN_FALSE_OBJECT(p) { if (!p) { return false; } }
/**************************************************************************************
* dxD3D
* Simon GL Jordan
* Description:
* Initialises DirectX10 and resources
* Stands as the bare minimum for a project to work, can be expanded or manipulated to
* meet the projects needs
*
* Note:
* I tried to retain structure of the frame work of DirectX10 which is defined in dxSystem::initialise()
* Create device -> Input assembly stage -> Rasterizer stage setup -> Output merger stage
*
* Use:
* Begin() and End() are called in the render() function inside dxSystem to start and stop
* rendering of data
*
* Future Implementations:
* 1.A shader loader could be extracted from loadShadersAndCreateInputLayouts()
* 2.Implement the camera to set up matrices and render scene
*
***************************************************************************************/
class dxD3D
{
private:
HWND* hWnd;
IDXGISwapChain* m_swapChain;
ID3D10Device* m_pD3DDevice;
ID3D10RenderTargetView* m_renderTargetView;
ID3D10Texture2D* m_depthStencilBuffer;
ID3D10DepthStencilState* m_depthStencilState;
ID3D10DepthStencilView* m_depthStencilView;
ID3D10RasterizerState* m_rasterState;
ID3D10Texture2D* pBackBuffer;
D3D10_TEXTURE2D_DESC descDepth;
D3D10_DEPTH_STENCIL_VIEW_DESC descDSV;
D3D10_DEPTH_STENCIL_DESC depthStencilDesc;
ID3D10EffectMatrixVariable* pViewMatrixEffectVariable;
ID3D10EffectMatrixVariable* pProjectionMatrixEffectVariable;
ID3D10EffectMatrixVariable* pWorldMatrixEffectVariable;
ID3D10InputLayout* pVertexLayout;
ID3D10Effect* pBasicEffect;
ID3D10EffectTechnique* pBasicTechnique;
D3D10_RASTERIZER_DESC rasterDesc;
ID3D10RasterizerState* pRS;
DXGI_SWAP_CHAIN_DESC swapChainDesc;
D3D10_TECHNIQUE_DESC techDesc;
public:
dxD3D();
dxD3D(const dxD3D&);
~dxD3D();
bool createSwapChainAndDevice( UINT width, UINT height);
bool loadShadersAndCreateInputLayouts();
void createViewports( UINT width, UINT height );
bool initRasterizerState(){
bool result;
// Setup the raster description which will determine how and what polygons will be drawn.
rasterDesc.AntialiasedLineEnable = false;
rasterDesc.CullMode = D3D10_CULL_BACK;
rasterDesc.DepthBias = 0;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = true;
rasterDesc.FillMode = D3D10_FILL_SOLID;
rasterDesc.FrontCounterClockwise = false;
rasterDesc.MultisampleEnable = false;
rasterDesc.ScissorEnable = false;
rasterDesc.SlopeScaledDepthBias = 0.0f;
// Create the rasterizer state from the description we just filled out.
result = m_pD3DDevice->CreateRasterizerState( &rasterDesc, &pRS);
if(FAILED(result))
{
MessageBox(NULL, L"Failed to create razterizer state", NULL, NULL);
return false;
}
m_pD3DDevice->RSSetState(pRS);
return true;
}//Inline for greater speed
bool createRenderTargetsAndDepthBuffer( UINT width, UINT height );
void beginScene(float red, float green, float blue, float alpha){
float colour[4];
// Setup the color to clear the buffer to.
colour[0] = red;
colour[1] = green;
colour[2] = blue;
colour[3] = alpha;
// Clear the back buffer.
m_pD3DDevice->ClearRenderTargetView(m_renderTargetView, colour);
// Clear the depth buffer.
m_pD3DDevice->ClearDepthStencilView(m_depthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0);
}
void endScene(){
// Present as fast as possible.
m_swapChain->Present(0, 0);
}
void shutDown();
};
dxD3D::dxD3D(): m_pD3DDevice(NULL),
m_swapChain(NULL),
m_renderTargetView(NULL),
m_depthStencilBuffer(0),
m_depthStencilState(0),
m_depthStencilView(0),
m_rasterState(0)
{}
dxD3D::dxD3D(const dxD3D& other)
{}
dxD3D::~dxD3D()
{}
bool dxD3D::createSwapChainAndDevice( UINT width, UINT height )
{
HRESULT result;
//Set up DX swap chain
//--------------------------------------------------------------
//set buffer dimensions and format
// Initialize the swap chain description.
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
// Set to a single back buffer.
swapChainDesc.BufferCount = 1;
// Set the width and height of the back buffer.
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
// Set regular 32-bit surface for the back buffer.
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
//set refresh rate
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
// Set the usage of the back buffer.
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
// Turn multisampling off.
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
// Set the handle for the window to render to.
swapChainDesc.OutputWindow = *hWnd;
// Set the scan line ordering and scaling to unspecified.
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// Discard the back buffer contents after presenting.
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
// Don't set the advanced flags.
swapChainDesc.Flags = 0;
if(FAILED(result))
{
MessageBox(NULL, L"Failed", NULL, NULL);
return false;
}
//Create the D3D device
//--------------------------------------------------------------
result = D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION,
&swapChainDesc, &m_swapChain, &m_pD3DDevice);
if(FAILED(result))
{
MessageBox(NULL, L"Failed to create the D3D device", NULL, NULL);
return false;
}
return true;
}
bool dxD3D::createRenderTargetsAndDepthBuffer(UINT width, UINT height)
{
HRESULT result;
result = m_swapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer);
if(FAILED(result))
{
MessageBox(NULL, L"Failed to get the buffer", NULL, NULL);
return false;
}
// Create the render target view with the back buffer pointer.
result = m_pD3DDevice->CreateRenderTargetView(pBackBuffer, NULL, &m_renderTargetView);
if(FAILED(result))
{
MessageBox(NULL, L"Failed to create the render target view", NULL, NULL);
return false;
}
pBackBuffer->Release();
pBackBuffer = 0;
descDepth.Width = width;
descDepth.Height = height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D32_FLOAT;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D10_USAGE_DEFAULT;
descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
// Create the texture for the depth buffer using the filled out description.
result = m_pD3DDevice->CreateTexture2D(&descDepth, NULL, &m_depthStencilBuffer);
if(FAILED(result))
{
return false;
MessageBox(NULL, L"Failed to create the texture for the depth buffer", NULL, NULL);
}
// Initialize the description of the stencil state.
ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc));
// Set up the description of the stencil state.
depthStencilDesc.DepthEnable = true;
depthStencilDesc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
depthStencilDesc.DepthFunc = D3D10_COMPARISON_LESS;
depthStencilDesc.StencilEnable = true;
depthStencilDesc.StencilReadMask = 0xFF;
depthStencilDesc.StencilWriteMask = 0xFF;
// Stencil operations if pixel is front-facing.
depthStencilDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;
depthStencilDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
depthStencilDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
// Stencil operations if pixel is back-facing.
depthStencilDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;
depthStencilDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
depthStencilDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
// Create the depth stencil state.
result = m_pD3DDevice->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState);
if(FAILED(result))
{
MessageBox(NULL, L"Failed to create the depth stencil state", NULL, NULL);
return false;
}
// Initialise the depth stencil view.
ZeroMemory(&descDepth, sizeof(descDepth));
// Set up the depth stencil view description.
descDSV.Format = descDepth.Format;
descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
// Create the depth stencil view.
result = m_pD3DDevice->CreateDepthStencilView(m_depthStencilBuffer, &descDSV, &m_depthStencilView);
if(FAILED(result))
{
MessageBox(NULL, L"Failed to create the depth stencil view", NULL, NULL);
return false;
}
// Bind the render target view and depth stencil buffer to the output render pipeline.
m_pD3DDevice->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);
return true;
}
bool dxD3D::loadShadersAndCreateInputLayouts()
{
//technique
HRESULT result;
result = D3DX10CreateEffectFromFile(L"./basicEffect.fx",
NULL, NULL,
"fx_4_0",
D3D10_SHADER_ENABLE_STRICTNESS,
0,
m_pD3DDevice,
NULL,
NULL,
&pBasicEffect,
NULL,
NULL );
if(!result)
{
MessageBox(NULL, L"Failed to load effect file", NULL, NULL);
return false;
}
pBasicTechnique = pBasicEffect->GetTechniqueByName("render");
if(!pBasicTechnique)
{
MessageBox(NULL, L"Failed to retrieve technique", NULL, NULL);
return false;
}
//create matrix effect pointers
pViewMatrixEffectVariable = pBasicEffect->GetVariableByName( "View" )->AsMatrix();
pProjectionMatrixEffectVariable = pBasicEffect->GetVariableByName( "Projection" )->AsMatrix();
pWorldMatrixEffectVariable = pBasicEffect->GetVariableByName( "World" )->AsMatrix();
//create input layout
D3D10_PASS_DESC PassDesc;
pBasicTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc );
// Create the input layout.
result = m_pD3DDevice->CreateInputLayout( vertexInputLayout,
2,
PassDesc.pIAInputSignature,
PassDesc.IAInputSignatureSize,
&pVertexLayout );
if(FAILED(result))
{
MessageBox(NULL, L"Failed to create the input layout", NULL, NULL);
return false;
}
// Set the input layout
m_pD3DDevice->IASetInputLayout( pVertexLayout );
//get technique description
pBasicTechnique->GetDesc( &techDesc );
return true;
}
void dxD3D::shutDown()
{
// Before shutting down set to windowed mode or when you release the swap chain it will throw an exception.
if(m_swapChain)
{
m_swapChain->SetFullscreenState(false, NULL);
}
if(m_rasterState)
{
m_rasterState->Release();
m_rasterState = 0;
}
if(m_depthStencilView)
{
m_depthStencilView->Release();
m_depthStencilView = 0;
}
if(m_depthStencilState)
{
m_depthStencilState->Release();
m_depthStencilState = 0;
}
if(m_depthStencilBuffer)
{
m_depthStencilBuffer->Release();
m_depthStencilBuffer = 0;
}
if(m_renderTargetView)
{
m_renderTargetView->Release();
m_renderTargetView = 0;
}
if(m_swapChain)
{
m_swapChain->Release();
m_swapChain = 0;
}
if(m_pD3DDevice)
{
m_pD3DDevice->Release();
m_pD3DDevice = 0;
}
}
#endif