//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; m_depthDisabledStencilState = 0; m_alphaDisableBlendingState = 0; m_alphaEnableBlendingState = 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, 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; D3D11_VIEWPORT viewport; float fieldOfView, screenAspect; D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc; D3D11_BLEND_DESC blendStateDescription; //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; } //enum 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 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 combo displayModeList = new DXGI_MODE_DESC[numModes]; if(!displayModeList) { return false; } //now fill the adapter 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 h/w when a match is found store the numerator //and deniminator of the refresh rate for that monitor for(i=0; iGetDesc(&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; //Ini the swapchain desc ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); //set to a single back buffer swapChainDesc.BufferCount = 1; //st the width and height of the back buffer swapChainDesc.BufferDesc.Width = screenWidth; swapChainDesc.BufferDesc.Height = screenHeight; //set the reg 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 contexts after presenting swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //dont set the advanced flags swapChainDesc.Flags = 0; //set the feature level to DX 11 featureLevel = D3D_FEATURE_LEVEL_11_0; //create the swapchain, D3Ddevice and d3d 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 the pointer to the back buffer as we no longer need it backBufferPtr->Release(); backBufferPtr = 0; ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); //set up the desc of th 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 desc 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); // Initailze 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. viewport.Width = (float)screenWidth; viewport.Height = (float)screenHeight; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; // Create the viewport. m_deviceContext->RSSetViewports(1, &viewport); // Setup the projection matrix. fieldOfView = (float)D3DX_PI / 4.0f; screenAspect = (float)screenWidth / (float)screenHeight; // Create the projection matrix for 3D rendering. D3DXMatrixPerspectiveFovLH(&m_projectionMatrix, fieldOfView, screenAspect, screenNear, screenDepth); // Initialize the world matrix to the identity matrix. D3DXMatrixIdentity(&m_worldMatrix); // Create an orthographic projection matrix for 2D rendering. D3DXMatrixOrthoLH(&m_orthoMatrix, (float)screenWidth, (float)screenHeight, screenNear, screenDepth); //clear the second depth stencil state ZeroMemory(&depthDisabledStencilDesc, sizeof(depthDisabledStencilDesc)); //now create a second depth stencil state which turns off the Z buffer for 2d rendering //the only difference is that depthenable is set to false depthDisabledStencilDesc.DepthEnable = false; depthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthDisabledStencilDesc.StencilEnable = true; depthDisabledStencilDesc.StencilReadMask = 0xFF; depthDisabledStencilDesc.StencilWriteMask = 0xFF; depthDisabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; depthDisabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; depthDisabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; depthDisabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; //create the state using the device result = m_device->CreateDepthStencilState(&depthDisabledStencilDesc, &m_depthDisabledStencilState); if(FAILED(result)) { return false; } //clear the blend state desc ZeroMemory(&blendStateDescription, sizeof(D3D11_BLEND_DESC)); // Create an alpha enabled blend state description. blendStateDescription.RenderTarget[0].BlendEnable = TRUE; blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blendStateDescription.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blendStateDescription.RenderTarget[0].RenderTargetWriteMask = 0x0f; //create the blend state using the desc result = m_device->CreateBlendState(&blendStateDescription, &m_alphaEnableBlendingState); if(FAILED(result)) { return false; } //modify the dfesc to create an alpha disabled blend state desc blendStateDescription.RenderTarget[0].BlendEnable = FALSE; //create the blend state using the desc result = m_device->CreateBlendState(&blendStateDescription, &m_alphaDisableBlendingState); if(FAILED(result)) { return false; } 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_alphaEnableBlendingState) { m_alphaEnableBlendingState->Release(); m_alphaEnableBlendingState = 0; } if(m_alphaDisableBlendingState) { m_alphaDisableBlendingState->Release(); m_alphaDisableBlendingState = 0; } if(m_rasterState) { m_rasterState->Release(); m_rasterState = 0; } if(m_depthStencilView) { m_depthStencilView->Release(); m_depthStencilView = 0; } if(m_depthDisabledStencilState) { m_depthDisabledStencilState->Release(); m_depthDisabledStencilState = 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(D3DXMATRIX& projectionMatrix) { projectionMatrix = m_projectionMatrix; return; } void D3DClass::GetWorldMatrix(D3DXMATRIX& worldMatrix) { worldMatrix = m_worldMatrix; return; } void D3DClass::GetOrthoMatrix(D3DXMATRIX& orthoMatrix) { orthoMatrix = m_orthoMatrix; return; } void D3DClass::GetVideoCardInfo(char* cardName, int& memory) { strcpy_s(cardName, 128, m_videoCardDescription); memory = m_videoCardMemory; return; } void D3DClass::TurnZBufferOn() { m_deviceContext->OMSetDepthStencilState(m_depthStencilState ,1); return; } void D3DClass::TurnZBufferOff() { m_deviceContext->OMSetDepthStencilState(m_depthDisabledStencilState, 1); return; } void D3DClass::TurnOnAlphaBlending() { float blendFactor[4]; // Setup the blend factor. blendFactor[0] = 0.0f; blendFactor[1] = 0.0f; blendFactor[2] = 0.0f; blendFactor[3] = 0.0f; // Turn on the alpha blending. m_deviceContext->OMSetBlendState(m_alphaEnableBlendingState, blendFactor, 0xffffffff); return; } void D3DClass::TurnOffAlphaBlending() { float blendFactor[4]; // Setup the blend factor. blendFactor[0] = 0.0f; blendFactor[1] = 0.0f; blendFactor[2] = 0.0f; blendFactor[3] = 0.0f; // Turn off the alpha blending. m_deviceContext->OMSetBlendState(m_alphaDisableBlendingState, blendFactor, 0xffffffff); return; }