Direct3D 11 教程1:Direct3D 11基础

D3D10 SDK 专栏收录该内容
12 篇文章 1 订阅

概览

在第一个教程中,我们学习了创建一个最小Direct3D 11应用程序所需的元素,每个Direct3D 11应用程序必须包含这些元素才能正常工作,这些元素包括创建一个窗口和设备对象,然后才能在窗口中显示颜色。

程序截图

源代码

(SDK root)\Samples\C++\Direct3D11\Tutorials\Tutorial01。

创建Direct3D 11设备

第一个步骤中的创建窗口和消息循环在Direct3D 9、Direct3D 10、Direct3D 11都是相同的,可参见Direct3D 10教程0:Win32编程基础理解这个过程。当显示了一个窗口后,下面继续创建一个Direct3D 11设备,这个设备用于绘制3D场景。首先必须创建三个对象:一个设备、一个立即执行上下文(immediate context)和一个交换链(Swap Chain),立即执行上下文对象是Direct3D 11中新添加的。

在Direct3D 10中,设备同时用来绘制和资源的创建。在Direct3D 11中,立即执行上下文用于将内容绘制到缓存,而设备用于创建资源。

当显示了一个窗口后,下面继续创建一个Direct3D 11设备,这个设备用于绘制3D场景。首先必须创建两个对象:一个设备和一个交换链(Swap Chain)

设备对象用于将内容绘制在一个缓冲中,设备还包含创建资源的方法。

交换链即表示对缓冲的操作,这些缓冲就是设备绘制的和显示在屏幕上的内容。交换链包含两个或两个以上的缓冲,主要是前缓冲和后备缓冲,它们就是设备绘制形成的纹理,用于显示在屏幕上。前缓冲(front buffer)就是当前显示在屏幕上的内容,这个缓冲是只读的,无法修改。后备缓冲(back buffer)是设备将要绘制的渲染目标,一旦它完成了绘制操作,交换链就会通过交换前缓冲和后备缓冲,将后备缓冲的内容显示在屏幕上,此时后备缓冲就变成了前缓冲。

要创建交换链,我们需要设置一个DXGI_SWAPCHAIN_DESC结构体说明将要创建的交换链。此结构体的几个字段需要说明一下:BackBufferUsage标志告诉程序我们使用后备缓冲的方式。本例中我们想绘制到后备缓冲,所以将BackBufferUsage设置为DXGI_USAGE_RENDER_TARGET_OUTPUTOutputWindow字段表示交换链将使用的窗口,在这个窗口上我们显示图像。SampleDesc用来开启多重采样(multi-sampling),因为这个教程不使用多重采样,SampleDesc的Count设置为1,Quality设置为0,这样就禁用了多重采样。

设置好这个描述结构体后,我们就可以调用D3D11CreateDeviceAndSwapChaing方法创建设备和交换链。代码如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
DXGI_SWAP_CHAIN_DESC sd;
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 ( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
{
     g_driverType = driverTypes[driverTypeIndex];
     hr = D3D11CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags,
                                         D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice,
                                             NULL, &g_pImmediateContext);
     if ( SUCCEEDED( hr ) )
         break ;
}
if ( FAILED( hr ) )
     return hr;

下一步需要创建一个渲染目标视图(render target view)。渲染目标视图是Direct3D 11中一种资源视图(resource view)。资源视图可以让一个资源绑定到图形管线的某个阶段。可以将资源视图看成C中的类型转换,C中的一块原始内存(raw memory)可以被转换为任意数据结构,我们可以将一块内存转换为整数数组,浮点数数组,结构,结构数组等。如果我们不知道原始内存的类型,那么它对我们来说用处不大。Direct3D 11的资源视图工作原理类似,例如一张2D纹理就类似于一块原始内存,就是一种原始基础资源,有了这个原始资源,我们就可以创建不同的资源视图将这个纹理以不同的格式绑定到图形管线的不同阶段,而不同的格式可以是要绘制的渲染目标,接收深度信息的深度模板缓冲,或者也可以是一个纹理资源。C中的类型转换可以以不同方式使用一块内存,而在Direct3D 11中是资源视图进行类似的操作。

因为我们需要将交换链中的后备缓冲绑定为一个渲染目标,所以需要创建一个渲染目标视图,这样Direct3D 11就可以在其上进行绘制了。我们首先调用GetBuffer() 方法获取后备缓冲对象。我们可以使用一个D3D11_RENDERTARGETVIEW_DESC结构体表示要创建的渲染目标视图,这个结构体通常是CreateRenderTargetView方法的第二个参数。但是,在本教程中,默认的渲染目标视图就能满足需要,所以第二个参数为NULL表示使用默认的渲染目标视图。创建了渲染目标视图后,我们就可以调用OMSetRenderTargets()方法将它绑定到图形管线,这样管线的绘制输出被写到了后备缓冲中。创建并设置渲染目标视图的代码如下:


1
2
3
4
5
6
7
8
9
10
11
12
// Create a render target view
ID3D11Texture2D* pBackBuffer;
hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID * )&pBackBuffer );
if ( FAILED( hr ) )
     return hr;
 
hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView );
pBackBuffer->Release();
if ( FAILED( hr ) )
     return hr;
 
g_pd3dDevice->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );

最后,我们需要初始化视口(viewport)。视口剪裁空间坐标(X和Y的范围从-1到1,Z的范围从0到1)映射到渲染空间(有时又称为像素空间)。在Direct3D 9中,如果程序没有设置视口,会创建一个与渲染目标相同大小的默认视口。在Direct3D 11中,没有默认视口,我们必须事先设定。因为我们想将整个渲染目标输出,所以设置左上点为(0, 0),宽度和高度与渲染目标相同。代码如下:


1
2
3
4
5
6
7
8
9
// 设置视口
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()会将应用程序置于“睡眠”状态。这样会导致在程序进行绘制时,当消息队列为空时,应用程序会处于等待状态。我们可以使用PeekMessage()代替GetMessage()来解决这个问题。PeekMessage()像GetMessage()一样可以接收消息,当没有消息处于等待时,PeekMessage()会立即返回给应用程序一个FALSE值而不是处于休眠状态。这样我们就可以利用这段时间进行绘制的工作。修改过的消息循环的代码如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Main message loop
MSG msg = {0};
while ( WM_QUIT != msg.message )
{
     if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
     {
         TranslateMessage( &msg );
         DispatchMessage( &msg );
     }
     else
     {
         Render();
     }
}

绘制代码

绘制过程是在Render()方法中进行的。在本教程中,我们想让过程尽量简单,所以就用单色填充屏幕。在Direct3D 10中,要将一种颜色填充渲染目标的简单方法就是使用设备的ClearRenderTargetView()方法。我们首先定义一个包含四个浮点数的数组设置要显示的颜色,然后将这个数组传递到ClearRenderTargetView()方法中。本例中使用的是蓝色。填充了后备缓冲后,就可以调用交换链的Present()方法完成绘制。Present()负责将后备缓冲的内容显示在屏幕上。Render()方法的代码如下:


1
2
3
4
5
6
7
void Render()
{
     // Just clear the backbuffer
     float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
     g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );
     g_pSwapChain->Present( 0, 0 );
}
  • 1
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

本书是基于DirectX 9.0编写的,是介绍Direct3D技术的入门教程。它详细介绍了Direct3D的背景、基本知识以及3D程序设计的相关概念与技术。全书由浅入深,分为四个部分,第一部分介绍Direct3D的发展历史和基本知识,对3D程序设计中的术语、概念进行了深入讲解;第二部分着重讨论纹理映射技术,包括多重纹理等;第三部分通过多个示例来探讨高级shader编程,并对.MD3文件格式做了详细分析;第四部分是附录,对本书中用到的概念和技术背景进行了简单补充。 本书适用于略有DirectX基础的C/C++程序员学习Direct3D游戏开发,也适用于具有Direct3D开发经验的程序员参考。 本书是学习DirectX3D图形编程的入门教程。它从基础知识开始逐步介绍各项技术,最终让你轻松掌握图形编程和动画编程的方法。相对于第一版,本书深入介绍了顶点shader和像素shader编程,覆盖了微软最新的HLSL(高级Shader语言),集中介绍了固定功能的渲染流水线,并在最后介绍了一些高级的shader效果,从而可使你的游戏具有更真实的视觉表现。 这本由业界资深专家编写的入门教程将带领你实现、甚至超越那些你不断在想象的3D图形效果! 第1部分 DirectX图形Don’t Hurt Me 第1Direct3D/DirectX的历史 11 DirectX 2.0 1.2 DirectX 6/7 1.3 DirectX 8 1.3.1 Point Sprite 1.3.2 3D纹理 1.3.3 Direct3DX实用程序库 1.3.4 顶点Shader和像素Shader 1.4 DirectX 9 1.5 小结 第2章 HAL和COM概述 2.1 硬件抽象层(Hardware Abstraction Layer,HAL) 2.2 插件式软件设备(Pluggable Software Device) 2.3 参考光栅器(Reference Rasterizer) 2.4 设备控制 2.5 COM 2.6 小结 第3章 编程约定
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值