所以我是DirectX的总菜鸟,从未做过任何事情。我研究了一些已经编写过的框架,并且还阅读了Frank Luna的一本书(使用DirectX进行游戏编程)来制作一个框架。我对WINAPI也不好,但我认为这不是问题所在。当我运行代码时,我得到这个例外: this-> m_swapChain为nullptr 我怎么解决这个问题?我尝试不将m_swapChain初始化为NULL但没有改变。 这是DirectClass.h文件
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")
#include <d3d11.h>
#include <directxmath.h>
using namespace DirectX;
class DirectClass {
public:
DirectClass();
~DirectClass();
ID3D11Device *GetDevice() { return m_device; };
ID3D11DeviceContext *GetDeviceContext() { return m_deviceContext; };
IDXGISwapChain*GetSwapChain() { return m_swapChain; };
HRESULT Initialize(HWND hwnd);
private:
ID3D11Device *m_device;
ID3D11DeviceContext *m_deviceContext;
IDXGISwapChain *m_swapChain;
DXGI_SWAP_CHAIN_DESC m_swapChainDesc;
ID3D11Texture2D *m_backBuffer; //Back Buffer
ID3D11Texture2D *m_depthStencilBuffer; //Depth Stencil Buffer
D3D11_TEXTURE2D_DESC m_depthBufferDesc; //Depth Buffer Desc
D3D11_DEPTH_STENCIL_DESC m_depthStencilDesc;
ID3D11DepthStencilView *m_depthStencilView;
D3D11_DEPTH_STENCIL_VIEW_DESC m_depthStencilViewDesc;
D3D11_VIEWPORT m_viewPort;
ID3D11DepthStencilState* m_depthStencilState;
ID3D11RenderTargetView *m_renderTargetView;
int m_screenHeight;
int m_screenWidth;
bool m_windowed;
//render target
//render target view
};
这是DirectClass.cpp文件
#include "DirectClass.h"
DirectClass::DirectClass() {
m_windowed = false;
}
DirectClass::~DirectClass() {
}
HRESULT DirectClass::Initialize(HWND hwnd) {
HRESULT hr=S_OK;
m_windowed = true;
m_screenHeight= GetSystemMetrics(SM_CYSCREEN);
m_screenWidth = GetSystemMetrics(SM_CXSCREEN);
//feature levels
D3D_FEATURE_LEVEL featureLevels[]{
D3D_FEATURE_LEVEL_9_1,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_11_0,
};
//swap chain
if (m_windowed) {
m_swapChainDesc.BufferDesc.Height = 600;
m_swapChainDesc.BufferDesc.Width = 800;
m_swapChainDesc.Windowed = true;
}
else {
m_swapChainDesc.BufferDesc.Height = m_screenHeight;
m_swapChainDesc.BufferDesc.Width = m_screenWidth;
m_swapChainDesc.Windowed = false;
}
m_swapChainDesc.BufferCount = 2;
m_swapChainDesc.OutputWindow = hwnd; // dopo correggi
m_swapChainDesc.Flags = 0;
m_swapChainDesc.SampleDesc.Count = 1;
m_swapChainDesc.SampleDesc.Quality = 0;
m_swapChainDesc.BufferUsage = DXGI_USAGE_DISCARD_ON_PRESENT;
m_swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
hr=D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, 0, 0, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION,
&m_swapChainDesc, &m_swapChain, &m_device, featureLevels, &m_deviceContext ); //The problem is here. I get an exception like this "this->m_swapChain was nullptr
m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&m_backBuffer);
m_backBuffer->Release();
//Descrizione del depth buffer
ZeroMemory(&m_depthBufferDesc, sizeof(m_depthBufferDesc));
if (m_windowed) {
m_depthBufferDesc.Width = 800;
m_depthBufferDesc.Height = 600;
}
else {
m_depthBufferDesc.Width = m_screenWidth;
m_depthBufferDesc.Height = m_screenHeight;
}
m_depthBufferDesc.ArraySize = 1;
m_depthBufferDesc.MipLevels = 1;
m_depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
m_depthBufferDesc.SampleDesc.Count = 1;
m_depthBufferDesc.SampleDesc.Quality = 0;
m_depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
m_depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
m_depthBufferDesc.BindFlags = 0;
m_depthBufferDesc.CPUAccessFlags = 0;
m_depthStencilDesc.DepthEnable = true;
m_depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
m_depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
m_depthStencilDesc.StencilEnable = true;
m_depthStencilDesc.StencilReadMask = 0xFF;
m_depthStencilDesc.StencilWriteMask = 0xFF;
m_depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
m_depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
m_depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
m_depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
m_depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
m_depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
m_depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
m_depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
m_device->CreateTexture2D(&m_depthBufferDesc, 0, &m_depthStencilBuffer);
m_device->CreateDepthStencilView(m_depthStencilBuffer, 0, &m_depthStencilView);
if (m_windowed) {
m_viewPort.Height = 600;
m_viewPort.Width = 800;
}
else {
m_viewPort.Height = m_screenHeight;
m_viewPort.Width = m_screenWidth;
}
m_viewPort.MaxDepth = 1.0f;
m_viewPort.MinDepth = 0.0f;
m_viewPort.TopLeftX = 0.0f;
m_viewPort.TopLeftY = 0.0f;
m_device->CreateRenderTargetView(m_backBuffer, 0, &m_renderTargetView);
m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);
m_deviceContext->RSSetViewports(1, &m_viewPort);
return hr;
}
可能有更多的错误比我要求的(如果你发现一些不好或缺少的东西告诉我,没有问题)在代码中,但我自己做了这个并通过在线查看一些例子(复制的东西) ,但了解大部分内容)
这是MainClass.h文件(从这里复制https://msdn.microsoft.com/en-us/library/windows/desktop/dn643742(v=vs.85).aspx)
#pragma once
#include "DirectClass.h"
#include<Windows.h>
#include <string>
class MainClass
{
public:
MainClass();
~MainClass();
HRESULT CreateDesktopWindow();
HWND GetWindowHandle() { return m_hWnd; };
static LRESULT CALLBACK StaticWindowProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
HRESULT Present(IDXGISwapChain *swapChain);
private:
HMENU m_hMenu;
RECT m_rc;
HWND m_hWnd;
};
static HINSTANCE m_hInstance;
static std::wstring m_windowClassName;
和MainClass.cpp文件一样,这确实没有错误
MainClass::MainClass()
{
m_windowClassName = L"Direct3DWindowClass";
m_hInstance = NULL;
}
MainClass::~MainClass(){}
//-----------------------------------------------------------------------------
// Create a window for our Direct3D viewport.
//-----------------------------------------------------------------------------
HRESULT MainClass::CreateDesktopWindow()
{
// Window resources are dealt with here.
HRESULT hr=S_OK;
if (m_hInstance == NULL)
m_hInstance = (HINSTANCE)GetModuleHandle(NULL);
HICON hIcon = NULL;
WCHAR szExePath[MAX_PATH];
GetModuleFileName(NULL, szExePath, MAX_PATH);
// If the icon is NULL, then use the first one found in the exe
if (hIcon == NULL)
hIcon = ExtractIcon(m_hInstance, szExePath, 0);
// Register the windows class
WNDCLASS wndClass;
wndClass.style = CS_DBLCLKS;
wndClass.lpfnWndProc = MainClass::StaticWindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = m_hInstance;
wndClass.hIcon = hIcon;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = m_windowClassName.c_str();
if (!RegisterClass(&wndClass))
{
DWORD dwError = GetLastError();
if (dwError != ERROR_CLASS_ALREADY_EXISTS)
return HRESULT_FROM_WIN32(dwError);
}
m_rc;
int x = CW_USEDEFAULT;
int y = CW_USEDEFAULT;
// No menu in this example.
m_hMenu = NULL;
// This example uses a non-resizable 640 by 480 viewport for simplicity.
int nDefaultWidth = 800;
int nDefaultHeight = 600;
SetRect(&m_rc, 0, 0, nDefaultWidth, nDefaultHeight);
AdjustWindowRect(
&m_rc,
WS_OVERLAPPEDWINDOW,
(m_hMenu != NULL) ? true : false
);
// Create the window for our viewport.
m_hWnd = CreateWindow(
m_windowClassName.c_str(),
L"Cube11",
WS_OVERLAPPEDWINDOW,
x, y,
(m_rc.right - m_rc.left), (m_rc.bottom - m_rc.top),
0,
m_hMenu,
m_hInstance,
0
);
if (m_hWnd == NULL)
{
DWORD dwError = GetLastError();
return HRESULT_FROM_WIN32(dwError);
}
return hr;
}
HRESULT MainClass::Present(IDXGISwapChain *swapChain) {
HRESULT hr;
hr = S_OK;
swapChain->Present(1, 0);
return hr;
}
LRESULT CALLBACK MainClass::StaticWindowProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch (uMsg)
{
case WM_CLOSE:
{
HMENU hMenu;
hMenu = GetMenu(hWnd);
if (hMenu != NULL)
{
DestroyMenu(hMenu);
}
DestroyWindow(hWnd);
UnregisterClass(
m_windowClassName.c_str(),
m_hInstance
);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
主要
#include "DirectClass.h"
#include "MainClass.h"
#include <memory>
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
HRESULT hr = S_OK;
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
std::shared_ptr<MainClass> winMain = std::shared_ptr<MainClass>(new MainClass());
// Create a window.
hr = winMain->CreateDesktopWindow();
std::shared_ptr<DirectClass> directClass = std::shared_ptr<DirectClass>(new DirectClass());
HWND hwnd = winMain->GetWindowHandle();
directClass->Initialize(hwnd);
IDXGISwapChain *sC = directClass->GetSwapChain();
if (SUCCEEDED(hr))
{
winMain->Present(sC);
}
}
对不起,如果这是写得不好,愚蠢,废话和糟糕的优化。 也许通过解决该异常,我可以尝试改进此代码,谢谢。