03.初始化Direct3D 11
IDXGISwapChain* SwapChain;
ID3D11Device* d3d11Device;
ID3D11DeviceContext* d3d11DevCon;
ID3D11RenderTargetView* renderTargetView;
float red = 0.0f;
float green = 0.0f;
float blue = 0.0f;
int colormodr = 1;
int colormodg = 1;
int colormodb = 1;
接下来,我们声明函数原型。第一个函数用于初始化direct3d。第二个是释放我们不需要的对象以防止内存泄漏。InitScene用于设置或场景。更新场景用于按帧更改我们的场景,然后绘制场景用于将我们的场景绘制到屏幕上,并且每帧也进行更新。
bool InitializeDirect3d11App(HINSTANCE hInstance);
void ReleaseObjects();
bool InitScene();
void UpdateScene();
void DrawScene();
在我们的winMain函数中,我们将调用InitializeDirect3d11App,然后调用InitScene。此后,我们将调用消息循环,并在完成消息循环后,释放对象,然后结束程序。
if(!InitializeDirect3d11App(hInstance)) //Initialize Direct3D
{
MessageBox(0, L"Direct3D Initialization - Failed",
L"Error", MB_OK);
return 0;
}
if(!InitScene()) //Initialize our scene
{
MessageBox(0, L"Scene Initialization - Failed",
L"Error", MB_OK);
return 0;
}
messageloop();
ReleaseObjects();
初始化Direct3D 11
这是我们将初始化direct3d的函数。它采用一个参数,这是我们的应用程序实例的句柄。我将对它进行部分介绍。bool InitializeDirect3dApp(HINSTANCE hInstance)
{
HRESULT hr;
//Describe our Buffer
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
bufferDesc.Width = Width;
bufferDesc.Height = Height;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
//Describe our SwapChain
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = hwnd;
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
//Create our SwapChain
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);
//Create our BackBuffer
ID3D11Texture2D* BackBuffer;
hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&BackBuffer );
//Create our Render Target
hr = d3d11Device->CreateRenderTargetView( BackBuffer, NULL, &renderTargetView );
BackBuffer->Release();
//Set our Render Target
d3d11DevCon->OMSetRenderTargets( 1, &renderTargetView, NULL );
return true;
}
首先,我们创建一个名为hr的HRESULT对象,用于进行错误检查。为了使代码更加清晰和简洁,我没有包括错误检查功能,但是在本课程的最后,我将说明如何隐含错误检查功能。
HRESULT hr;
描述BackBuffer
(DXGI_MODE_DESC) 我们在此功能中要做的第一件事是描述我们的后缓冲。我们创建一个称为bufferDesc的DXGI_MODE_DESC对象。然后,我们调用ZeroMemory以确保对象被完全清除(以防万一我们没有设置所有参数,并且参数中已经有一个值)。然后,我们填写我们的后缓冲描述。DXGI_MODE_DESC结构:typedef struct DXGI_MODE_DESC {
UINT Width;
UINT Height;
DXGI_RATIONAL RefreshRate;
DXGI_FORMAT Format;
DXGI_MODE_SCANLINE_ORDER ScanlineOrdering;
DXGI_MODE_SCALING Scaling;
} DXGI_MODE_DESC, *LPDXGI_MODE_DESC;
每个成员的说明如下:
宽度
-这是我们要使用的分辨率的宽度。
高度
-这是我们要使用的分辨率的高度。
刷新率
-这是DXGI_RATIONAL类型,以赫兹为单位描述刷新率。我们将其设置为60/1或60hz。
格式
-这是DXGI_FORMAT枚举类型,描述了我们的显示格式。我们可以使用DXGI_FORMAT_R8G8B8A8_UNORM,它是一个32位无符号整数,分别为Red,Green,Blue和Alpha占用8位。
ScanlineOrdering-DXGI_MODE_SCANLINE_ORDER枚举类型,描述了光栅化器将渲染到表面上的方式。当我们使用双缓冲时,通常不会看到这种情况,因此可以将其设置为DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,这意味着在表面上进行渲染的顺序无关紧要。
缩放-这是另一种枚举类型。DXGI_MODE_SCALING,说明如何拉伸图像以适合显示器分辨率。我们可以使用以下三种之一:DXGI_MODE_SCALING_UNSPECIFIED(未指定),DXGI_MODE_SCALING_CENTERED(意味着图像位于屏幕中央,并且根本不进行缩放和拉伸)以及DXGI_MODE_SCALING_STRETCHED(将图像拉伸到显示器分辨率)。
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
bufferDesc.Width = Width;
bufferDesc.Height = Height;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
现在我们已经完成了对后缓冲区的描述,我们可以继续描述SwapChain。我们创建一个称为swapChainDesc的DXGI_SWAP_CHAIN_DESC,然后通过调用ZeroMemory函数将其清除。之后,我们可以填写说明。结构如下:
typedef struct DXGI_SWAP_CHAIN_DESC {
DXGI_MODE_DESC BufferDesc;
DXGI_SAMPLE_DESC SampleDesc;
DXGI_USAGE BufferUsage;
UINT BufferCount;
HWND OutputWindow;
BOOL Windowed;
DXGI_SWAP_EFFECT SwapEffect;
UINT Flags;
} DXGI_SWAP_CHAIN_DESC;
每个成员的说明如下:
缓冲区描述
-这是DXGI_MODE_DESC结构,描述了后缓冲区。我们将把刚才填写的bufferDesc对象放在这里。
样本描述
-这是DXGI_SAMPLE_DESC结构,用于描述多重采样。如果您不知道,则使用多重采样来“消除”线条和边缘的不连续感,这是由于监视器上的像素并不小而造成的。由于像素就像小块,因此您可以在计算机屏幕上的对角线和边缘看到“起伏”。
缓冲区使用率
-DXGI_USAGE枚举类型,描述cpu对后缓冲区表面的访问。我们指定DXGI_USAGE_RENDER_TARGET_OUTPUT,因为我们将对其进行渲染。
缓冲区数
-这是我们将使用的后台缓冲区的数量。我们将1设置为双缓冲,但您可以将2设置为三缓冲,如果需要,甚至可以设置更多。
输出窗口
-这是我们窗口的句柄,hwnd。
开窗的
-根据是要窗口显示还是全屏显示,这是true还是false。为窗口设置为true,为全屏设置为false。(请小心退出全屏模式。它可能会冻结程序。解决此问题的一种方法是在实际退出程序之前将应用程序设置为窗口式)
交换效果
-这是DXGI_SWAP_EFFECT枚举类型,描述了将显示驱动程序交换到后缓冲区后,显示驱动程序应如何处理前缓冲区。我们设置DXGI_SWAP_EFFECT_DISCARD来让显示驱动程序决定最有效的处理方式。
标志
-DXGI_SWAP_CHAIN_FLAG枚举类型。这是描述交换链行为的额外标志。现在唯一可能有用的是DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH,当在窗口和全屏之间切换时,它会更改显示器的分辨率。
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = hwnd;
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
创建设备和交换链
(D3D11CreateDeviceAndSwapChain()) 接下来,我们通过调用direct3d核心函数D3D11CreateDeviceAndSwapChain()创建direct3d设备,设备上下文和交换链。函数参数如下所示:HRESULT D3D11CreateDeviceAndSwapChain(
__in IDXGIAdapter *pAdapter,
__in D3D_DRIVER_TYPE DriverType,
__in HMODULE Software,
__in UINT Flags,
__in const D3D_FEATURE_LEVEL *pFeatureLevels,
__in UINT FeatureLevels,
__in UINT SDKVersion,
__in const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,
__out IDXGISwapChain **ppSwapChain,
__out ID3D11Device **ppDevice,
__out D3D_FEATURE_LEVEL *pFeatureLevel,
__out ID3D11DeviceContext **ppImmediateContext
);
每个参数的说明如下:
pAdapter
-这是要使用的视频适配器的指针。我们可以设置NULL以使用默认值。
驱动类型
-D3D_DRIVER_TYPE枚举类型。这表示将如何实现direct3d。我们使用D3D_DRIVER_TYPE_HARDWARE表示Direct3d将被GPU(图形卡)所隐含。
软件
-这是DLL的HMODULE句柄,将用于隐含软件光栅化。
标志
-这是一种或多种D3D11_CREATE_DEVICE_FLAG类型或一起使用。
pFeatureLevels
-这是指向D3D_FEATURE_LEVEL枚举类型数组的指针,这些类型表示要使用的DirectX功能版本。将NULL设置为使用可用的最高功能。
功能级别
-这是pFeatureLevels数组中元素的数量。设置为NULL。
SDK版本
-DirectX SDK的版本。使用D3D11_SDK_VERSION。
pSwapChainDesc
-指向我们在上面创建的DXGI_SWAP_CHAIN_DESC结构的指针。
pp交换链
-指向IDXGISwapChain接口的指针,以接收创建的SwapChain。
pp设备
-指向我们的direct3d设备的指针。
pFeatureLevel
-这是指向D3D_FEATURE_LEVEL的指针,该指针将保持可用的最高功能级别。(功能级别用于向后兼容)
ppImmediateContext
-这是指向我们的ID3D11DeviceContext(设备上下文)的指针。请记住,设备上下文将用于设备的呈现方法,以支持多线程并提高性能。
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);
创建BackBuffer
(GetBuffer()) 接下来,我们创建我们的后缓冲区,该缓冲区将用于创建渲染目标视图。我们调用SwapChain接口的GetBuffer方法:HRESULT GetBuffer(
[in] UINT Buffer,
[in] REFIID riid,
[in, out] void **ppSurface
);
每个参数的说明如下:
缓冲
-由于我们将swapChainDesc.SwapEffect设置为DXGI_SWAP_EFFECT_DISCARD,因此我们只能访问第一个缓冲区,因此我们将其设置为0。
RIID
-这是更改后备缓冲区的接口类型的参考ID。我们使用2D纹理(ID3D11Texture2D)。
pp表面
-这是我们上面创建的BackBuffer的指针,这是我们将渲染到的表面。
ID3D11Texture2D* BackBuffer;
hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&BackBuffer );
创建渲染目标
(ID3D11Device :: CreateRenderTargetView()) 现在,我们创建渲染目标视图,并将其发送到管道的输出合并阶段。我们可以通过调用设备界面的CreateRenderTargetView来创建渲染目标视图:HRESULT CreateRenderTargetView(
[in] ID3D11Resource *pResource,
[in] const D3D11_RENDER_TARGET_VIEW_DESC *pDesc,
[out] ID3D11RenderTargetView **ppRTView
);
每个参数的说明如下:
pResource
-这是我们的后备缓冲区。
pDesc
-指向D3D11_RENDER_TARGET_VIEW_DESC结构的指针。我们将NULL设置为创建一个视图,该视图访问mipmap级别0中的所有子资源。
ppRTView
-这是指向我们的ID3D11RenderTargetView接口renderTargetView的指针。
现在我们不再需要反向缓冲,我们可以释放它。
hr = d3d11Device->CreateRenderTargetView( BackBuffer, NULL, &renderTargetView );
BackBuffer->Release();
设置渲染目标
(ID3D11DeviceContext :: OMSetRenderTargets()) 我们初始化的最后一件事就是将渲染目标视图绑定到管道的输出合并阶段。该函数也将绑定我们的深度/模板缓冲区,但是我们尚未创建一个缓冲区,因此我们将该参数设置为NULL。void OMSetRenderTargets(
[in] UINT NumViews,
[in] ID3D11RenderTargetView *const **ppRenderTargetViews,
[in] ID3D11DepthStencilView *pDepthStencilView
);
每个参数的说明如下:
NumViews
-这是要绑定的渲染目标的数量。我们只有一个。
ppRenderTargetViews
-这是要绑定的渲染目标视图的数组。
pDepthStencilView
-这是指向深度模板缓冲区的指针。我们还没有,所以我们将其设置为NULL。
以上就是Direct3d 11的基本初始化。
d3d11DevCon->OMSetRenderTargets( 1, &renderTargetView, NULL );
清理
接下来,我们还有其他新功能。第一个,ReleaseObjects(),将释放我们创建的所有COM对象。不要忘记这样做,否则会导致内存泄漏。void ReleaseObjects()
{
//Release the COM Objects we created
SwapChain->Release();
d3d11Device->Release();
d3dDevCon->Release();
}
初始化场景
InitScene()函数将用于初始化场景。在视频游戏中,您可能会有许多不同的场景,因此您可能需要从InitScene()重命名它们。我们将放置我们的对象,加载我们的模型,纹理,声音,以及从该特定场景开始必须完成的所有工作。bool InitScene()
{
return true;
}
更新场景
接下来,我们有我们的UpdateScene()函数。我们将使用此功能来完成场景的所有更新,例如更改对象位置,更改值以及在场景中进行的所有更改。在本课程中,我们将仅更改背景的颜色,因此在更新场景功能中,我们将仅更改颜色。void UpdateScene()
{
//Update the colors of our scene
red += colormodr * 0.00005f;
green += colormodg * 0.00002f;
blue += colormodb * 0.00001f;
if(red >= 1.0f || red <= 0.0f)
colormodr *= -1;
if(green >= 1.0f || green <= 0.0f)
colormodg *= -1;
if(blue >= 1.0f || blue <= 0.0f)
colormodb *= -1;
}
渲染场景
现在我们有了DrawScene()函数。在这里,我们将简单地渲染场景。我们应该避免在该场景中进行任何更新,而仅在绘制场景时保留此功能。这是我们将更改背景颜色的地方。请记住,如果您来自DirectX的早期版本,例如DirectX 10,则所有呈现方法都已移至设备上下文接口,因此,与其像在DirectX 10中那样调用d3dDevice,我们将d3dDeviceContext对象称为获取ClearRenderTargetView方法,因为这是一种渲染方法。我们将调用d3dDevice来处理与GPU无关的其他事情,而不是渲染。最后,我们通过调用swapchain接口的Present方法来呈现场景。这是将前缓冲区与后缓冲区交换。在drawscene函数中,void DrawScene()
{
//Clear our backbuffer to the updated color
D3DXCOLOR bgColor( red, green, blue, 1.0f );
d3d11DevCon->ClearRenderTargetView(renderTargetView, bgColor);
//Present the backbuffer to the screen
SwapChain->Present(0, 0);
}
这是我们的messageloop()函数。它与上一课中创建窗口的过程几乎相同,但是现在当没有消息要检查时,我们将首先调用UpdateScene()函数来更新场景,然后调用DrawScene()函数,将场景绘制到后缓冲区并将后缓冲区呈现给屏幕。
int messageloop(){
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
while(true)
{
BOOL PeekMessageL(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
///**************new**************
// run game code
UpdateScene();
DrawScene();
///**************new**************
}
}
return msg.wParam;
}
错误检查:
这将节省您在调用函数时检查代码中错误的时间,因为即使函数未成功执行,应用程序仍可以继续运行。当函数返回时,您可以检查HRESULT的值以查看如何继续执行代码。这些是HRESULT的返回值:
S_OK
功能成功。
E_NOTIMPL
没有隐式功能。
E_NOINTERFACE
不支持该接口。
E_ABORT
该函数异常终止。
E_FAIL
功能失败。
E_INVALIDARG
一个或多个参数无效。
您可以显示通过调用DXGetErrorDescription(HRESULT hResult)函数返回的确切错误。如果要使用此功能,则需要链接到“ DXErr.lib”库并包括“ DXErr.h”标头。
以下是我们的带有错误检查功能的InitializeDirect3d11App()函数:(您将要确保在弹出错误框时未处于全屏状态。您可以在显示消息之前直接进入窗口模式来做到这一点。)
#pragma comment (lib, "DXErr.lib")
#include <DXErr.h>
...
bool InitializeDirect3d11App(HINSTANCE hInstance)
{
HRESULT hr;
//Describe our Buffer
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
bufferDesc.Width = Width;
bufferDesc.Height = Height;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
//Describe our SwapChain
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = hwnd;
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
//Create our SwapChain
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);
if(FAILED(hr))
{
MessageBox(NULL, DXGetErrorDescription(hr),
TEXT(" D3D11CreateDeviceAndSwapChain"), MB_OK);
return 0;
}
//Create our BackBuffer
ID3D11Texture2D* BackBuffer;
hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&BackBuffer );
if(FAILED(hr))
{
MessageBox(NULL, DXGetErrorDescription(hr),
TEXT("SwapChain->GetBuffer"), MB_OK);
return 0;
}
//Create our Render Target
hr = d3d11Device->CreateRenderTargetView( BackBuffer, NULL, &renderTargetView );
BackBuffer->Release();
if(FAILED(hr))
{
MessageBox(NULL, DXGetErrorDescription(hr),
TEXT("d3d11Device->CreateRenderTargetView"), MB_OK);
return 0;
}
//Set our Render Target
d3d11DevCon->OMSetRenderTargets( 1, &renderTargetView, NULL );
return true;
}
行使:
1.在本课中,我们创建了一个双缓冲区。 您的工作是创建三重缓冲! 这是完整的源代码:
///**************new**************
//Include and link appropriate libraries and headers//
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dx11.lib")
#pragma comment(lib, "d3dx10.lib")
#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
#include <xnamath.h>
//Global Declarations//
IDXGISwapChain* SwapChain;
ID3D11Device* d3d11Device;
ID3D11DeviceContext* d3d11DevCon;
ID3D11RenderTargetView* renderTargetView;
float red = 0.0f;
float green = 0.0f;
float blue = 0.0f;
int colormodr = 1;
int colormodg = 1;
int colormodb = 1;
///**************new**************
LPCTSTR WndClassName = L"firstwindow";
HWND hwnd = NULL;
const int Width = 300;
const int Height = 300;
///**************new**************
//Function Prototypes//
bool InitializeDirect3d11App(HINSTANCE hInstance);
void ReleaseObjects();
bool InitScene();
void UpdateScene();
void DrawScene();
///**************new**************
bool InitializeWindow(HINSTANCE hInstance,
int ShowWnd,
int width, int height,
bool windowed);
int messageloop();
LRESULT CALLBACK WndProc(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, //Main windows function
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
if(!InitializeWindow(hInstance, nShowCmd, Width, Height, true))
{
MessageBox(0, L"Window Initialization - Failed",
L"Error", MB_OK);
return 0;
}
///**************new**************
if(!InitializeDirect3d11App(hInstance)) //Initialize Direct3D
{
MessageBox(0, L"Direct3D Initialization - Failed",
L"Error", MB_OK);
return 0;
}
if(!InitScene()) //Initialize our scene
{
MessageBox(0, L"Scene Initialization - Failed",
L"Error", MB_OK);
return 0;
}
messageloop();
ReleaseObjects();
///**************new**************
return 0;
}
bool InitializeWindow(HINSTANCE hInstance,
int ShowWnd,
int width, int height,
bool windowed)
{
typedef struct _WNDCLASS {
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HANDLE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS;
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
wc.lpszMenuName = NULL;
wc.lpszClassName = WndClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Error registering class",
L"Error", MB_OK | MB_ICONERROR);
return 1;
}
hwnd = CreateWindowEx(
NULL,
WndClassName,
L"Window Title",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
width, height,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd)
{
MessageBox(NULL, L"Error creating window",
L"Error", MB_OK | MB_ICONERROR);
return 1;
}
ShowWindow(hwnd, ShowWnd);
UpdateWindow(hwnd);
return true;
}
///**************new**************
bool InitializeDirect3d11App(HINSTANCE hInstance)
{
//Describe our Buffer
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
bufferDesc.Width = Width;
bufferDesc.Height = Height;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
//Describe our SwapChain
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = hwnd;
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
//Create our SwapChain
D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL,
D3D11_SDK_VERSION, &swapChainDesc, &SwapChain, &d3d11Device, NULL, &d3d11DevCon);
//Create our BackBuffer
ID3D11Texture2D* BackBuffer;
SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (void**)&BackBuffer );
//Create our Render Target
d3d11Device->CreateRenderTargetView( BackBuffer, NULL, &renderTargetView );
BackBuffer->Release();
//Set our Render Target
d3d11DevCon->OMSetRenderTargets( 1, &renderTargetView, NULL );
return true;
}
void ReleaseObjects()
{
//Release the COM Objects we created
SwapChain->Release();
d3d11Device->Release();
d3d11DevCon->Release();
}
bool InitScene()
{
return true;
}
void UpdateScene()
{
//Update the colors of our scene
red += colormodr * 0.00005f;
green += colormodg * 0.00002f;
blue += colormodb * 0.00001f;
if(red >= 1.0f || red <= 0.0f)
colormodr *= -1;
if(green >= 1.0f || green <= 0.0f)
colormodg *= -1;
if(blue >= 1.0f || blue <= 0.0f)
colormodb *= -1;
}
void DrawScene()
{
//Clear our backbuffer to the updated color
D3DXCOLOR bgColor( red, green, blue, 1.0f );
d3d11DevCon->ClearRenderTargetView(renderTargetView, bgColor);
//Present the backbuffer to the screen
SwapChain->Present(0, 0);
}
///**************new**************
int messageloop(){
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
while(true)
{
BOOL PeekMessageL(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
///**************new**************
// run game code
UpdateScene();
DrawScene();
///**************new**************
}
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
switch( msg )
{
case WM_KEYDOWN:
if( wParam == VK_ESCAPE ){
DestroyWindow(hwnd);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,
msg,
wParam,
lParam);
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)