Github-LearnDirectX-DX3D11 tutorial01git
在這第一篇教程中,咱們將經過介紹建立最小Direct3D應用程序所必需的元素。每個Direct3D應用程序必需擁有這些元素才能正常地工做。這些元素包括設置窗口和設備對象,以及在窗口上顯示顏色。github
(SDK root)\Samples\C++\Direct3D11\Tutorials\Tutorial01數組
第一步是建立一個窗口和消息循環,這些在Direct3D 9, Direct3D 10, 和Direct3D 11都是相同的。有關此過程的介紹,請參閱Direct3D 10教程00:Win 32 Basics。如今咱們有了一個正在顯示的窗口,咱們能夠繼續設置一個Direct3D 11設備。若是咱們將要渲染任何3D場景,設置這個是有必要的。首先要作的是建立三個對象:一個設備(device),一個直接的上下文(immediate context),一個交換鏈(swap chain)。直接上下文是Direct3d 11中的一個新對象。函數
在Direct3D 10中,設備對象用於執行渲染和資源的建立。在Direct3D 11中,應用程序使用直接上下文對緩衝區執行渲染,設備中包含建立資源的方法。學習
交換鏈負責接收設備渲染的緩衝區,並在實際監視器屏幕上顯示內容。交換鏈包含兩個或多個緩衝區,主要是前面和後面。這些紋理是設備爲了在監視器上顯示而呈現的紋理。前臺緩衝區是當前呈現給用戶的內容。這個緩衝區是隻能讀,不能作修改。後臺緩衝區是設備將要繪製的渲染目標。一旦設備完成了繪圖操做,交換鏈將經過交換兩個緩衝區來顯示後臺緩衝區。此時後臺緩衝區變成了前臺緩衝區,反之亦然。ui
爲了建立交換鏈,咱們填寫 DXGI_SWAPCHAIN_DESC 結構來描述咱們即將建立的交換鏈。有一些字段值得一提。BackBufferUsage是一個標誌,它告訴應用程序如何使用後臺緩衝區。 在這種狀況下,咱們想要渲染到後臺緩衝區,所以咱們將 BackBufferUsage 設置爲 DXGI_USAGE_RENDER_TARGET_OUTPUT。OutputWindow字段表示交換鏈將用於在屏幕上顯示圖像的窗口。SampleDesc用於啓用屢次採樣。 因爲本教程不使用屢次採樣,所以SampleDesc的Count設置爲1,Quality設置爲0以禁用屢次採樣。spa
填寫完描述後,咱們能夠調用D3D11CreateDeviceAndSwapChain函數爲咱們建立設備和交換鏈。如下是建立設備和交換鏈的代碼:翻譯
DXGI_SWAP_CHAIN_DESC sd; 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( D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, NULL, &g_pImmediateContext ) ) ) { return FALSE; }
接下來咱們要作的事情是建立一個渲染目標的視圖。3d
渲染目標視圖是Direct3D 11裏的一種資源視圖。資源視圖容許資源在特定場合綁定到圖形管道上。將資源視圖當作是C語言中的類型轉換。C中的一塊原始內存能夠轉換爲任何數據類型。咱們能夠將這塊內存轉換爲整數數組,浮點數組,結構數組,結構數組等等。若是咱們不知道它的類型,原始內存自己對咱們沒有太大用處。Direct3D 11中的資源視圖與該方法相似。例如,一個2D紋理,相似於原始內存塊,是原始的底層資源。一旦咱們擁有了該資源,咱們就能夠建立不一樣的資源視圖,將該紋理綁定到不一樣格式的圖形管道中的不一樣階段:做爲要渲染的渲染目標,做爲將接收深度信息的深度模板緩衝區,或做爲紋理資源。在C語言類型轉換中容許以不一樣的方式使用內存塊的狀況下,Direct3D 11資源視圖也是如此。orm
咱們須要建立一個渲染目標視圖,由於咱們想將交換鏈中的後臺緩衝區綁定爲咱們的渲染目標。這樣可以使Direct3D 11渲染到它上面。咱們首先調用GetBuffer()來獲取後臺緩衝區對象。或者,咱們能夠填寫D3D11_RENDERTARGETVIEW_DESC結構,該結構描述要建立的渲染目標視圖。此描述一般是CreateRenderTargetView的第二個參數。然而,對於這些教程,默認的渲染目標視圖已經足夠了。能夠經過傳遞NULL做爲第二個參數來獲取默認的渲染目標視圖。一旦咱們建立了渲染目標視圖,咱們就能夠在直接上下文中調用OMSetRenderTargets()來將它綁定到管道上。這可確保管道呈現的輸出被寫入後臺緩衝區。建立和設置渲染目標視圖的代碼以下:
// Create a render target view ID3D11Texture2D *pBackBuffer; if( FAILED( g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pBackBuffer ) ) ) return FALSE; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return FALSE; g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );
在Direct3D 11渲染以前咱們須要設置的最後一件事是初始化視口。
視口映射剪輯空間座標,其中X和Y的範圍爲-1到1,Z的範圍爲0到1,以渲染目標空間,有時稱爲像素空間。 在Direct3D 9中,若是應用程序未設置視口,則默認視口設置爲與渲染目標的大小相同。在Direct3D 11中,默認狀況下不設置視口。 所以,咱們必須在屏幕上看到任何內容以前這樣作。因爲咱們但願將整個渲染目標用於輸出,所以咱們將左上角的點設置爲(0,0),將寬度和高度設置爲與渲染目標的大小相同。 爲此,請使用如下代碼:
D3D11_VIEWPORT vp; vp.Width = (FLOAT)width; vp.Height = (FLOAT)height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; g_pImmediateContext->RSSetViewports( 1, &vp );
咱們已經設置了窗口和Direct3D 11設備而且咱們已準備好渲染。 可是,咱們的消息循環仍然存在問題:它使用GetMessage()來獲取消息。GetMessage()的問題在於,若是應用程序窗口的隊列中沒有消息,則GetMessage()會阻塞,而且在消息可用以前不會返回。所以,當消息隊列爲空時,咱們的應用程序在GetMessage()內等待,而不是像渲染那樣。咱們能夠使用PeekMessage()而不是GetMessage()來解決這個問題。 PeekMessage()能夠檢索像GetMessage()那樣的消息,可是當沒有消息等待時,PeekMessage()會當即返回而不是阻塞。 而後咱們能夠花時間作一些渲染。 使用PeekMessage()的修改後的消息循環以下所示:
MSG msg = {0}; while( WM_QUIT != msg.message ) { if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { Render(); // Do some rendering } }
渲染在Render()函數中完成。
在這個教程中,咱們將渲染最簡單的場景,即用單一顏色填充屏幕。在Direct3D 11中,使用單一顏色填充渲染目標的簡單方法是使用直接上下文的ClearRenderTargetView()方法。
void Render() { // // Clear the backbuffer // float ClearColor[4] = { 0.0f, 0.125f, 0.6f, 1.0f }; // RGBA g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor ); g_pSwapChain->Present( 0, 0 ); }
本教程最終的運行效果:
本教程是我在學習DirectX中查看SDK文檔中看到的,所以想在國慶期間翻譯成中文,方便之後查閱。
教程總共有七篇:
但願翻譯過的教程能對學習DX的朋友們有所幫助,本教程的源碼我已上傳至Github(在本文首部)。