介绍
创建窗口成功之后,就要使用 direct3D 进行绘图,本节主要介绍,如何初始化 direct3D,并通过 direct3D改变窗口颜色。
初始化 direct3D
函数解释
D3D11CreateDevice
通过 D3D11CreateDevice 函数创建设备和上下文,device 主要用于显示是否支持某些特性和分配资源,context 主要用于设置渲染状态、将资源绑定到 pipeline 和 发出渲染命令。需要设置的参数有 使用的电脑上的哪个显卡(现在很多电脑上多有两块显卡,独立显卡和集成显卡),驱动的类型(可能你电脑上没有显卡,也想使用 direct3D,可以使用软件进行模拟,只是速度会慢一点),显卡支持的功能(由于显卡和 directX 功能一直在升级,所以有些老的显卡不支持一些新的功能)。
CreateSwapChain
通过 CreateSwapChain,设置窗口的交换缓存。主要的参数是 缓存的宽、高、格式、缓存的用处(用于渲染目标输出)和渲染目标窗口句柄(指定渲染后的图像显示在哪个窗口)
CreateRenderTargetView
由于创建的资源缓存就行申请的一块 void* 内存,代码不知道如何使用该资源,需要获取该资源的视图,才便于使用。
具体代码
void Graphics::Initialize(HWND hWnd)
{
UINT flags = 0;
#ifndef NDEBUG
flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
// 1. 创建设备和上下文
// device 主要用于显示是否支持某些特性和分配资源
// context 主要用于设置渲染状态、将资源绑定到 pipeline 和 发出渲染命令
HRESULT hr = D3D11CreateDevice(
NULL, // 选择显卡, NULL 为默认显卡
D3D_DRIVER_TYPE_HARDWARE, // 驱动类型
NULL, // 驱动类型选择 软件时,需要设置
flags, // flag
nullptr, // 支持哪些功能
0, // feature 个数
D3D11_SDK_VERSION, // SDK 版本号
&m_pDevice, // 获取创建的设备
NULL, // 获取支持的功能
&m_pContext); // 上下文
// 2. 设置 DXGI_SWAP_CHAIN_DESC 实例属性
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
// 缓存设置
sd.BufferDesc.Width = 0; // 缓存宽度,设为0,则 CreateSwapChain 时将该值设为输出窗口的宽度
sd.BufferDesc.Height = 0; // 缓存高度
sd.BufferDesc.RefreshRate.Numerator = 0;
sd.BufferDesc.RefreshRate.Denominator = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // 输出存储格式
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; // 扫描路线
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; // 缩放
// 采样设置
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // 缓存的用处
sd.BufferCount = 1; // 缓存个数
sd.OutputWindow = hWnd; // 渲染目标窗口句柄
sd.Windowed = TRUE; // 窗口显示
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;
// 3. 使用 IDXGIFactory 创建 IDXGISwapChain 实例
IDXGIDevice* dxgiDevice = nullptr;
IDXGIAdapter* dxgiAdapter = nullptr;
IDXGIFactory* dxgiFactory = nullptr;
hr = m_pDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter);
hr = dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory);
if(m_pDevice!= nullptr)
dxgiFactory->CreateSwapChain(m_pDevice, &sd, &m_pSwapChain);
dxgiDevice->Release();
dxgiAdapter->Release();
dxgiFactory->Release();
// 4. 创建渲染目标视图
ID3D11Texture2D* backBuffer = nullptr;
m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer));
m_pDevice->CreateRenderTargetView(backBuffer, 0, &m_pRenderTargetView);
backBuffer->Release();
}
改变窗口颜色
函数解释
ClearRenderTargetView
设置渲染目标视图的背景颜色,正真使用的时候,就是把上一次画的画面擦除掉。
Present
负责将后备缓冲的内容显示在屏幕上
具体代码
void Graphics::ClearBuffer(float red, float green, float blue)
{
const FLOAT color[4] = { red, green, blue, 1.0f };
// 使用指定颜色清空渲染目标视图
m_pContext->ClearRenderTargetView(m_pRenderTargetView, color);
}
void Graphics::EndDraw()
{
m_pSwapChain->Present(1, 0);
}
参考文献
https://enjoyphysics.cn/Article923