From 70c19f4619e92c9e0981907410acd443a3ed2ae0 Mon Sep 17 00:00:00 2001 From: axelpicou <115532798+axelpicou@users.noreply.github.com> Date: Wed, 20 Mar 2024 11:58:51 +0100 Subject: [PATCH] class d3d --- enginecustom/applicationclass.cpp | 32 ++ enginecustom/applicationclass.h | 4 +- enginecustom/d3dclass.cpp | 507 ++++++++++++++++++++++ enginecustom/d3dclass.h | 70 +++ enginecustom/enginecustom.vcxproj | 2 + enginecustom/enginecustom.vcxproj.filters | 6 + 6 files changed, 619 insertions(+), 2 deletions(-) create mode 100644 enginecustom/d3dclass.cpp create mode 100644 enginecustom/d3dclass.h diff --git a/enginecustom/applicationclass.cpp b/enginecustom/applicationclass.cpp index 2e18374..1b3d9ff 100644 --- a/enginecustom/applicationclass.cpp +++ b/enginecustom/applicationclass.cpp @@ -3,6 +3,7 @@ ApplicationClass::ApplicationClass() { + m_Direct3D = 0; } @@ -18,13 +19,31 @@ ApplicationClass::~ApplicationClass() bool ApplicationClass::Initialize(int screenWidth, int screenHeight, HWND hwnd) { + bool result; + + // Create and initialize the Direct3D object. + m_Direct3D = new D3DClass; + + result = m_Direct3D->Initialize(screenWidth, screenHeight, VSYNC_ENABLED, hwnd, FULL_SCREEN, SCREEN_DEPTH, SCREEN_NEAR); + if (!result) + { + MessageBox(hwnd, L"Could not initialize Direct3D", L"Error", MB_OK); + return false; + } return true; } void ApplicationClass::Shutdown() { + // Release the Direct3D object. + if (m_Direct3D) + { + m_Direct3D->Shutdown(); + delete m_Direct3D; + m_Direct3D = 0; + } return; } @@ -32,13 +51,26 @@ void ApplicationClass::Shutdown() bool ApplicationClass::Frame() { + bool result; + + // Render the graphics scene. + result = Render(); + if (!result) + { + return false; + } return true; } bool ApplicationClass::Render() { + // Clear the buffers to begin the scene. + m_Direct3D->BeginScene(0.5f, 0.5f, 0.5f, 1.0f); + + // Present the rendered scene to the screen. + m_Direct3D->EndScene(); return true; } \ No newline at end of file diff --git a/enginecustom/applicationclass.h b/enginecustom/applicationclass.h index 833acfb..d62822f 100644 --- a/enginecustom/applicationclass.h +++ b/enginecustom/applicationclass.h @@ -6,7 +6,7 @@ // INCLUDES // ////////////// #include - +#include "d3dclass.h" ///////////// // GLOBALS // @@ -31,7 +31,7 @@ private: bool Render(); private: - + D3DClass* m_Direct3D; }; #endif \ No newline at end of file diff --git a/enginecustom/d3dclass.cpp b/enginecustom/d3dclass.cpp new file mode 100644 index 0000000..e87bc65 --- /dev/null +++ b/enginecustom/d3dclass.cpp @@ -0,0 +1,507 @@ +//////////////////////////////////////////////////////////////////////////////// +// Filename: d3dclass.cpp +//////////////////////////////////////////////////////////////////////////////// +#include "d3dclass.h" + + +D3DClass::D3DClass() +{ + m_swapChain = 0; + m_device = 0; + m_deviceContext = 0; + m_renderTargetView = 0; + m_depthStencilBuffer = 0; + m_depthStencilState = 0; + m_depthStencilView = 0; + m_rasterState = 0; +} + + +D3DClass::D3DClass(const D3DClass& other) +{ +} + + +D3DClass::~D3DClass() +{ +} + + +bool D3DClass::Initialize(int screenWidth, int screenHeight, bool vsync, HWND hwnd, bool fullscreen, float screenDepth, float screenNear) +{ + HRESULT result; + IDXGIFactory* factory; + IDXGIAdapter* adapter; + IDXGIOutput* adapterOutput; + unsigned int numModes, i, numerator, denominator; + unsigned long long stringLength; + DXGI_MODE_DESC* displayModeList; + DXGI_ADAPTER_DESC adapterDesc; + int error; + DXGI_SWAP_CHAIN_DESC swapChainDesc; + D3D_FEATURE_LEVEL featureLevel; + ID3D11Texture2D* backBufferPtr; + D3D11_TEXTURE2D_DESC depthBufferDesc; + D3D11_DEPTH_STENCIL_DESC depthStencilDesc; + D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; + D3D11_RASTERIZER_DESC rasterDesc; + float fieldOfView, screenAspect; + + + // Store the vsync setting. + m_vsync_enabled = vsync; + + // Create a DirectX graphics interface factory. + result = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory); + if (FAILED(result)) + { + return false; + } + + // Use the factory to create an adapter for the primary graphics interface (video card). + result = factory->EnumAdapters(0, &adapter); + if (FAILED(result)) + { + return false; + } + + // Enumerate the primary adapter output (monitor). + result = adapter->EnumOutputs(0, &adapterOutput); + if (FAILED(result)) + { + return false; + } + + // Get the number of modes that fit the DXGI_FORMAT_R8G8B8A8_UNORM display format for the adapter output (monitor). + result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL); + if (FAILED(result)) + { + return false; + } + + // Create a list to hold all the possible display modes for this monitor/video card combination. + displayModeList = new DXGI_MODE_DESC[numModes]; + if (!displayModeList) + { + return false; + } + + // Now fill the display mode list structures. + result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList); + if (FAILED(result)) + { + return false; + } + + // Now go through all the display modes and find the one that matches the screen width and height. + // When a match is found store the numerator and denominator of the refresh rate for that monitor. + for (i = 0; i < numModes; i++) + { + if (displayModeList[i].Width == (unsigned int)screenWidth) + { + if (displayModeList[i].Height == (unsigned int)screenHeight) + { + numerator = displayModeList[i].RefreshRate.Numerator; + denominator = displayModeList[i].RefreshRate.Denominator; + } + } + } + + // Get the adapter (video card) description. + result = adapter->GetDesc(&adapterDesc); + if (FAILED(result)) + { + return false; + } + + // Store the dedicated video card memory in megabytes. + m_videoCardMemory = (int)(adapterDesc.DedicatedVideoMemory / 1024 / 1024); + + // Convert the name of the video card to a character array and store it. + error = wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128); + if (error != 0) + { + return false; + } + + // Release the display mode list. + delete[] displayModeList; + displayModeList = 0; + + // Release the adapter output. + adapterOutput->Release(); + adapterOutput = 0; + + // Release the adapter. + adapter->Release(); + adapter = 0; + + // Release the factory. + factory->Release(); + factory = 0; + + // 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 = screenWidth; + swapChainDesc.BufferDesc.Height = screenHeight; + + // Set regular 32-bit surface for the back buffer. + swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + + // Set the refresh rate of the back buffer. + if (m_vsync_enabled) + { + swapChainDesc.BufferDesc.RefreshRate.Numerator = numerator; + swapChainDesc.BufferDesc.RefreshRate.Denominator = denominator; + } + else + { + swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; + swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; + } + + // Set the usage of the back buffer. + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + + // Set the handle for the window to render to. + swapChainDesc.OutputWindow = hwnd; + + // Turn multisampling off. + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + + // Set to full screen or windowed mode. + if (fullscreen) + { + swapChainDesc.Windowed = false; + } + else + { + swapChainDesc.Windowed = true; + } + + // 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; + + // Set the feature level to DirectX 11. + featureLevel = D3D_FEATURE_LEVEL_11_0; + + // Create the swap chain, Direct3D device, and Direct3D device context. + result = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1, + D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, NULL, &m_deviceContext); + if (FAILED(result)) + { + return false; + } + + // Get the pointer to the back buffer. + result = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr); + if (FAILED(result)) + { + return false; + } + + // Create the render target view with the back buffer pointer. + result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView); + if (FAILED(result)) + { + return false; + } + + // Release pointer to the back buffer as we no longer need it. + backBufferPtr->Release(); + backBufferPtr = 0; + + // Initialize the description of the depth buffer. + ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); + + // Set up the description of the depth buffer. + depthBufferDesc.Width = screenWidth; + depthBufferDesc.Height = screenHeight; + depthBufferDesc.MipLevels = 1; + depthBufferDesc.ArraySize = 1; + depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + depthBufferDesc.SampleDesc.Count = 1; + depthBufferDesc.SampleDesc.Quality = 0; + depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; + depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + depthBufferDesc.CPUAccessFlags = 0; + depthBufferDesc.MiscFlags = 0; + + // Create the texture for the depth buffer using the filled out description. + result = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer); + if (FAILED(result)) + { + return false; + } + + // Initialize the description of the stencil state. + ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); + + // Set up the description of the stencil state. + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; + + depthStencilDesc.StencilEnable = true; + depthStencilDesc.StencilReadMask = 0xFF; + depthStencilDesc.StencilWriteMask = 0xFF; + + // Stencil operations if pixel is front-facing. + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + // Stencil operations if pixel is back-facing. + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + // Create the depth stencil state. + result = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState); + if (FAILED(result)) + { + return false; + } + + // Set the depth stencil state. + m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1); + + // Initialize the depth stencil view. + ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); + + // Set up the depth stencil view description. + depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilViewDesc.Texture2D.MipSlice = 0; + + // Create the depth stencil view. + result = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView); + if (FAILED(result)) + { + return false; + } + + // Bind the render target view and depth stencil buffer to the output render pipeline. + m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView); + + // Setup the raster description which will determine how and what polygons will be drawn. + rasterDesc.AntialiasedLineEnable = false; + rasterDesc.CullMode = D3D11_CULL_BACK; + rasterDesc.DepthBias = 0; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = true; + rasterDesc.FillMode = D3D11_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_device->CreateRasterizerState(&rasterDesc, &m_rasterState); + if (FAILED(result)) + { + return false; + } + + // Now set the rasterizer state. + m_deviceContext->RSSetState(m_rasterState); + + // Setup the viewport for rendering. + m_viewport.Width = (float)screenWidth; + m_viewport.Height = (float)screenHeight; + m_viewport.MinDepth = 0.0f; + m_viewport.MaxDepth = 1.0f; + m_viewport.TopLeftX = 0.0f; + m_viewport.TopLeftY = 0.0f; + + // Create the viewport. + m_deviceContext->RSSetViewports(1, &m_viewport); + + // Setup the projection matrix. + fieldOfView = 3.141592654f / 4.0f; + screenAspect = (float)screenWidth / (float)screenHeight; + + // Create the projection matrix for 3D rendering. + m_projectionMatrix = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, screenNear, screenDepth); + + // Initialize the world matrix to the identity matrix. + m_worldMatrix = XMMatrixIdentity(); + + // Create an orthographic projection matrix for 2D rendering. + m_orthoMatrix = XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, screenNear, screenDepth); + + return true; +} + + +void D3DClass::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_deviceContext) + { + m_deviceContext->Release(); + m_deviceContext = 0; + } + + if (m_device) + { + m_device->Release(); + m_device = 0; + } + + if (m_swapChain) + { + m_swapChain->Release(); + m_swapChain = 0; + } + + return; +} + + +void D3DClass::BeginScene(float red, float green, float blue, float alpha) +{ + float color[4]; + + + // Setup the color to clear the buffer to. + color[0] = red; + color[1] = green; + color[2] = blue; + color[3] = alpha; + + // Clear the back buffer. + m_deviceContext->ClearRenderTargetView(m_renderTargetView, color); + + // Clear the depth buffer. + m_deviceContext->ClearDepthStencilView(m_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0); + + return; +} + + +void D3DClass::EndScene() +{ + // Present the back buffer to the screen since rendering is complete. + if (m_vsync_enabled) + { + // Lock to screen refresh rate. + m_swapChain->Present(1, 0); + } + else + { + // Present as fast as possible. + m_swapChain->Present(0, 0); + } + + return; +} + + +ID3D11Device* D3DClass::GetDevice() +{ + return m_device; +} + + +ID3D11DeviceContext* D3DClass::GetDeviceContext() +{ + return m_deviceContext; +} + + +void D3DClass::GetProjectionMatrix(XMMATRIX& projectionMatrix) +{ + projectionMatrix = m_projectionMatrix; + return; +} + + +void D3DClass::GetWorldMatrix(XMMATRIX& worldMatrix) +{ + worldMatrix = m_worldMatrix; + return; +} + + +void D3DClass::GetOrthoMatrix(XMMATRIX& orthoMatrix) +{ + orthoMatrix = m_orthoMatrix; + return; +} + + +void D3DClass::GetVideoCardInfo(char* cardName, int& memory) +{ + strcpy_s(cardName, 128, m_videoCardDescription); + memory = m_videoCardMemory; + return; +} + + +void D3DClass::SetBackBufferRenderTarget() +{ + // Bind the render target view and depth stencil buffer to the output render pipeline. + m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView); + + return; +} + + +void D3DClass::ResetViewport() +{ + // Set the viewport. + m_deviceContext->RSSetViewports(1, &m_viewport); + + return; +} \ No newline at end of file diff --git a/enginecustom/d3dclass.h b/enginecustom/d3dclass.h new file mode 100644 index 0000000..df75750 --- /dev/null +++ b/enginecustom/d3dclass.h @@ -0,0 +1,70 @@ +//////////////////////////////////////////////////////////////////////////////// +// Filename: d3dclass.h +//////////////////////////////////////////////////////////////////////////////// +#ifndef _D3DCLASS_H_ +#define _D3DCLASS_H_ + + +///////////// +// LINKING // +///////////// +#pragma comment(lib, "d3d11.lib") +#pragma comment(lib, "dxgi.lib") +#pragma comment(lib, "d3dcompiler.lib") + + +////////////// +// INCLUDES // +////////////// +#include +#include +using namespace DirectX; + + +//////////////////////////////////////////////////////////////////////////////// +// Class name: D3DClass +//////////////////////////////////////////////////////////////////////////////// +class D3DClass +{ +public: + D3DClass(); + D3DClass(const D3DClass&); + ~D3DClass(); + + bool Initialize(int, int, bool, HWND, bool, float, float); + void Shutdown(); + + void BeginScene(float, float, float, float); + void EndScene(); + + ID3D11Device* GetDevice(); + ID3D11DeviceContext* GetDeviceContext(); + + void GetProjectionMatrix(XMMATRIX&); + void GetWorldMatrix(XMMATRIX&); + void GetOrthoMatrix(XMMATRIX&); + + void GetVideoCardInfo(char*, int&); + + void SetBackBufferRenderTarget(); + void ResetViewport(); + +private: + bool m_vsync_enabled; + int m_videoCardMemory; + char m_videoCardDescription[128]; + IDXGISwapChain* m_swapChain; + ID3D11Device* m_device; + ID3D11DeviceContext* m_deviceContext; + ID3D11RenderTargetView* m_renderTargetView; + ID3D11Texture2D* m_depthStencilBuffer; + ID3D11DepthStencilState* m_depthStencilState; + ID3D11DepthStencilView* m_depthStencilView; + ID3D11RasterizerState* m_rasterState; + XMMATRIX m_projectionMatrix; + XMMATRIX m_worldMatrix; + XMMATRIX m_orthoMatrix; + D3D11_VIEWPORT m_viewport; +}; + +#endif \ No newline at end of file diff --git a/enginecustom/enginecustom.vcxproj b/enginecustom/enginecustom.vcxproj index 2ab0ec6..71dcc8c 100644 --- a/enginecustom/enginecustom.vcxproj +++ b/enginecustom/enginecustom.vcxproj @@ -20,12 +20,14 @@ + + diff --git a/enginecustom/enginecustom.vcxproj.filters b/enginecustom/enginecustom.vcxproj.filters index 57a70d5..6bef417 100644 --- a/enginecustom/enginecustom.vcxproj.filters +++ b/enginecustom/enginecustom.vcxproj.filters @@ -27,6 +27,9 @@ Fichiers sources + + Fichiers sources + @@ -38,5 +41,8 @@ Fichiers d%27en-tĂȘte + + Fichiers d%27en-tĂȘte + \ No newline at end of file