使用Dx11渲染纹理1——初始化

新建Windows窗口工程

使用VS2019工程创建一个默认的窗口工程。


创建一个win32应用

创建交换链和设备及上下文

添加头文件和依赖库如下:

#include <d3d11.h>
#pragma comment(lib, "d3d11.lib")

我们要做的第一件事是填写交换链的描述。交换链是图形将被绘制到的前后缓冲区。通常,您使用单个后台缓冲区,对其进行所有绘图,然后将其交换到前台缓冲区,然后将其显示在用户屏幕上。这就是为什么它被称为交换链。
交换链描述DXGI_SWAP_CHAIN_DESC

D3D11CreateDeviceAndSwapChain创建

HRESULT D3D11CreateDeviceAndSwapChain(
  [in, optional]  IDXGIAdapter               *pAdapter,
                  D3D_DRIVER_TYPE            DriverType,
                  HMODULE                    Software,
                  UINT                       Flags,
  [in, optional]  const D3D_FEATURE_LEVEL    *pFeatureLevels,
                  UINT                       FeatureLevels,
                  UINT                       SDKVersion,
  [in, optional]  const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc,
  [out, optional] IDXGISwapChain             **ppSwapChain,
  [out, optional] ID3D11Device               **ppDevice,
  [out, optional] D3D_FEATURE_LEVEL          *pFeatureLevel,
  [out, optional] ID3D11DeviceContext        **ppImmediateContext
);

pAdapter: 指向用来创建设备的显示适配器的指针。NULL表示使用默认的适配器
DriverType: 指定驱动类型,常用的有D3D_DRIVER_TYPE_HARDWARE,使用硬件驱动
Software: 实现软件光栅器的DLL的句柄。如果DriverTypeD3D_DRIVER_TYPE_SOFTWARE,Software不能为NULL
Flags: 运行时层标记
pFeatureLevels:指向D3D特性等级数组的指针,如果为NULL,则使用默认的特性等级数组,默认数组如下:

{
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0,
    D3D_FEATURE_LEVEL_9_3,
    D3D_FEATURE_LEVEL_9_2,
    D3D_FEATURE_LEVEL_9_1,
}

FeatureLevel: pFeatureLevels中的元素个数。
SDKVersion: SDK版本,使用D3D11_SDK_VERSION
pSwapChainDesc: 指向交换链描述的指针DXGI_SWAP_CHAIN_DESC

交换链描述

typedef struct DXGI_SWAP_CHAIN_DESC {
    DXGI_MODE_DESC   BufferDesc;
    DXGI_SAMPLE_DESC SampleDesc;
    DXGI_USAGE       BufferUsage;
    UINT             BufferCount;
    HWND             OutputWindow;
    BOOL             Windowed;
    DXGI_SWAP_EFFECT SwapEffect;
    UINT             Flags;
} DXGI_SWAP_CHAIN_DESC;

BufferDesc: 描述后缓冲的显示模式
SampleDesc: 描述多重采样参数
BufferUsage: 描述表面的用法和CPU访问后缓冲的操作。后缓冲用于着色器输入或渲染对象输出
BufferCount: 缓冲区个数,包括前缓冲
OutputWindow: 输出窗口句柄,不能为NULL
Windowed: true表示窗口模式,false表示全屏模式
SwapEffect: 枚举类型。描述了提交表面后处理缓冲区内容的可选方法
Flags: 枚举类型。描述交换链的行为

显示模式描述

typedef struct DXGI_MODE_DESC {
    UINT                     Width;
    UINT                     Height;
    DXGI_RATIONAL            RefreshRate;
    DXGI_FORMAT              Format;
    DXGI_MODE_SCANLINE_ORDER ScanlineOrdering;
    DXGI_MODE_SCALING        Scaling;
} DXGI_MODE_DESC, *LPDXGI_MODE_DESC;

Width: 分辨率宽
Height: 分辨率高
RefreshRate: 结构类型。描述刷新频率
Format: 结构类型。描述显示模式
ScanlineOrdering: 枚举类型。描述扫描线绘制模式
Scaling: 枚举类型。描述缩放模式

示例代码

创建交换链及设备的代码如下:

DXGI_SWAP_CHAIN_DESC swapChainDesc; 
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));

// 设置为单个后台缓冲区。
swapChainDesc.BufferCount = 1;

// 设置后台缓冲区的宽度和高度。
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;

// 为后台缓冲区设置常规的32位表面。
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

// 设置刷新率,设置让系统尽快刷新
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;

// 设置后台缓冲区的使用目的
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

// 设置要渲染到的窗口句柄
swapChainDesc.OutputWindow = hwnd;

// 关闭多重采样。
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;

// 设置为窗口模式
swapChainDesc.Windowed = true;

// 将扫描线排序和缩放设置为未指定。
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

// 呈现后丢弃后台缓冲区内容。
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

// 不要设置高级标志。
swapChainDesc.Flags = 0;

// 特征级别设置为 11.0,即 DirectX 11
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;

// 创建交换链、设备及上下文
D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, &featureLevel, 1,
    D3D11_SDK_VERSION, &swapChainDesc, &m_swapChain, &m_device, NULL, &m_deviceContext);

创建渲染目标

使用交换链后台缓存创建渲染目标。

ID3D11Texture2D* backBufferPtr;
HRESULT hr = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);

hr = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView);
backBufferPtr->Release();

渲染

在消息循环中渲染,其中消息循环中取系统消息队列中的消息需要改用PeekMessage,如果没有消息时进行渲染操作。
在每次渲染前可以使用CreateRenderTargetView,将渲染目标使用指定的颜色清除其后台缓冲。

PeekMessage、GetMessage区别

  1. GetMessage的主要功能是从消息队列中“取出”消息,消息被取出以后,就从消息队列中将其删除;而PeekMessage的主要功能是“窥视”消息,如果有消息,就返回true,否则返回false。也可以使用PeekMessage从消息队列中取出消息,这要用到它的一个参数(UINT wRemoveMsg),如果设置为PM_REMOVE,消息则被取出并从消息队列中删除;如果设置为PM_NOREMOVE,消息就不会从消息队列中取出。
  2. 如果GetMessage从消息队列中取不到消息,则线程就会被操作系统挂起,等到OS重新调度该线程,GetMessage每次都会等待消息,直到取到消息才返回;而PeekMessage只是查询消息队列,没有消息就立即返回,从返回值判断是否取到了消息。

效果

image.png

完整代码见:使用git log可以查看初始化过程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容