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


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

    初始化Driect3D类:

    #include "Commond3dApp.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
  • 相关阅读:
    第一次冲刺团队绩效评估
    各组意见汇总及我组改进方案
    对其他小组的评价和建议
    检查第一组博客状况
    第一次冲刺-站立会议10
    第一次冲刺-站立会议09
    第一次冲刺-站立会议08
    敏捷软件需求:团队、项目群与企业级的精益需求实践 阅读笔记二
    敏捷软件需求:团队、项目群与企业级的精益需求实践 阅读笔记一
    问题账户需求分析
  • 原文地址:https://www.cnblogs.com/yaya12138/p/11562194.html
Copyright © 2020-2023  润新知