03.初始化Direct3D 11

在这里,我们声明我们的全局变量。第一个声明是一个COM接口对象。这是我们的SwapChain,用于将后缓冲区更改为前缓冲区,并将前缓冲区更改为后缓冲区。这称为双缓冲。渲染场景时,我们正在渲染到后缓冲区,因此,当我们将后缓冲区呈现给监视器时,它将被完全绘制。否则,我们将获得扫描线,即通常可以从上到下看到程序将场景绘制到屏幕上的情况。接下来是一个接口,我们将使用它来表示我们的硬件设备(GPU)。现在,此后的一行是DirectX 11附带的新接口。ID3D11Device接口被拆分为两个,以帮助支持新的多线程功能。我们将使用ID3D11DeviceContext接口对象来调用所有呈现方法, 我将更好地解释将ID3D11Device分为两部分的原因。DirectX 11具有新的多线程功能,用于加速应用程序。将某些内容加载到内存中(例如模型)或创建对象时,将调用ID3D11Device对象。在加载或创建对象或模型时,可以调用ID3D11DeviceContext接口对象以继续渲染场景。这将消除加载模型,创建对象或类似情况时对性能的影响。它不是很难理解的主意,所以我希望您能遵循我的意思。 因此,在那之后,我们还有另一个接口对象,即渲染目标视图。基本上,我们不直接写入屏幕,而是写入渲染目标视图,该视图是2d纹理(我们的后缓冲)。然后将此纹理发送到管道的输出合并阶段作为渲染目标,然后将其渲染到屏幕。 接下来的6行用于更改背景的颜色,对本课程而言并不重要。
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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要使用Microsoft.DirectX.DirectSound,您需要遵循以下步骤: 1. 首先,确保您的项目引用了Microsoft.DirectX.DirectSound程序集。您可以在Visual Studio中右键单击项目,选择“添加引用”,然后在“COM”选项卡中找到并选中“Microsoft.DirectX.DirectSound”。 2. 在代码文件的顶部,添加以下命名空间: ```csharp using Microsoft.DirectX.DirectSound; ``` 3. 创建一个DirectSound设备对象,用于管理声音的初始化和播放。例如: ```csharp Device device = new Device(); device.SetCooperativeLevel(yourForm, CooperativeLevel.Normal); ``` 这里的`yourForm`是你的窗体对象,`CooperativeLevel.Normal`表示以普通协作级别初始化设备。 4. 创建一个或多个缓冲区对象,用于存储声音数据。例如: ```csharp BufferDescription bufferDesc = new BufferDescription(); bufferDesc.Flags = BufferDescriptionFlags.ControlVolume; bufferDesc.PrimaryBuffer = true; SecondaryBuffer buffer = new SecondaryBuffer(bufferDesc, device); ``` 5. 加载音频文件并将其数据填充到缓冲区中。例如: ```csharp buffer = new SecondaryBuffer("yourSoundFile.wav", bufferDesc, device); ``` 6. 控制缓冲区的播放和停止。例如: ```csharp buffer.Play(0, BufferPlayFlags.Default); buffer.Stop(); ``` 这只是使用Microsoft.DirectX.DirectSound的基本示例。您可以根据您的需求进行更多高级操作,例如控制音量、平衡、3D空间效果等。请参考Microsoft.DirectX.DirectSound的文档和示例以获取更多详细信息和用法示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

szmtjs10

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值