DirectX 11 引擎在第三次代码改进后突然 运行 了,我不知道为什么
DirectX 11 engine is not running suddenly after third code improvement and I don't know why
我正在学习使用 DirectX 11 引擎的 C++ 游戏教程。在前两部分中,我的代码没有问题,但在第三部分(创建交换链)中,DirectX window 决定不显示,让我使用控制台。我真的不知道如何描述代码,所以我将插入所有 类、头文件等。
main.cpp:
#include "AppWindow.h"
int main()
{
AppWindow app;
if (app.Init())
{
while (app.isRun())
{
app.brodcast();
}
}
return 0;
}
AppWindow.cpp:
#include "AppWindow.h"
void AppWindow::onCreate()
{
GraphicsEngine::get()->init();
m_swap_chain = GraphicsEngine::get()->crreateSwapChain();
RECT rc = this->getClientWindowRect();
m_swap_chain->init(this->m_hwnd, rc.right-rc.left, rc.bottom-rc.top);
}
void AppWindow::onUpdate()
{
}
void AppWindow::onDestroy()
{
Window::onDestroy();
GraphicsEngine::get()->release();
}
AppWindow.h:
#pragma once
#include "Window.h"
#include "GraphicsEngine.h"
#include "SwapChain.h"
class AppWindow: public Window
{
public:
// Inherited via Window
virtual void onCreate() override;
virtual void onUpdate() override;
virtual void onDestroy() override;
private:
SwapChain * m_swap_chain;
};
Window.cpp:
#include "Window.h"
Window* window = nullptr;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_CREATE:
{
//Event fired when the window will be created
//collected here...
Window* window = (Window*)((LPCREATESTRUCT)lparam)->lpCreateParams;
//...and then stored here for later look up
SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)window);
window->setHWND(hwnd);
window->onCreate();
break;
}
case WM_DESTROY:
{
//Event fired when the window will be destroyed
window->onDestroy();
::PostQuitMessage(0);
break;
}
default:
return ::DefWindowProc(hwnd, msg, wparam, lparam);
}
return NULL;
}
bool Window::Init()
{
WNDCLASSEX wc;
wc.cbClsExtra = NULL;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = NULL;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = NULL;
wc.lpszClassName = "MyWindowClass";
wc.lpszMenuName = "";
wc.style = NULL;
wc.lpfnWndProc = &WndProc;
if (!::RegisterClassEx(&wc)) //if the registration of the class will fail, the function will return false
return false;
if (!window)
window = this;
//creation of the window
m_hwnd=::CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "MyWindowClass", "DirectX Application", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1024, 768, NULL, NULL, NULL, NULL);
//if the creation fails then the method will return false
if (!m_hwnd)
return false;
//show up the window
::ShowWindow(m_hwnd, SW_SHOW);
::UpdateWindow(m_hwnd);
//set this flag to true to indicate that the window is initialized and running
m_is_run = true;
return true;
}
bool Window::brodcast()
{
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
window->onUpdate();
Sleep(0);
return true;
}
bool Window::Release()
{
//destroy the window
if (!::DestroyWindow(m_hwnd))
return false;
return true;
}
void Window::onDestroy()
{
m_is_run = false;
}
bool Window::isRun()
{
return m_is_run;
}
RECT Window::getClientWindowRect()
{
RECT rc;
::GetClientRect(this->m_hwnd, &rc);
return rc;
}
void Window::setHWND(HWND hwnd)
{
this->m_hwnd = hwnd;
}
Window.h:
#pragma once
#include <windows.h>
class Window
{
public:
//Initialize the window
bool Init();
bool brodcast();
//Release the window
bool Release();
bool isRun();
RECT getClientWindowRect();
void setHWND(HWND hwnd);
//EVENTS
virtual void onCreate()=0;
virtual void onUpdate()=0;
virtual void onDestroy()=0;
protected:
HWND m_hwnd;
bool m_is_run;
};
GraphicsEngine.cpp:
#include "GraphicsEngine.h"
#include <d3d11.h>
#include "SwapChain.h"
bool GraphicsEngine::init()
{
D3D_DRIVER_TYPE driver_types[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE
};
UINT num_driver_types = ARRAYSIZE(driver_types);
D3D_FEATURE_LEVEL feature_levels[]=
{
D3D_FEATURE_LEVEL_11_0
};
UINT num_feature_levels = ARRAYSIZE(feature_levels);
HRESULT res = 0;
for (UINT driver_type_index = 0; driver_type_index < num_driver_types;)
{
res = D3D11CreateDevice(NULL, driver_types[driver_type_index], NULL, NULL, feature_levels,
num_feature_levels, D3D10_1_SDK_VERSION, &m_d3d_device, &m_feature_level, &m_imm_context);
if (SUCCEEDED(res))
break;
++driver_type_index;
}
if (FAILED(res))
{
return false;
}
m_d3d_device->QueryInterface(__uuidof(IDXGIDevice), (void**)&m_dxgi_device);
m_dxgi_device->GetParent(__uuidof(IDXGIAdapter), (void**)&m_dxgi_adapter);
m_dxgi_adapter->GetParent(__uuidof(IDXGIFactory), (void**)&m_dxgi_factory);
return true;
}
bool GraphicsEngine::release()
{
m_dxgi_device->Release();
m_dxgi_adapter->Release();
m_dxgi_factory->Release();
m_imm_context->Release();
m_d3d_device->Release();
return true;
}
GraphicsEngine * GraphicsEngine::get()
{
static GraphicsEngine engine;
return &engine;
}
SwapChain * GraphicsEngine::crreateSwapChain()
{
return new SwapChain();
}
GraphicsEngine.h
#pragma once
#include <d3d11.h>
class SwapChain;
class GraphicsEngine
{
public:
//initialize graphics engine and DirectX 11 device
bool init();
//release all the resources loaded
bool release();
static GraphicsEngine* get();
SwapChain* crreateSwapChain();
private:
ID3D11Device * m_d3d_device;
D3D_FEATURE_LEVEL m_feature_level;
ID3D11DeviceContext * m_imm_context;
IDXGIDevice * m_dxgi_device;
IDXGIAdapter * m_dxgi_adapter;
IDXGIFactory * m_dxgi_factory;
friend class SwapChain;
};
SwapChain.cpp:
#include "SwapChain.h"
#include "GraphicsEngine.h"
bool SwapChain::init(HWND hwnd, UINT width, UINT height)
{
ID3D11Device *device = GraphicsEngine::get()->m_d3d_device;
DXGI_SWAP_CHAIN_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.BufferCount = 1;
desc.BufferDesc.Width = width;
desc.BufferDesc.Height = height;
desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.BufferDesc.RefreshRate.Numerator = 60;
desc.BufferDesc.RefreshRate.Denominator = 1;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.OutputWindow = hwnd;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Windowed = TRUE;
//Create the SwapChain for the window initialized by the HWND paramater
HRESULT hr = GraphicsEngine::get()->m_dxgi_factory->CreateSwapChain(device, &desc, &m_swap_chain);
if (FAILED(hr))
{
return false;
}
return true;
}
bool SwapChain::release()
{
m_swap_chain->Release();
delete this;
return true;
}
SwapChain.h:
#pragma once
#include <d3d11.h>
class SwapChain
{
public:
//Initialize a SwapChain for a window
bool init(HWND hwnd, UINT width, UINT height);
//release the SwapChain
bool release();
private:
IDXGISwapChain* m_swap_chain;
};
在 window.cpp 中我得到一个异常->m_hwnd = hwnd;
问题出在这行代码中:
Window* window = (Window*)((LPCREATESTRUCT)lparam)->lpCreateParams;
传入的lparam
是空值,使window
成为空指针,最终导致访问错误
如何解决?
调用CreateWindowEx
时,需要在最后的void*参数中传递一个指向Window
class的指针。
//creation of the window
m_hwnd = ::CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "MyWindowClass", "DirectX Application", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1024, 768, NULL, NULL, NULL, window);
注意:(您可能遇到的问题)
If the Direct3D 11.1 runtime is present on the computer and
pFeatureLevels is set to NULL, this function won't create a
D3D_FEATURE_LEVEL_11_1 device. To create a D3D_FEATURE_LEVEL_11_1
device, you must explicitly provide a D3D_FEATURE_LEVEL array that
includes D3D_FEATURE_LEVEL_11_1. If you provide a D3D_FEATURE_LEVEL
array that contains D3D_FEATURE_LEVEL_11_1 on a computer that doesn't
have the Direct3D 11.1 runtime installed, this function immediately
fails with E_INVALIDARG.
您可能需要在 D3D11CreateDevice
中使用 D3D11_SDK_VERSION
而不是 D3D10_1_SDK_VERSION
。
我正在学习使用 DirectX 11 引擎的 C++ 游戏教程。在前两部分中,我的代码没有问题,但在第三部分(创建交换链)中,DirectX window 决定不显示,让我使用控制台。我真的不知道如何描述代码,所以我将插入所有 类、头文件等。 main.cpp:
#include "AppWindow.h"
int main()
{
AppWindow app;
if (app.Init())
{
while (app.isRun())
{
app.brodcast();
}
}
return 0;
}
AppWindow.cpp:
#include "AppWindow.h"
void AppWindow::onCreate()
{
GraphicsEngine::get()->init();
m_swap_chain = GraphicsEngine::get()->crreateSwapChain();
RECT rc = this->getClientWindowRect();
m_swap_chain->init(this->m_hwnd, rc.right-rc.left, rc.bottom-rc.top);
}
void AppWindow::onUpdate()
{
}
void AppWindow::onDestroy()
{
Window::onDestroy();
GraphicsEngine::get()->release();
}
AppWindow.h:
#pragma once
#include "Window.h"
#include "GraphicsEngine.h"
#include "SwapChain.h"
class AppWindow: public Window
{
public:
// Inherited via Window
virtual void onCreate() override;
virtual void onUpdate() override;
virtual void onDestroy() override;
private:
SwapChain * m_swap_chain;
};
Window.cpp:
#include "Window.h"
Window* window = nullptr;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_CREATE:
{
//Event fired when the window will be created
//collected here...
Window* window = (Window*)((LPCREATESTRUCT)lparam)->lpCreateParams;
//...and then stored here for later look up
SetWindowLongPtr(hwnd, GWL_USERDATA, (LONG_PTR)window);
window->setHWND(hwnd);
window->onCreate();
break;
}
case WM_DESTROY:
{
//Event fired when the window will be destroyed
window->onDestroy();
::PostQuitMessage(0);
break;
}
default:
return ::DefWindowProc(hwnd, msg, wparam, lparam);
}
return NULL;
}
bool Window::Init()
{
WNDCLASSEX wc;
wc.cbClsExtra = NULL;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = NULL;
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = NULL;
wc.lpszClassName = "MyWindowClass";
wc.lpszMenuName = "";
wc.style = NULL;
wc.lpfnWndProc = &WndProc;
if (!::RegisterClassEx(&wc)) //if the registration of the class will fail, the function will return false
return false;
if (!window)
window = this;
//creation of the window
m_hwnd=::CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "MyWindowClass", "DirectX Application", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1024, 768, NULL, NULL, NULL, NULL);
//if the creation fails then the method will return false
if (!m_hwnd)
return false;
//show up the window
::ShowWindow(m_hwnd, SW_SHOW);
::UpdateWindow(m_hwnd);
//set this flag to true to indicate that the window is initialized and running
m_is_run = true;
return true;
}
bool Window::brodcast()
{
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
window->onUpdate();
Sleep(0);
return true;
}
bool Window::Release()
{
//destroy the window
if (!::DestroyWindow(m_hwnd))
return false;
return true;
}
void Window::onDestroy()
{
m_is_run = false;
}
bool Window::isRun()
{
return m_is_run;
}
RECT Window::getClientWindowRect()
{
RECT rc;
::GetClientRect(this->m_hwnd, &rc);
return rc;
}
void Window::setHWND(HWND hwnd)
{
this->m_hwnd = hwnd;
}
Window.h:
#pragma once
#include <windows.h>
class Window
{
public:
//Initialize the window
bool Init();
bool brodcast();
//Release the window
bool Release();
bool isRun();
RECT getClientWindowRect();
void setHWND(HWND hwnd);
//EVENTS
virtual void onCreate()=0;
virtual void onUpdate()=0;
virtual void onDestroy()=0;
protected:
HWND m_hwnd;
bool m_is_run;
};
GraphicsEngine.cpp:
#include "GraphicsEngine.h"
#include <d3d11.h>
#include "SwapChain.h"
bool GraphicsEngine::init()
{
D3D_DRIVER_TYPE driver_types[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE
};
UINT num_driver_types = ARRAYSIZE(driver_types);
D3D_FEATURE_LEVEL feature_levels[]=
{
D3D_FEATURE_LEVEL_11_0
};
UINT num_feature_levels = ARRAYSIZE(feature_levels);
HRESULT res = 0;
for (UINT driver_type_index = 0; driver_type_index < num_driver_types;)
{
res = D3D11CreateDevice(NULL, driver_types[driver_type_index], NULL, NULL, feature_levels,
num_feature_levels, D3D10_1_SDK_VERSION, &m_d3d_device, &m_feature_level, &m_imm_context);
if (SUCCEEDED(res))
break;
++driver_type_index;
}
if (FAILED(res))
{
return false;
}
m_d3d_device->QueryInterface(__uuidof(IDXGIDevice), (void**)&m_dxgi_device);
m_dxgi_device->GetParent(__uuidof(IDXGIAdapter), (void**)&m_dxgi_adapter);
m_dxgi_adapter->GetParent(__uuidof(IDXGIFactory), (void**)&m_dxgi_factory);
return true;
}
bool GraphicsEngine::release()
{
m_dxgi_device->Release();
m_dxgi_adapter->Release();
m_dxgi_factory->Release();
m_imm_context->Release();
m_d3d_device->Release();
return true;
}
GraphicsEngine * GraphicsEngine::get()
{
static GraphicsEngine engine;
return &engine;
}
SwapChain * GraphicsEngine::crreateSwapChain()
{
return new SwapChain();
}
GraphicsEngine.h
#pragma once
#include <d3d11.h>
class SwapChain;
class GraphicsEngine
{
public:
//initialize graphics engine and DirectX 11 device
bool init();
//release all the resources loaded
bool release();
static GraphicsEngine* get();
SwapChain* crreateSwapChain();
private:
ID3D11Device * m_d3d_device;
D3D_FEATURE_LEVEL m_feature_level;
ID3D11DeviceContext * m_imm_context;
IDXGIDevice * m_dxgi_device;
IDXGIAdapter * m_dxgi_adapter;
IDXGIFactory * m_dxgi_factory;
friend class SwapChain;
};
SwapChain.cpp:
#include "SwapChain.h"
#include "GraphicsEngine.h"
bool SwapChain::init(HWND hwnd, UINT width, UINT height)
{
ID3D11Device *device = GraphicsEngine::get()->m_d3d_device;
DXGI_SWAP_CHAIN_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.BufferCount = 1;
desc.BufferDesc.Width = width;
desc.BufferDesc.Height = height;
desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.BufferDesc.RefreshRate.Numerator = 60;
desc.BufferDesc.RefreshRate.Denominator = 1;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.OutputWindow = hwnd;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Windowed = TRUE;
//Create the SwapChain for the window initialized by the HWND paramater
HRESULT hr = GraphicsEngine::get()->m_dxgi_factory->CreateSwapChain(device, &desc, &m_swap_chain);
if (FAILED(hr))
{
return false;
}
return true;
}
bool SwapChain::release()
{
m_swap_chain->Release();
delete this;
return true;
}
SwapChain.h:
#pragma once
#include <d3d11.h>
class SwapChain
{
public:
//Initialize a SwapChain for a window
bool init(HWND hwnd, UINT width, UINT height);
//release the SwapChain
bool release();
private:
IDXGISwapChain* m_swap_chain;
};
在 window.cpp 中我得到一个异常->m_hwnd = hwnd;
问题出在这行代码中:
Window* window = (Window*)((LPCREATESTRUCT)lparam)->lpCreateParams;
传入的lparam
是空值,使window
成为空指针,最终导致访问错误
如何解决?
调用CreateWindowEx
时,需要在最后的void*参数中传递一个指向Window
class的指针。
//creation of the window
m_hwnd = ::CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, "MyWindowClass", "DirectX Application", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1024, 768, NULL, NULL, NULL, window);
注意:(您可能遇到的问题)
If the Direct3D 11.1 runtime is present on the computer and pFeatureLevels is set to NULL, this function won't create a D3D_FEATURE_LEVEL_11_1 device. To create a D3D_FEATURE_LEVEL_11_1 device, you must explicitly provide a D3D_FEATURE_LEVEL array that includes D3D_FEATURE_LEVEL_11_1. If you provide a D3D_FEATURE_LEVEL array that contains D3D_FEATURE_LEVEL_11_1 on a computer that doesn't have the Direct3D 11.1 runtime installed, this function immediately fails with E_INVALIDARG.
您可能需要在 D3D11CreateDevice
中使用 D3D11_SDK_VERSION
而不是 D3D10_1_SDK_VERSION
。