Direct3D11教程1Direct3D11基础Word下载.docx
《Direct3D11教程1Direct3D11基础Word下载.docx》由会员分享,可在线阅读,更多相关《Direct3D11教程1Direct3D11基础Word下载.docx(12页珍藏版)》请在冰豆网上搜索。
![Direct3D11教程1Direct3D11基础Word下载.docx](https://file1.bdocx.com/fileroot1/2022-12/8/87845600-bceb-426f-8b27-52cca5455c8a/87845600-bceb-426f-8b27-52cca5455c8a1.gif)
设置好这个描述结构体后,我们就可以调用D3D11CreateDeviceAndSwapChaing方法创建设备和交换链。
代码如下:
DXGI_SWAP_CHAIN_DESCsd;
ZeroMemory(&
sd,sizeof(sd));
sd.BufferCount=1;
sd.BufferDesc.Width=640;
sd.BufferDesc.Height=480;
sd.BufferDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator=60;
sd.BufferDesc.RefreshRate.Denominator=1;
sd.BufferUsage=DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow=g_hWnd;
sd.SampleDesc.Count=1;
sd.SampleDesc.Quality=0;
sd.Windowed=TRUE;
if(FAILED(D3D10CreateDeviceAndSwapChain(NULL,D3D11_DRIVER_TYPE_REFERENCE,NULL,0,D3D11_SDK_VERSION,&
sd,&
g_pSwapChain,&
g_pd3dDevice,NULL,&
g_pImmediateContext)))
{
returnFALSE;
}
下一步需要创建一个渲染目标视图(rendertargetview)。
渲染目标视图是Direct3D10中一种资源视图(resourceview)。
资源视图可以让一个资源绑定到图形管线的某个阶段。
可以将资源视图看成C中的类型转换,C中的一块原始内存(rawmemory)可以被转换为任意数据结构,我们可以将一块内存转换为整数数组,浮点数数组,结构,结构数组等。
如果我们不知道原始内存的类型,那么它对我们来说用处不大。
Direct3D11的资源视图工作原理类似,例如一张2D纹理就类似于一块原始内存,就是一种原始基础资源,有了这个原始资源,我们就可以创建不同的资源视图将这个纹理以不同的格式绑定到图形管线的不同阶段,而不同的格式可以是要绘制的渲染目标,接收深度信息的深度模板缓冲,或者也可以是一个纹理资源。
C中的类型转换可以以不同方式使用一块内存,而在Direct3D11中是资源视图进行类似的操作。
因为我们需要将交换链中的后备缓冲绑定为一个渲染目标,所以需要创建一个渲染目标视图,这样Direct3D11就可以在其上进行绘制了。
我们首先调用GetBuffer()方法获取后备缓冲对象。
我们可以使用一个D3D11_RENDERTARGETVIEW_DESC结构体表示要创建的渲染目标视图,这个结构体通常是CreateRenderTargetView方法的第二个参数。
但是,在本教程中,默认的渲染目标视图就能满足需要,所以第二个参数为NULL表示使用默认的渲染目标视图。
创建了渲染目标视图后,我们就可以调用OMSetRenderTargets()方法将它绑定到图形管线,这样管线的绘制输出被写到了后备缓冲中。
创建并设置渲染目标视图的代码如下:
//创建一个rendertargetview
ID3D11Texture2D*pBackBuffer;
if(FAILED(g_pSwapChain->
GetBuffer(0,__uuidof(ID3D11Texture2D),(LPVOID*)&
pBackBuffer)))
hr=g_pd3dDevice->
CreateRenderTargetView(pBackBuffer,NULL,&
g_pRenderTargetView);
pBackBuffer->
Release();
if(FAILED(hr))
g_pImmediateContext->
OMSetRenderTargets(1,&
g_pRenderTargetView,NULL);
最后,我们需要初始化视口(viewport)。
视口剪裁空间坐标(X和Y的范围从-1到1,Z的范围从0到1)映射到渲染空间(有时又称为像素空间)。
在Direct3D9中,如果程序没有设置视口,会创建一个与渲染目标相同大小的默认视口。
在Direct3D11中,没有默认视口,我们必须事先设定。
因为我们想将整个渲染目标输出,所以设置左上点为(0,0),宽度和高度与渲染目标相同。
D3D10_VIEWPORTvp;
vp.Width=(FLOAT)640;
vp.Height=(FLOAT)480;
vp.MinDepth=0.0f;
vp.MaxDepth=1.0f;
vp.TopLeftX=0;
vp.TopLeftY=0;
g_pImmediateContext->
RSSetViewports(1,&
vp);
修改消息循环
创建了窗口和Direct3D11设备后,就做好了绘制的准备。
但是在处理消息循环环节还有一个问题:
我们使用的是GetMessage()获取消息,使用GetMessage()带来的问题是当没有消息可返回给应用程序时,GetMessage()会将应用程序置于“睡眠”状态。
这样会导致在程序进行绘制时,当消息队列为空时,应用程序会处于等待状态。
我们可以使用PeekMessage()代替GetMessage()来解决这个问题。
PeekMessage()像GetMessage()一样可以接收消息,当没有消息处于等待时,PeekMessage()会立即返回给应用程序一个FALSE值而不是处于休眠状态。
这样我们就可以利用这段时间进行绘制的工作。
修改过的消息循环的代码如下:
MSGmsg={0};
while(WM_QUIT!
=msg.message)
if(PeekMessage(&
msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&
msg);
DispatchMessage(&
}
else
Render();
//进行绘制
绘制代码
绘制过程是在Render()方法中进行的。
在本教程中,我们想让过程尽量简单,所以就用单色填充屏幕。
在Direct3D11中,要将一种颜色填充渲染目标的简单方法就是使用设备的ClearRenderTargetView()方法。
我们首先定义一个包含四个浮点数的数组设置要显示的颜色,然后将这个数组传递到ClearRenderTargetView()方法中。
本例中使用的是蓝色。
填充了后备缓冲后,就可以调用交换链的Present()方法完成绘制。
Present()负责将后备缓冲的内容显示在屏幕上。
Render()方法的代码如下:
voidRender()
//
//清除后备缓冲
floatClearColor[4]={0.0f,0.125f,0.6f,1.0f};
//RGBA
g_pImmediateContext->
ClearRenderTargetView(g_pRenderTargetView,ClearColor);
g_pSwapChain->
Present(0,0);
完整代码
//Copyright(c)MicrosoftCorporation.Allrightsreserved.
//--------------------------------------------------------------------------------------
#include<
windows.h>
d3d11.h>
#include"
resource.h"
//全局变量
HINSTANCEg_hInst=NULL;
HWNDg_hWnd=NULL;
D3D_DRIVER_TYPEg_driverType=D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVELg_featureLevel=D3D_FEATURE_LEVEL_11_0;
ID3D11Device*g_pd3dDevice=NULL;
ID3D11DeviceContext*g_pImmediateContext=NULL;
IDXGISwapChain*g_pSwapChain=NULL;
ID3D11RenderTargetView*g_pRenderTargetView=NULL;
//函数声明
HRESULTInitWindow(HINSTANCEhInstance,intnCmdShow);
HRESULTInitDevice();
voidCleanupDevice();
LRESULTCALLBACKWndProc(HWND,UINT,WPARAM,LPARAM);
voidRender();
//程序入口。
初始化,并进入消息循环。
空闲时间用来绘制场景。
intWINAPIwWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,LPWSTRlpCmdLine,intnCmdShow)
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
if(FAILED(InitWindow(hInstance,nCmdShow)))
return0;
if(FAILED(InitDevice()))
CleanupDevice();
//消息循环
MSGmsg={0};
while(WM_QUIT!
return(int)msg.wParam;
//注册窗口类并创建窗口
HRESULTInitWindow(HINSTANCEhInstance,intnCmdShow)
//注册窗口类
WNDCLASSEXwcex;
wcex.cbSize=sizeof(WNDCLASSEX);
wcex.style=CS_HREDRAW|CS_VREDRAW;
wcex.lpfnWndProc=WndProc;
wcex.cbClsExtra=0;
wcex.cbWndExtra=0;
wcex.hInstance=hInstance;
wcex.hIcon=LoadIcon(hInstance,(LPCTSTR)IDI_TUTORIAL1);
wcex.hCursor=LoadCursor(NULL,IDC_ARROW);
wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName=NULL;
wcex.lpszClassName=L"
TutorialWindowClass"
;
wcex.hIconSm=LoadIcon(wcex.hInstance,(LPCTSTR)IDI_TUTORIAL1);
if(!
RegisterClassEx(&
wcex))
returnE_FAIL;
//创建窗口
g_hInst=hInstance;
RECTrc={0,0,640,480};
AdjustWindowRect(&
rc,WS_OVERLAPPEDWINDOW,FALSE);
g_hWnd=CreateWindow(L"
L"
Direct3D11Tutorial1:
Direct3D11Basics"
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,rc.right-rc.left,rc.bottom-rc.top,NULL,NULL,hInstance,
NULL);
g_hWnd)
ShowWindow(g_hWnd,nCmdShow);
returnS_OK;
//每次当应用程序接收消息时调用这个方法
LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)
PAINTSTRUCTps;
HDChdc;
switch(message)
caseWM_PAINT:
hdc=BeginPaint(hWnd,&
ps);
EndPaint(hWnd,&
break;
caseWM_DESTROY:
PostQuitMessage(0);
default:
returnDefWindowProc(hWnd,message,wParam,lParam);
//创建Direct3D设备和交换链
HRESULTInitDevice()
HRESULThr=S_OK;
RECTrc;
GetClientRect(g_hWnd,&
rc);
UINTwidth=rc.right-rc.left;
UINTheight=rc.bottom-rc.top;
UINTcreateDeviceFlags=0;
#ifdef_DEBUG
createDeviceFlags|=D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_DRIVER_TYPEdriverTypes[]=
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINTnumDriverTypes=ARRAYSIZE(driverTypes);
D3D_FEATURE_LEVELfeatureLevels[]=
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
UINTnumFeatureLevels=ARRAYSIZE(featureLevels);
DXGI_SWAP_CHAIN_DESCsd;
ZeroMemory(&
sd,sizeof(sd));
sd.BufferCount=1;
sd.BufferDesc.Width=width;
sd.BufferDesc.Height=height;
sd.BufferDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator=60;
sd.BufferDesc.RefreshRate.Denominator=1;
sd.BufferUsage=DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow=g_hWnd;
sd.SampleDesc.Count=1;
sd.SampleDesc.Quality=0;
sd.Windowed=TRUE;
for(UINTdriverTypeIndex=0;
driverTypeIndex<
numDriverTypes;
driverTypeIndex++)
g_driverType=driverTypes[driverTypeIndex];
hr=D3D11CreateDeviceAndSwapChain(NULL,g_driverType,NULL,createDeviceFlags,featureLevels,numFeatureLevels,
D3D11_SDK_VERSION,&
g_pd3dDevice,&
g_featureLevel,&
g_pImmediateContext);
if(SUCCEEDED(hr))
if(FAILED(hr))
returnhr;
//创建渲染目标视图
ID3D11Texture2D*pBackBuffer=NULL;
hr=g_pSwapChain->
GetBuffer(0,__uuidof(ID3D11Texture2D),(LPVOID*)&
pBackBuffer);
hr=g_pd3dDevice->
CreateRenderTargetView(pBackBu