bool D3DManager::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 int stringLength; DXGI_MODE_DESC* displayModeList; DXGI_ADAPTER_DESC adapterDesc; int error; DXGI_SWAP_CHAIN_DESC swapChainDesc; D3D_FEATURE_LEVEL featureLevel; Microsoft::WRL::ComPtr<ID3D11Texture2D> backBufferPtr; D3D11_TEXTURE2D_DESC depthBufferDesc; D3D11_DEPTH_STENCIL_DESC depthStencilDesc; D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; D3D11_RASTERIZER_DESC rasterDesc; float fieldOfView, screenAspect; D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc; D3D11_BLEND_DESC blendStateDesc; // 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 multi-sampling 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_pSwapChain, &m_device, NULL, &m_deviceContext); if (FAILED(result)) { return false; } // Get the pointer to the back buffer. result = m_pSwapChain->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.Get(), NULL, &m_renderTargetView); if (FAILED(result)) { return false; } // Release pointer to the back buffer as we no longer need it. backBufferPtr.Reset(); backBufferPtr = nullptr; // 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); rasterDesc.CullMode = D3D11_CULL_NONE; result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterStateNoCulling); if (FAILED(result)) { return false; } // Setup a raster description which enables wire frame rendering. rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBias = 0; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = true; rasterDesc.FillMode = D3D11_FILL_WIREFRAME; rasterDesc.FrontCounterClockwise = false; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; // Create the wire frame rasterizer state. result = m_device->CreateRasterizerState(&rasterDesc, &m_rasterStateWireframe); if (FAILED(result)) { return false; } // 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 = DirectX::XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, screenNear, screenDepth); // Initialize the world matrix to the identity matrix. m_worldMatrix = DirectX::XMMatrixIdentity(); // Create an orthographic projection matrix for 2D rendering. m_orthoMatrix = DirectX::XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, screenNear, screenDepth); // Set up the description of the stencil state. depthDisabledStencilDesc.DepthEnable = false; depthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthDisabledStencilDesc.StencilEnable = true; depthDisabledStencilDesc.StencilReadMask = 0xFF; depthDisabledStencilDesc.StencilWriteMask = 0xFF; // Stencil operations if pixel is front-facing. 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; // Stencil operations if pixel is back-facing. 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 description. ZeroMemory(&blendStateDesc, sizeof(D3D11_BLEND_DESC)); // Create an alpha enabled blend state description. blendStateDesc.RenderTarget[0].BlendEnable = TRUE; blendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; blendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; blendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blendStateDesc.RenderTarget[0].RenderTargetWriteMask = 0x0f; // Create the blend state using the description. result = m_device->CreateBlendState(&blendStateDesc, &m_alphaEnableBlendingState); if (FAILED(result)) { return false; } // Modify the description to create an alpha disabled blend state description. blendStateDesc.RenderTarget[0].BlendEnable = FALSE; // Create the blend state using the description. result = m_device->CreateBlendState(&blendStateDesc, &m_alphaDisableBlendingState); if (FAILED(result)) { return false; } // Create a blend state description for the alpha-to-coverage blending mode. blendStateDesc.AlphaToCoverageEnable = true; blendStateDesc.IndependentBlendEnable = false; blendStateDesc.RenderTarget[0].BlendEnable = true; blendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; blendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; blendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; blendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; blendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blendStateDesc.RenderTarget[0].RenderTargetWriteMask = 0x0f; // Create the blend state using the description. result = m_device->CreateBlendState(&blendStateDesc, &m_alphaEnableBlendingState2); if (FAILED(result)) { return false; } return true; }
void Scene::onInit() { this->mpZBufferDSV.Reset(); this->mpZBuffer.Reset(); this->mpBackBufferRTV.Reset(); this->mpBackBuffer.Reset(); this->mpImmediateContext.Reset(); this->mpDevice.Reset(); this->mpSwapChain.Reset(); //デバイスなどを作り直す //DXGIを使う上で必要となるIDXGIFactory1を作成 HRESULT hr; Microsoft::WRL::ComPtr<IDXGIFactory1> pFactory; hr = CreateDXGIFactory1(IID_PPV_ARGS(pFactory.GetAddressOf())); if (FAILED(hr)) { throw std::runtime_error("IDXGIFactoryクラスの作成に失敗しました。"); } //GPUアダプターを列挙して一番最初に見つかった使えるものを選ぶ Microsoft::WRL::ComPtr<IDXGIAdapter1> pAdapterIt; for (UINT adapterIndex = 0; S_OK == pFactory->EnumAdapters1(adapterIndex, pAdapterIt.GetAddressOf()); ++adapterIndex) { DXGI_ADAPTER_DESC1 desc; pAdapterIt->GetDesc1(&desc); OutputDebugStringA( std::string("adapter " + std::to_string(adapterIndex) + "\n").c_str()); OutputDebugStringW((std::wstring(L" decription = ") + desc.Description + L"\n").c_str()); OutputDebugStringA( std::string(" VemdorId = " + std::to_string(desc.VendorId) + "\n").c_str()); OutputDebugStringA( std::string(" DeviceId = " + std::to_string(desc.DeviceId) + "\n").c_str()); OutputDebugStringA( std::string(" SubSysId = " + std::to_string(desc.SubSysId) + "\n").c_str()); OutputDebugStringA( std::string(" Revision = " + std::to_string(desc.Revision) + "\n").c_str()); OutputDebugStringA( std::string(" DedicatedVideoMemory = " + std::to_string(desc.DedicatedVideoMemory) + "\n").c_str()); OutputDebugStringA( std::string(" DedicatedSystemMemory = " + std::to_string(desc.DedicatedSystemMemory) + "\n").c_str()); OutputDebugStringA( std::string(" SharedSystemMemory = " + std::to_string(desc.SharedSystemMemory) + "\n").c_str()); OutputDebugStringA( std::string(" AdapterLuid = high:" + std::to_string(desc.AdapterLuid.HighPart) + " low:" + std::to_string(desc.AdapterLuid.LowPart) + "\n").c_str()); OutputDebugStringA( std::string(" Flag = " + std::to_string(desc.Flags) + "\n").c_str()); if (nullptr == this->mpAdapter) { if (desc.Flags ^= DXGI_ADAPTER_FLAG_SOFTWARE) { this->mpAdapter = pAdapterIt; OutputDebugStringA(std::string("このアダプターを使用します。 adapterIndex = " + std::to_string(adapterIndex) + "\n").c_str()); } //期待通りに動作してくれなかった //LARGE_INTEGER version; //hr = pAdapterIt->CheckInterfaceSupport(__uuidof(ID3D11Device), &version); //DXGI_ERROR_UNSUPPORTED; //if (S_OK == hr) { // pAdapter = pAdapterIt; // OutputDebugStringA(std::string("このアダプターを使用します。 adapterIndex = " + std::to_string(adapterIndex) + "\n").c_str()); //} } //使い終わったら必ずReleaseすること pAdapterIt.Reset(); } //ID3D11DeviceとID3D11DeviceContextの作成 std::array<D3D_FEATURE_LEVEL, 3> featureLevels = { { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 } }; UINT flags = 0; #ifdef _DEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL usedLevel; hr = D3D11CreateDevice( this->mpAdapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, flags, featureLevels.data(), static_cast<UINT>(featureLevels.size()), D3D11_SDK_VERSION, this->mpDevice.GetAddressOf(), &usedLevel, this->mpImmediateContext.GetAddressOf() ); if (FAILED(hr)) { throw std::runtime_error("ID3D11Deviceの作成に失敗。"); } //IDXGISwapChainの作成 DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 }; swapChainDesc.OutputWindow = Win32Application::hwnd(); swapChainDesc.BufferCount = 2; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; //swapChainDesc.Flags = 0; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; //フルスクリーンとウィンドモードの切り替えがしたい場合は、まずウィンドウモードとして生成することを推奨しているみたい //https://msdn.microsoft.com/en-us/library/bb174579(v=vs.85).aspx swapChainDesc.Windowed = true; //希望する画面設定 swapChainDesc.BufferDesc.Width = this->width(); swapChainDesc.BufferDesc.Height = this->height(); swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //上の画面設定に一番近いものを調べる Microsoft::WRL::ComPtr<IDXGIOutput> pOutput; if (DXGI_ERROR_NOT_FOUND == this->mpAdapter->EnumOutputs(0, pOutput.GetAddressOf())) { throw std::runtime_error("アダプターの出力先が見つかりません。"); } DXGI_MODE_DESC modeDesc; hr = pOutput->FindClosestMatchingMode(&swapChainDesc.BufferDesc, &modeDesc, this->mpDevice.Get()); if (FAILED(hr)) { throw std::runtime_error("表示モードの取得に失敗"); } //IDXGISwapChainの作成 swapChainDesc.BufferDesc = modeDesc; hr = pFactory->CreateSwapChain(this->mpDevice.Get(), &swapChainDesc, this->mpSwapChain.GetAddressOf()); if (FAILED(hr)) { throw std::runtime_error("IDXGISwapChainの作成に失敗"); } //ディスプレイの画面モードの一覧を取得する //IDXGIOutput* pOutput; //this->mpSwapChain->GetContainingOutput(&pOutput); //UINT num; //UINT flag = DXGI_ENUM_MODES_INTERLACED; //pOutput->GetDisplayModeList(swapChainDesc.BufferDesc.Format, flag, &num, nullptr); //std::vector<DXGI_MODE_DESC> modeDesces; //modeDesces.resize(num); //pOutput->GetDisplayModeList(swapChainDesc.BufferDesc.Format, flag, &num, &modeDesces[0]); //pOutput->Release(); // // 後はバックバッファのレンダーターゲットビューの作成、必要ならZバッファの作成とビューポートの設定を行う // initRenderTargetAndDepthStencil(swapChainDesc.BufferDesc.Width, swapChainDesc.BufferDesc.Height); }