Direct3D 11 Tutorial 1: Basics_Direct3D 11 教程1:基础

Github-LearnDirectX-DX3D11 tutorial01git

概述

在这第一篇教程中,咱们将经过介绍建立最小Direct3D应用程序所必需的元素。每个Direct3D应用程序必需拥有这些元素才能正常地工做。这些元素包括设置窗口和设备对象,以及在窗口上显示颜色。github

资源目录

(SDK root)\Samples\C++\Direct3D11\Tutorials\Tutorial01数组

 

设置Direct3D 11 设备

第一步是建立一个窗口和消息循环,这些在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()方法。

  • 首先,咱们定义一个由四个浮点数组成的数组,用于描述咱们想要填充屏幕的颜色。
  • 接着,咱们将它传递给ClearRenderTargetView()。在这个例子中,咱们选择了蓝色的阴影。
  • 填充后台缓冲区后,咱们调用交换链的Present()方法来完成渲染。 Present()负责将交换链的后台缓冲区内容显示在屏幕上,以便用户能够看到它。Render()函数看起来像是这样的:
    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(在本文首部)。

相关文章
相关标签/搜索