win32 - Direct3D 11的demo创建
我们可以使用D3D为游戏,科学和桌面应用程序创建3-D图形。
非官方demo实例: https://github.com/Ray1024/D3D11Tutorial
当然,我们第一步要开始认识里面的基本api。
#include <d3d11.h>
#include <chrono> using namespace std::chrono; #pragma comment(lib,"D3D11.lib")
//-----------------------------------------------------------------------------
// 全局变量
//-----------------------------------------------------------------------------
HRESULT hr;
ID3D11Device* g_pd3dDevice = nullptr;
IDXGISwapChain* g_pSwapChain = nullptr;
ID3D11DeviceContext* g_pImmediateContext = nullptr;
ID3D11RenderTargetView* pTarget = nullptr;
std::chrono::steady_clock::time_point last; //-----------------------------------------------------------------------------
// Desc: 初始化Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D(HWND hWnd)
{
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1; // BufferCount: number of buffers 1: 设置一个后缓存,再加上一个自动设置的前缓存,就是双缓存
sd.BufferDesc.Width = 0; //系统自动设置合适的值
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 0; //不处于全屏模式,所以不用管刷新率
sd.BufferDesc.RefreshRate.Denominator = 0;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; //程序自己决定缩放比率
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; //对于大多数显示器,不用设置扫描线顺序
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // Use the surface or resource as an output render target.
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 1; //不需要抗锯齿,一般默认该值
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE; //窗口化 if (FAILED(hr = D3D11CreateDeviceAndSwapChain(
NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
0,
NULL,
0,
D3D11_SDK_VERSION,
&sd,
&g_pSwapChain,
&g_pd3dDevice,
NULL,
&g_pImmediateContext)))
{
return hr;
}
//gain access to texture subresource in swap chain (back buffer)
ID3D11Resource* pBackBuffer = nullptr;
g_pSwapChain->GetBuffer(0, _uuidof(ID3D11Resource), reinterpret_cast<void**>(&pBackBuffer)); // Get the back buffer 0: 后缓存的索引
g_pd3dDevice->CreateRenderTargetView(
pBackBuffer,
nullptr,
&pTarget // pTarget is used to save RenderTarget view
);
pBackBuffer->Release(); } //-----------------------------------------------------------------------------
// Desc: 释放创建对象
//-----------------------------------------------------------------------------
VOID Cleanup()
{
//释放Direct3D设备对象
if (g_pd3dDevice != NULL)
g_pd3dDevice->Release();
//释放Direct3D对象
if (g_pSwapChain != NULL)
g_pSwapChain->Release();
if (g_pImmediateContext != NULL)
g_pImmediateContext->Release();
if (pTarget != NULL)
pTarget->Release();
} //定时器
float Peek()
{
return duration<float>(steady_clock::now() - last).count();
} //-----------------------------------------------------------------------------
// Desc: 渲染图形
//-----------------------------------------------------------------------------
void Render()
{
// Just clear the backbuffer
float r = sin(Peek()) / 2.0f + 0.5f;
float ClearColor[4] = { r, r, 1.0f, 1.0f }; //red,green,blue,alpha
g_pImmediateContext->ClearRenderTargetView(pTarget, ClearColor); // undertake all the drawing work
g_pSwapChain->Present(0u, 0u); //Presents a rendered image to the user.
} //-----------------------------------------------------------------------------
// Desc: 消息处理
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
return 0; case WM_PAINT:
Render();
ValidateRect(hWnd, NULL);
return 0;
} return DefWindowProc(hWnd, msg, wParam, lParam);
} //-----------------------------------------------------------------------------
// Desc: 程序入口
//-----------------------------------------------------------------------------
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
//注册窗口类
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
L"ClassName", NULL };
RegisterClassEx(&wc); //创建窗口
HWND hWnd = CreateWindow(L"ClassName", L"A Direct3D appp",
WS_OVERLAPPEDWINDOW, 200, 100, 600, 500,
NULL, NULL, wc.hInstance, NULL);
last = steady_clock::now(); //running timer
//初始化Direct3D
if (SUCCEEDED(InitD3D(hWnd)))
{
//显示主窗口
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd); //进入消息循环
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
Render(); //渲染图形
}
}
} UnregisterClass(L"ClassName", wc.hInstance);
return 0;
}
先上一个简单的demo供参考,里面有很多的参数介绍。
大概流程:
创建一个交换链(D3D11CreateDeviceAndSwapChain),然后创建一个后缓存(GetBuffer),再创建一个RenderTarget作为后台缓冲区的渲染目标(ID3D11RenderTargetView* pTarget = nullptr)。 使用CreateRenderTargetView创建用于访问资源数据的渲染目标视图,它承担所有绘图工作。
ClearRenderTargetView将渲染目标中的所有元素设置为一个值。
上面都是对象的创建, 我们还需要context,即上下文,用于发送渲染命令并配置渲染管道。D3D11CreateDeviceAndSwapChain已经帮我们创建好了
等这些都创建完毕,则可以调用g_pSwapChain->Present(0u, 0u); 来将渲染的图片发给user --------------------Present命令相当于bitblt,用于将后缓存的视图快速复制给前缓存
另附一张图:
简单说来就是,传统情况下,显示器从单个缓冲区扫描像素的时候,它遵循自左上角到右下角的点扫描,就是一个像素一个像素的扫描,那么如果我们在单个缓冲区里绘制东西的时候,还没绘制好就被显示器扫描走了,那就会显示不完整的图形。
所以D3D需要后缓存来避免这样的问题。当后缓存的东西绘制完毕,使用present或者filp来将后缓存快速复制给前缓存,那么显示器在扫描的时候,每次扫描完前缓存的东西时(扫描也需要时间的),后缓存已经准备好了。
言归正传,在代码中我们有了后缓存pBackBuffer,但是我们得需要一个渲染视图在后缓存中绘制我们需要的东西,那么我们就需要创建一个渲染对象pTarget,然后使用CreateRenderTargetView来使pTarget保存渲染的视图(渲染视图相当于后缓冲区)。 好了,有了渲染视图,就可以使用ClearRenderTargetView将RGBA的数值渲染到视图中,这样我们就可以使用Present来显示图像了。
为什么需要渲染呢?
从逻辑上将, 我们会说:“后缓存...!" 并完成。 但是,Direct3D在这一点上并不知道。
在Direct3D中渲染时,必须建立渲染目标。 这是一个简单的com对象,它在视频内存中维护一个位置,供我们渲染。 在大多数情况下, 这是后台缓冲区。
拓展:
纹理资源是旨在存储纹理像素的数据的结构化集合。纹素表示管道可以读取或写入的纹理的最小单位。与缓冲区不同,纹理可以被着色器单元读取,从而可以通过纹理采样器进行过滤。
渲染管线是指:在给定一个3D场景的几何描述及一架已确定位置和方向的虚拟摄像机(virtual camera)时,根据虚拟摄像机的视角生成2D图像的一系列步骤。
win32 - Direct3D 11的demo创建的更多相关文章
- 【译】Import Changes from Direct3D 11 to Direct3D 12
译者:林公子 出处:木木的二进制人生 转载请注明作者和出处,谢谢! 这是微软公布的Direct3D 12文档的其中一篇,此翻译留作学习记录备忘,水平有限,错漏难免,还望海涵. 原文链接是https:/ ...
- win32 htmlayout点击按钮创建新窗口,以及按钮图片样式
最近在做一个C++ win32的桌面图形程序,我不是C++程序员,做这个只是因为最近没什么java的活. windows api,之前接触的时候,还是大学,那时用这个开发打飞机游戏纯粹是娱乐.现在基本 ...
- Direct3D 11 Tutorial 7:Texture Mapping and Constant Buffers_Direct3D 11 教程7:纹理映射和常量缓冲区
概述 在上一个教程中,我们为项目引入了照明. 现在我们将通过向我们的立方体添加纹理来构建它. 此外,我们将介绍常量缓冲区的概念,并解释如何使用缓冲区通过最小化带宽使用来加速处理. 本教程的目的是修改中 ...
- Direct3D 11 Tutorial 5: 3D Transformation_Direct3D 11 教程5:3D转型
概述 在上一个教程中,我们从模型空间到屏幕渲染了一个立方体. 在本教程中,我们将扩展转换的概念并演示可以通过这些转换实现的简单动画. 本教程的结果将是围绕另一个轨道运行的对象. 展示转换以及如何将它们 ...
- Direct3D 11 Tutorial 4: 3D Spaces_Direct3D 11 教程4:3D空间
概述 在上一个教程中,我们在应用程序窗口的中心成功渲染了一个三角形. 我们没有太注意我们在顶点缓冲区中拾取的顶点位置. 在本教程中,我们将深入研究3D位置和转换的细节. 本教程的结果将是渲染到屏幕的3 ...
- Direct3D 11 Tutorial 3: Shaders and Effect System_Direct3D 11 教程3:着色器和效果系统
概述 在上一个教程中,我们设置了一个顶点缓冲区并将一个三角形传递给GPU. 现在,我们将逐步完成图形管道并查看每个阶段的工作原理. 将解释着色器和效果系统的概念. 请注意,本教程与前一个源代码共享相同 ...
- Direct3D 11 Tutorial 2: Rendering a Triangle_Direct3D 11 教程2:渲染一个三角形
概要 在之前的教程中,我们建立了一个最小的Direct3D 11的应用程序,它用来在窗口上输出一个单一颜色.在本次教程中,我们将扩展这个应用程序,在屏幕上渲染出一个单一颜色的三角形.我们将通过设置数据 ...
- Direct3D 11 Tutorial 1: Basics_Direct3D 11 教程1:基础
Github-LearnDirectX-DX3D11 tutorial01 概述 在这第一篇教程中,我们将通过介绍创建最小Direct3D应用程序所必需的元素.每一个Direct3D应用程序必需拥有这 ...
- [转]Direct3D 11 Tessellation Tutorial
The new hardware tessellation feature available on Direct3D 11 video cards has great potential, but ...
- 选择 Delphi 2007 ( CodeGear Delphi 2007 for Win32 Version 11.0.2837.9583 ) 的理由
选择 Delphi 2007 ( CodeGear Delphi 2007 for Win32 Version 11.0.2837.9583 ) 的理由 我不喜欢用InstallRite的全自动安装包 ...
随机推荐
- Nginx loki监控日志的学习
Nginx loki监控日志的学习 背景 学习自: https://mp.weixin.qq.com/s/Qt1r7vzWvCcJpNDilWHuxQ 增加了一些自己的理解 第一部分nginx日志的完 ...
- [转帖]TiDB 配置参数修改与系统变量修改步骤
https://tidb.net/blog/bda86911 注意事项1:tidb-test 为集群名称 注意事项2:参数修改前与修改后备份.tiup目录 注意事项3:通过 tiup cl ...
- [转帖]Jmeter连接InfluxDB2.0.4
Jmeter连接InfluxDB2.0.4 问题描述:在用Jmeter+InfluxDB构建监控时,因为docker构建的InfluxDB的版本是2.0.4,按照网上的教程进行后端监听器的填写,但是一 ...
- [转帖]Jmeter 参数化
一.Jmeter参数化概念 当使用JMeter进行测试时,测试数据的准备是一项重要的工作.若要求每次迭代的数据不一样时,则需进行参数化,然后从参数化的文件中来读取测试数据. 参数化是自动化测试脚本的一 ...
- [转帖]iometer - 性能压力测试工具
<存储工具系列文章>主要介绍存储相关的测试和调试工具,包括不限于dd.fio.vdbench.iozone.iometer.cosbench等性能负载工具,及strace等调试工具. 1 ...
- 【转帖】JVM的发展历程
目录 1.Sun Classic VM 2.Exact VM 3.Sun HotSpot(主流) 4.JRockit 5.IBM J9 6.下一代虚拟机Graal VM 1.Sun Classic V ...
- CentOS创建vsftp进行读写操作的简单方法
1. 安装vsftpd yum install epel-release yum install vsftpd 2. 进入系统设置简单进行处理 注意 user_list 是不允许访问的列表. [roo ...
- K8S的pod展示镜像信息
https://kubernetes.io/zh/docs/tasks/access-application-cluster/list-all-running-container-images/ ku ...
- LINQ分组排序后获取每组第一条记录
当前有一张数据表{Student},包含了如下的字段信息: CREATE TABLE [dbo].[Student]( [Sno] [nchar](7) NOT NULL, [Sname] [ncha ...
- 【SpringBoot】AOP默认的动态代理
分析: 当引入AOP相关依赖后 <dependency> <groupId>org.springframework</groupId> <artifactId ...