初始化Direct3D演示(第四章内容)

初始化Driect3D类:

#include "Common\d3dApp.h"
#include <DirectXColors.h> using namespace DirectX; class InitDirect3DApp : public D3DApp
{
public:
InitDirect3DApp(HINSTANCE hInstance);
~InitDirect3DApp(); virtual bool Initialize()override; private:
virtual void OnResize()override;
virtual void Update(const GameTimer& gt)override;
virtual void Draw(const GameTimer& gt)override;
}; InitDirect3DApp::InitDirect3DApp(HINSTANCE hInscance) :D3DApp(hInscance)
{ } InitDirect3DApp::~InitDirect3DApp()
{ } bool InitDirect3DApp::Initialize()
{
if (!D3DApp::Initialize())
{
return false;
}
return true;
} void InitDirect3DApp::OnResize()
{
D3DApp::OnResize();
} void InitDirect3DApp::Update(const GameTimer& gt)
{ } void InitDirect3DApp::Draw(const GameTimer& gt)
{
//重置命令分配器
ThrowIfFailed(mDirectCmdListAlloc->Reset());
//重置命令列表
ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
//对资源的状态进行转变,将资源从呈现状态转变到渲染目标状态
mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(
CurrentBackBuffer(),
D3D12_RESOURCE_STATE_PRESENT,
D3D12_RESOURCE_STATE_RENDER_TARGET
));
//设置视口和裁剪矩形,他们需要跟随命令列表的重置而重置
mCommandList->RSSetViewports(1, &mScreenViewport);
mCommandList->RSSetScissorRects(1, &mScissorRect);
//清除后台缓冲区和深度缓冲区
mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL,
1.0f, 0, 0, nullptr);
//指定将要渲染的缓冲区
mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
//再次对资源状态进行转变,将资源从渲染目标状态转变为呈现状态
mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(
CurrentBackBuffer(), D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PRESENT
));
//完成命令的记录
ThrowIfFailed(mCommandList->Close());
//将命令列表的命令加入到命令队列中
ID3D12CommandList* cmdsList[] = { mCommandList.Get() };
mCommandQueue->ExecuteCommandLists(_countof(cmdsList), cmdsList);
//交换前后台缓冲区
ThrowIfFailed(mSwapChain->Present(0, 0));;
mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount; //等待此帧的命令执行完毕
FlushCommandQueue(); }

主函数:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
{
//为调试版本开启运行时内存检测,方便监督内存泄漏的情况
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif try
{
InitDirect3DApp theApp(hInstance);
if (!theApp.Initialize())
{
return 0;
}
return theApp.Run();
}
catch (DxException& e)
{
MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
return 0;
}
}

运行结果

接下来我们将介绍一些在前面没有提到的方法:

1、ClearRenderTargetView():将指定的渲染目标清理为给定的颜色

2、ClearDepthStencilView():清理指定的深度/模板缓冲区

3、OMSetRenderTargets():设置我们希望在渲染流水线上使用的渲染目标和深度/模板缓冲区

调试Direct3D应用程序

大多数的Direct3D函数会返回HRESULT错误码,我们的示例程序则采用简单的错误处理机制检测返回的HRESULT值,如果检测失败。则抛出异常,显示调用出错的错误码,函数名,文件名以及发生错误的行号,这些操作都由d3dUtil.h中的代码实现:

class DxException
{
public:
DxException() = default;
DxException(HRESULT hr, const std::wstring& functionName, const std::wstring& filName, int lineNumber); std::wstring ToString()const; HRESULT ErrorCode = S_OK;
std::wstring FunctionName;
std::wstring FileName;
int LineNumber = -1;
}; #ifndef ThrowIfFailed
#define ThrowIfFailed(x) \
{ \
HRESULT hr__ = (x); \
std::wstring wfn = AnsiToWString(__FILE__); \
if(FAILED(hr__)) { throw DxException(hr__, L#x, wfn, __LINE__); } \
}
#endif

由上面的代码可以看出来,ThrowifFailed是一个宏而不是一个函数,如果ThrowifFailed是一个函数,那么__FILE__和__LINE__将会定位到ThrowifFailed函数所在的文件和行,而不是出错函数的文件和行。

L#x会将ThrowifFailed的参数转换为Unicode字符串,这样一来,我们就可以将函数调用的错误信息输出到消息框中。

第四章小结

  1. Direct3D是一种介于程序员和硬件之间的桥梁,通过这个桥梁,程序员可以通过调用Direct3D函数来实现把资源视图绑定到硬件渲染流水线中,配置渲染流水线的输出以及绘制3D几何体等操作
  2. 组件对象模型(COM)是一种可以使DirectX不依赖任何特定语言且向后兼容的技术
  3. 1D、2D、3D纹理类似于有数据元素构成的1D、2D、3D数组,纹理元素的格式必定是DXGI_FORAMT枚举类型中的其中一种,纹理除了可以存储图像数据之外,还可以存储想深度信息等其他类型的数据
  4. 前台缓冲区和后台缓冲区构成了交换链,交换链在代码中可以通过IDXGISwapChain接口表示,使用两个缓冲区的情况称之为双缓冲,交换链的存在可以避免出现动画中出现闪烁的问题(前台缓冲区和后台缓冲区互换的操作称之为呈现)
  5. 深度缓冲是一种用于确定物体在场景中离摄像机最近点的技术,通过深度缓冲,我们可以不用考虑物体在场景中绘制的先后顺序
  6. 在Driect3D中,资源不可以直接和渲染流水线相互绑定,因此我们需要为绘制调用时所引用的资源指定描述符,描述符可以视为GPU识别以及描述资源的一种轻量级结构体,我们还可以为一种资源创建不同的描述符,这样我们就可以让一种资源具有多种用途。应用程序可以通过创建描述符堆来存储描述符。
  7. ID3DDeviec是Direct3D最重要的接口,我们可以把它看作是图形硬件设备的软件控制器,我们可以通过ID3DDevice来创建GPU资源以及其他一些用于控制图形硬件设备的特定接口
  8. 每一个GPU都有一个命令队列,CPU可以通过Direct3D API用命令列表来向该队列提交命令,这些命令将指挥GPU进行各种操作,在命令没有到达队列首部之前,该命令是不会被执行的。
  9. GPU是系统中和CPU一起并行工作的第二种处理器,我们需要对CPU和GPU进行同步
  10. 性能计数器是一种高精度的计时器,它是测量微小时间差的一种有效工具,性能计数器使用的时间单位是计数,QueryPerformanceFrequency函数输出的是性能计数器每秒的计数,可以用它将计数单位转换为秒,QueryPerformanceCounter函数输出的是当前的时间值(以计数为单位)
  11. 通过统计时间段t内处理的帧数可以计算出每秒的平均帧数(FPS),不过为了更直观的对程序的性能进行考量,我们一般使用“处理一帧所花费的时间”这个统计信息。以秒为单位的每帧平均处理时间可以用帧率的倒数来进行计算,即:1/FPS

Driect3D初始化演示的更多相关文章

  1. Java三大器之监听器(Listener)的工作原理和代码演示

    现在来说说Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次, ...

  2. STL学习之路

    本文面向的读者:学习过C++程序设计语言(也就是说学习过Template),但是还没有接触过STL的STL的初学者.这实际上是我学习STL的一篇笔记,老鸟就不用看了. 什么是泛型程序设计 我们可以简单 ...

  3. Vector示例一,二

    #include <iostream> int main(void) { double a[] = {1, 2, 3, 4, 5}; std::cout<<mean(a, 5) ...

  4. Servlet,过滤器,监听器,拦截器的区别

    1.过滤器 Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码.做一些业务逻辑判断等.其工作原理是,只要你在web.xml ...

  5. 027 hibernate查询语言(HQL)

    概述:数据查询与检索是Hibernate中的一个亮点,相对其他ORM实现而言,Hibernate提供了灵活多样的查询机制. 标准化对象查询(Criteria Query):以对象的方式进行查询,将查询 ...

  6. java监听器(Listener)学习笔记

    现在来说说Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次, ...

  7. STL学习笔记(转,还是比较全的)

    STL简介 1 概况 2 1.1 STL是什么 2 1.2 为什么我们需要学习STL 2 1.3 初识STL 2 1.4 STL 的组成 5 2 容器 6 2.1 基本容器——向量(vector) 6 ...

  8. web.xml中Listener的作用

    Servlet的监听器Listener,它是实现了javax.servlet.ServletContextListener 接口的服务器端程序,它也是随web应用的启动而启动,只初始化一次,随web应 ...

  9. x86保护模式-六 控制转移

    控制转移可以分为两大类  :同一任务内的控制转移    和   任务间的控制转移(任务切换) 同一个任务内的控制转移可以分为段内转移 .特权级不变的段间转移和特权级改变的段间转移 段内转移与实模式相同 ...

随机推荐

  1. 史上最全面的SignalR系列教程-5、SignalR 实现一对一聊天

    1.概述 通过前面几篇文章 史上最全面的SignalR系列教程-1.认识SignalR 史上最全面的SignalR系列教程-2.SignalR 实现推送功能-永久连接类实现方式 史上最全面的Signa ...

  2. 枚举类&&注解&&反射

    什么是枚举类? 枚举类是优化定义固定对象的一种特殊的类. 换句话说,在需要类的实例为一个或者多个并且相对固定的时候,使用枚举类.(枚举类可扩展) 类的实例相对来说固定的有日期,客观不变的一些数字等等. ...

  3. windows的磁盘操作之七——获取当前所有的物理磁盘号 加备注

     windows的磁盘操作之七--获取当前所有的物理磁盘号 2011-07-28 17:47:56 标签:windows API DeviceIoControl 物理磁盘 驱动器号 原创作品,允许转载 ...

  4. 【在 Nervos CKB 上做开发】Nervos CKB 脚本编程简介[1]:验证模型

    CKB 脚本编程简介[1]: 验证模型 本文作者:Xuejie 原文链接:Introduction to CKB Script Programming 1: Validation Model 本文译者 ...

  5. unity编辑器扩展_03(在组件中右击创建一个选项,并通过该选项修改该组件下面的字段的值)

    在组件中右击创建一个选项代码: [MenuItem("CONTEXT/PlayerHealth/InitHealth")]    static void Test5()    {  ...

  6. JNI开发流程

    交叉编译 在一个平台上去编译另一个平台上可以执行的本地代码 cpu平台 arm x86 mips 操作系统平台 windows linux mac os 原理 模拟不同平台的特性去编译代码 jni开发 ...

  7. 业务代码的救星——Java 对象转换框架 MapStruct 妙用

    简介 在业务项目的开发中,我们经常需要将 Java 对象进行转换,比如从将外部微服务得到的对象转换为本域的业务对象 domain object,将 domain object 转为数据持久层的 dat ...

  8. npm基本命令

    1.npm是什么? npm(Node Package Manager)意思是 node 的包管理器,它是随着 NodeJs 安装时一起被安装的: 无论是在前端还是在前端开发中都会使用到 npm 包管理 ...

  9. P2564 [SCOI2009]生日礼物 贪心

    https://www.luogu.org/problemnew/show/P2564) 题意 有n个珠子,包括k中颜色,找出长度最小的一个区间,使得这个区间中包含所有的颜色. 思路 把n个珠子按照位 ...

  10. 关于dijkstra的优化 及 多源最短路

    先来看这样一道题目 给你N个点,M条双向边,要求求出1号点到其他所有点的距离.其中 2 <= N <= 1e5,  1 <=M <= 1e6. 对于这样的一道题目 我们当然不可 ...