Github-LearnDirectX-DX3D11 tutorial01

概述

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

资源目录

(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中,应用程序使用直接上下文对缓冲区执行渲染,设备中包含创建资源的方法。

交换链负责接收设备渲染的缓冲区,并在实际监视器屏幕上显示内容。交换链包含两个或多个缓冲区,主要是前面和后面。这些纹理是设备为了在监视器上显示而呈现的纹理。前台缓冲区是当前呈现给用户的内容。这个缓冲区是只能读,不能做修改。后台缓冲区是设备将要绘制的渲染目标。一旦设备完成了绘图操作,交换链将通过交换两个缓冲区来显示后台缓冲区。此时后台缓冲区变成了前台缓冲区,反之亦然。

为了创建交换链,我们填写 DXGI_SWAPCHAIN_DESC 结构来描述我们即将创建的交换链。有一些字段值得一提。BackBufferUsage是一个标志,它告诉应用程序如何使用后台缓冲区。 在这种情况下,我们想要渲染到后台缓冲区,因此我们将 BackBufferUsage 设置为 DXGI_USAGE_RENDER_TARGET_OUTPUT。OutputWindow字段表示交换链将用于在屏幕上显示图像的窗口。SampleDesc用于启用多次采样。 由于本教程不使用多次采样,因此SampleDesc的Count设置为1,Quality设置为0以禁用多次采样。

填写完描述后,我们可以调用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;
}

  

接下来我们要做的事情是创建一个渲染目标的视图。

渲染目标视图是Direct3D 11里的一种资源视图。资源视图允许资源在特定场合绑定到图形管道上。将资源视图看成是C语言中的类型转换。C中的一块原始内存可以转换为任何数据类型。我们可以将这块内存转换为整数数组,浮点数组,结构数组,结构数组等等。如果我们不知道它的类型,原始内存本身对我们没有太大用处。Direct3D 11中的资源视图与该方法类似。例如,一个2D纹理,类似于原始内存块,是原始的底层资源。一旦我们拥有了该资源,我们就可以创建不同的资源视图,将该纹理绑定到不同格式的图形管道中的不同阶段:作为要渲染的渲染目标,作为将接收深度信息的深度模板缓冲区,或作为纹理资源。在C语言类型转换中允许以不同的方式使用内存块的情况下,Direct3D 11资源视图也是如此。

我们需要创建一个渲染目标视图,因为我们想将交换链中的后台缓冲区绑定为我们的渲染目标。这样能够使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(在本文首部)。

Direct3D 11 Tutorial 1: Basics_Direct3D 11 教程1:基础的更多相关文章

  1. Direct3D 11 Tutorial 6:Lighting_Direct3D 11 教程6:灯光

    概述 在之前的教程中,世界看起来很无聊,因为所有对象都以相同的方式点亮. 本教程将介绍简单照明的概念及其应用方法. 使用的技术将是朗伯照明. 本教程的结果将修改前面的示例以包含光源. 该光源将附在轨道 ...

  2. Java 11 Tutorial

    Java 11 Tutorial 参考 https://blog.csdn.net/sihai12345/article/details/82889827 原文 https://winterbe.co ...

  3. 【转】正则表达式简介及在C++11中的简单使用教程

    正则表达式Regex(regular expression)是一种强大的描述字符序列的工具.在许多语言中都存在着正则表达式,C++11中也将正则表达式纳入了新标准的一部分,不仅如此,它还支持了6种不同 ...

  4. Gitlab 11.9.1 高可用教程

    Gitlab 11.9.1 高可用教程 一. PostgreSQL数据迁移 由于默认Gitlab的安装会内置Postgres数据库,并且没有对外,所以我们需要通过设置对应的Gitlab的配置将其中的数 ...

  5. MapServer Tutorial——MapServer7.2.1教程学习——第一节用例实践:Example1.7 Adding a wms layer

    MapServer Tutorial——MapServer7.2.1教程学习——第一节用例实践:Example1.7 Adding a wms layer 前言 Add OGC WMS Layers( ...

  6. MapServer Tutorial——MapServer7.2.1教程学习——第一节用例实践:Example1.6 Defining Projections and Extents

    MapServer Tutorial——MapServer7.2.1教程学习——第一节用例实践:Example1.6 Defining Projections and Extents 一.前言 当在m ...

  7. MapServer Tutorial——MapServer7.2.1教程学习——第一节用例实践:Example1.3 Displaying Classes in a Layer

    MapServer Tutorial——MapServer7.2.1教程学习——第一节用例实践:Example1.3 Displaying Classes in a Layer 一.前言 关于第一节的 ...

  8. PSU 离11.2.0.3.0 -> 11.2.0.3.11 如果解决冲突的整个

    Oracle rdbms 扑灭psu离11.2.0.3.0升级到11.2.0.3.11 参考patch :18522512 停止应用,停止听音乐并DB,将db的oracle_home在下面OPatch ...

  9. Oracle DataGuard 升级 [11.2.0.1 -> 11.2.0.4]

    Oracle DataGuard 升级 [11.2.0.1 -> 11.2.0.4] Primary: 11.2.0.1 单机,Site A. Standby: 11.2.0.1 单机,Site ...

随机推荐

  1. SpringMVC框架简介

    1.简介 SpringMVC也叫Spring Web  mvc,属于表现层的框架.Spring MVC是Spring框架的一部分,是在Spring3.0后发布的 01.Spring mvc的优缺点 M ...

  2. tcp协议下粘包问题的产生及解决方案

    1 tcp有粘包及udp无粘包 - TCP 是面向连接的,面向流的可靠协议:发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据, 合并成 ...

  3. Redis设计与实现:读书笔记之二

    1.数据库 Redis服务器一般包含多个db,默认16个. 切换数据库 每个redis客户端都有自己的目标数据库,默认为0,可以通过select 1,切换数据库. 设置键的生存周期和过期时间 PTTL ...

  4. h5新增属性

    localStorage,sessionStorage,video,audio的使用方法 <!DOCTYPE html> <html lang="en"> ...

  5. python生成字符画

    python生成字符画 这个idea来自于实验楼,非常适合练习PIL的像素处理,更重要的是非常有意思. 环境配置 依赖的第三方库就是PIL(Python Image Library),可以直接使用pi ...

  6. Java类集 List, Set, Map, Stack, Properties基本使用

    首先看下继承结构: ArrayList(常用): /** * List接口继承Collection接口 * ArrayList, Vector为List接口的实现类 * add()添加新元素,remo ...

  7. PAT基础6-5

    6-5 求自定类型元素的最大值 (10 分) 本题要求实现一个函数,求N个集合元素S[]中的最大值,其中集合元素的类型为自定义的ElementType. 函数接口定义: ElementType Max ...

  8. css-div翻转动画

    <!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...

  9. How do I remove a particular element from an array in JavaScript?

    9090down voteaccepted Find the index of the array element you want to remove, then remove that index ...

  10. Ubuntu18.04下可以完美运行Quake3 Arena

    安装 其实很早就知道Linux下面可以跑Quake3, 但是一直没有付诸行动, 在硬盘上躺了很多年的Quake III Arena, 和Brood一起从来不舍得删, 昨天终于想起来试试. 安装很简单, ...