Directx11学习笔记【八】 龙书D3DApp的实现
原文:Directx11学习笔记【八】 龙书D3DApp的实现
directx11龙书中的初始化程序D3DApp跟我们上次写的初始化程序大体一致,只是包含了计时器的内容,而且使用了深度模板缓冲。
D3DUtil类,定义了一些工具和宏,目前只定义了两个宏,以后还会添加
#ifndef D3DUTIL_H
#define D3DUTIL_H #include <d3dx11.h>
#include <xnamath.h>
#include <dxerr.h>
#include <cassert> //-------------------------------
//方便检测d3d errors
//-------------------------------
#if defined(DEBUG) | defined(_DEBUG)
#ifndef HR
#define HR(x) \
{ \
HRESULT hr = (x); \
if (FAILED(hr)) \
{ \
DXTrace(__FILE__, (DWORD)__LINE__, hr, L#x, true); \
} \
}
#endif #else
#ifndef HR
#define HR(x) (x)
#endif
#endif //------------------------------
//方便删除COM objects
//------------------------------
#define ReleaseCOM(x) { if(x){ x->Release(); x = 0; } } #endif//D3DUTIL_H
基类D3DApp的实现
.h文件
#ifndef D3DAPP_H
#define D3DAPP_H #include <windows.h>
#include <string>
#include "D3DUtil.h"
#include "GameTimer.h" class D3DApp
{
public:
D3DApp(HINSTANCE hInstance);
virtual ~D3DApp(); HINSTANCE AppInst() const;
HWND MainWnd() const;
float AspectRatio() const; int Run(); virtual bool Init();
virtual void OnResize();
virtual void UpdateScene(float dt) = ;
virtual void DrawScene();
virtual LRESULT MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); //鼠标事件
virtual void OnMouseDown(WPARAM btnState, int x, int y){}
virtual void OnMouseUp(WPARAM btnState, int x, int y){}
virtual void OnMouseMove(WPARAM btnState, int x, int y){} protected:
bool InitMainWindow();
bool InitDirect3D();
//计算FPS
void CalculateFrameStats(); protected:
HINSTANCE m_hAppInst; //实例句柄
HWND m_hMainWnd; //主窗口句柄
bool m_isAppPaused;
bool m_isMinimized;
bool m_isMaximized;
bool m_isResizing;
UINT m_4xMsaaQuality; //4重采样质量 GameTimer m_timer; //计时器
D3D_DRIVER_TYPE m_d3dDriverType; //驱动类型
ID3D11Device *m_pD3dDevice; //设备
ID3D11DeviceContext *m_pImmediateContext; //设备上下文
IDXGISwapChain *m_pSwapChain; //交换链
ID3D11Texture2D *m_pDepthStencilBuffer; //深度模板缓冲
ID3D11RenderTargetView *m_pRenderTargetView; //渲染目标视图
ID3D11DepthStencilView *m_pDepthStencilView; //深度模板缓冲视图
D3D11_VIEWPORT m_screenViewPort; //视口 std::wstring m_mainWndCaption; //窗口标题
int m_clientWidth;
int m_clientHeight;
bool m_isEnable4xMsaa; //是否支持4重采样
};
#endif //D3DAPP_H
.cpp
#include <windowsx.h>//包含大量可用的宏和各种方便的工具
#include <sstream>
#include "D3DApp.h" namespace
{
D3DApp *g_d3dApp = NULL;
} LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return g_d3dApp->MsgProc(hWnd,msg,wParam,lParam);
} D3DApp::D3DApp(HINSTANCE hInstance) :
m_hAppInst(hInstance),
m_mainWndCaption(L"D3D11 Application"),
m_d3dDriverType(D3D_DRIVER_TYPE_HARDWARE),
m_clientHeight(),
m_clientWidth(),
m_isEnable4xMsaa(false),
m_hMainWnd(NULL),
m_isAppPaused(false),
m_isMaximized(false),
m_isMinimized(false),
m_isResizing(false),
m_4xMsaaQuality(), m_pD3dDevice(NULL),
m_pImmediateContext(NULL),
m_pSwapChain(NULL),
m_pRenderTargetView(NULL),
m_pDepthStencilBuffer(NULL)
{
ZeroMemory(&m_screenViewPort, sizeof(D3D11_VIEWPORT));
g_d3dApp = this;
} D3DApp::~D3DApp()
{
ReleaseCOM(m_pRenderTargetView);
ReleaseCOM(m_pDepthStencilBuffer);
ReleaseCOM(m_pSwapChain);
ReleaseCOM(m_pDepthStencilView); if (m_pImmediateContext)
m_pImmediateContext->ClearState(); ReleaseCOM(m_pImmediateContext);
ReleaseCOM(m_pD3dDevice);
} HINSTANCE D3DApp::AppInst() const
{
return m_hAppInst;
} HWND D3DApp::MainWnd() const
{
return m_hMainWnd;
} float D3DApp::AspectRatio() const
{
return static_cast<float>(m_clientWidth / m_clientHeight);
} int D3DApp::Run()
{
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
m_timer.Reset(); while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, , , PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
m_timer.Tick();
if (!m_isAppPaused)
{
CalculateFrameStats();
UpdateScene(m_timer.DeltaTime());
DrawScene();
}
else
{
Sleep();
}
}
}
return static_cast<int>(msg.wParam);
} bool D3DApp::Init()
{
if (!InitMainWindow())
return false;
if (!InitDirect3D())
return false;
return true;
} void D3DApp::OnResize()
{
assert(m_pImmediateContext);
assert(m_pD3dDevice);
assert(m_pSwapChain); //release old views
ReleaseCOM(m_pRenderTargetView);
ReleaseCOM(m_pDepthStencilView);
ReleaseCOM(m_pDepthStencilBuffer); HR(m_pSwapChain->ResizeBuffers(, m_clientWidth, m_clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, ));
ID3D11Texture2D *backBuffer;
HR(m_pSwapChain->GetBuffer(, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)));
HR(m_pD3dDevice->CreateRenderTargetView(backBuffer, , &m_pRenderTargetView));
ReleaseCOM(backBuffer); //create depth/stencil buffer and view
D3D11_TEXTURE2D_DESC depthStencilDecs;
depthStencilDecs.Width = m_clientWidth;
depthStencilDecs.Height = m_clientHeight;
depthStencilDecs.MipLevels = ;
depthStencilDecs.ArraySize = ;
depthStencilDecs.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; //是否使用4重采样
if (m_isEnable4xMsaa)
{
depthStencilDecs.SampleDesc.Count = ;
depthStencilDecs.SampleDesc.Quality = m_4xMsaaQuality - ;
}
else
{
depthStencilDecs.SampleDesc.Count = ;
depthStencilDecs.SampleDesc.Quality = ;
} depthStencilDecs.Usage = D3D11_USAGE_DEFAULT;
depthStencilDecs.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilDecs.CPUAccessFlags = ;
depthStencilDecs.MiscFlags = ; HR(m_pD3dDevice->CreateTexture2D(&depthStencilDecs, , &m_pDepthStencilBuffer));
HR(m_pD3dDevice->CreateDepthStencilView(m_pDepthStencilBuffer, , &m_pDepthStencilView)); //绑定新的render target view 和 depth/stencil view到管线
m_pImmediateContext->OMSetRenderTargets(, &m_pRenderTargetView, m_pDepthStencilView); //设置viewport
m_screenViewPort.TopLeftX = ;
m_screenViewPort.TopLeftY = ;
m_screenViewPort.Width = m_clientWidth;
m_screenViewPort.Height = m_clientHeight;
m_screenViewPort.MaxDepth = 1.0f;
m_screenViewPort.MinDepth = 0.0f; m_pImmediateContext->RSSetViewports(, &m_screenViewPort);
} LRESULT D3DApp::MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
//当一个窗口被激活或失去激活状态
case WM_ACTIVATE:
if (LOWORD(wParam) == WA_INACTIVE)
{
m_isAppPaused = true;
m_timer.Stop();
}
else
{
m_isAppPaused = false;
m_timer.Start();
}
return ; //当用户重绘窗口时
case WM_SIZE:
m_clientWidth = LOWORD(lParam);
m_clientHeight = HIWORD(lParam);
if (m_pD3dDevice)
{
if (wParam == SIZE_MINIMIZED)//窗口最小化
{
m_isAppPaused = true;
m_isMinimized = true;
m_isMaximized = true;
}
else if (wParam == SIZE_MAXIMIZED)//窗口最大化
{
m_isAppPaused = false;
m_isMinimized = false;
m_isMaximized = true;
OnResize();
}
else if (wParam == SIZE_RESTORED)//窗口大小改变既不是最大化也不是最小化
{
if (m_isMinimized)
{
m_isAppPaused = false;
m_isMinimized = false;
OnResize();
}
else if (m_isMaximized)
{
m_isAppPaused = false;
m_isMaximized = false;
OnResize();
}
//当用户正在改变窗口大小时不调用OnResize(),当改变完成后再
//调用
else if (m_isResizing)
{ }
else
{
OnResize();
}
}
}
return ; //用户开始拖拽改变窗口大小
case WM_ENTERSIZEMOVE:
m_isAppPaused = true;
m_isResizing = true;
m_timer.Stop();
return ; //用户改变窗口大小完毕
case WM_EXITSIZEMOVE:
m_isAppPaused = false;
m_isResizing = false;
m_timer.Start();
OnResize();
return ;
//窗口销毁
case WM_DESTROY:
PostQuitMessage();
return ; //The WM_MENUCHAR message is sent when a menu is active and the user presses
// a key that does not correspond to any mnemonic or accelerator key.
case WM_MENUCHAR:
return MAKELRESULT(, MNC_CLOSE); //防止窗口变得太小
case WM_GETMINMAXINFO:
((MINMAXINFO*)lParam)->ptMinTrackSize.x = ;
((MINMAXINFO*)lParam)->ptMinTrackSize.y = ;
return ; case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
OnMouseDown(wParam, GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam));
return ;
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
OnMouseUp(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return ;
case WM_MOUSEMOVE:
OnMouseMove(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return ;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
} bool D3DApp::InitMainWindow()
{
WNDCLASS wc;
wc.cbClsExtra = ;
wc.cbWndExtra = ;
wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(NULL_BRUSH));
wc.hCursor = LoadCursor(, IDC_ARROW);
wc.hIcon = LoadIcon(, IDI_APPLICATION);
wc.hInstance = m_hAppInst;
wc.lpfnWndProc = MainWndProc;
wc.lpszClassName = L"D3DWndClassName";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClass(&wc))
{
MessageBox(, L"RegisterClass Failed", , );
return false;
} RECT rect{ , , m_clientWidth, m_clientHeight };
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, false);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top; m_hMainWnd = CreateWindow(L"D3DWndClassName", m_mainWndCaption.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
width, height, NULL, NULL, m_hAppInst, );
if (!m_hMainWnd)
{
MessageBox(, L"CreateWindow Failed", , );
return ;
} ShowWindow(m_hMainWnd,SW_SHOW);
UpdateWindow(m_hMainWnd); return true;
} bool D3DApp::InitDirect3D()
{
UINT createDeviceFlags = ;
#if defined(DEBUG) || defined(_DEBUG)
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif D3D_FEATURE_LEVEL featureLevel;
HRESULT hr = D3D11CreateDevice(
,//默认的adapter
m_d3dDriverType,
,
createDeviceFlags,
, ,
D3D11_SDK_VERSION,
&m_pD3dDevice,
&featureLevel,
&m_pImmediateContext
);
if (FAILED(hr))
{
MessageBox(, L"D3D11CreateDevice Failed", , );
return hr;
} if (featureLevel != D3D_FEATURE_LEVEL_11_0)
{
MessageBox(, L"Direct3D Feature Level 11 unsupported!", , );
return false;
} //check 4x msaa quality support
HR(m_pD3dDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, , &m_4xMsaaQuality));
assert(m_4xMsaaQuality > ); //填充交换链描述
DXGI_SWAP_CHAIN_DESC sd;
sd.BufferDesc.Width = m_clientWidth;
sd.BufferDesc.Height = m_clientHeight;
sd.BufferDesc.RefreshRate.Numerator = ;
sd.BufferDesc.RefreshRate.Denominator = ;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
//是否用4重采样
if (m_isEnable4xMsaa)
{
sd.SampleDesc.Count = ;
sd.SampleDesc.Quality = m_4xMsaaQuality - ;
}
else
{
sd.SampleDesc.Count = ;
sd.SampleDesc.Quality = ;
} sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = ;
sd.OutputWindow = m_hMainWnd;
sd.Windowed = true;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = ; //要创建交换链必须得到IDXGIFactory
IDXGIDevice *pDxgiDevice = ;
HR(m_pD3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&pDxgiDevice))); IDXGIAdapter *pDxgiAdapter = ;
HR(pDxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&pDxgiAdapter))); IDXGIFactory *pDxgiFactory = ;
HR(pDxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&pDxgiFactory))); HR(pDxgiFactory->CreateSwapChain(m_pD3dDevice, &sd, &m_pSwapChain)); ReleaseCOM(pDxgiDevice);
ReleaseCOM(pDxgiAdapter);
ReleaseCOM(pDxgiFactory); OnResize(); return true;
} void D3DApp::CalculateFrameStats()
{
//计算fps,每一帧调用
static int frameCnt = ;
static float timeElapsed = 0.0f; frameCnt++; if ((m_timer.TotalTime() - timeElapsed) >= 1.0f)
{
float fps = static_cast<float>(frameCnt);
float mspf = .f / fps; std::wostringstream outs;
outs.precision();//浮点数显示6位
outs << m_mainWndCaption << L" " << L"FPS:" << fps << L" "
<< L"Frame Time:" << mspf << L" (ms) ";
SetWindowText(m_hMainWnd, outs.str().c_str()); frameCnt = ;
timeElapsed += 1.0f;
}
} void D3DApp::DrawScene()
{ }
初始化程序
InitDirect3DApp.h
#ifndef INITDIRECT3DAPP_H
#define INITDIRECT3DAPP_H #include "D3DApp.h" class InitDirect3DApp : public D3DApp
{
public:
InitDirect3DApp(HINSTANCE hInstance);
~InitDirect3DApp(); bool Init();
void OnResize();
void UpdateScene(float dt);
void DrawScene();
}; #endif//INITDIRECT3DAPP_H
InitDirect3DApp.cpp
#include "InitDirect3DApp.h" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif InitDirect3DApp theApp(hInstance); if (!theApp.Init())
return ;
return theApp.Run();
} InitDirect3DApp::InitDirect3DApp(HINSTANCE hInstance) : D3DApp(hInstance)
{
} InitDirect3DApp::~InitDirect3DApp()
{
} bool InitDirect3DApp::Init()
{
if (!D3DApp::Init())
return false;
return true;
} void InitDirect3DApp::OnResize()
{
D3DApp::OnResize();
} void InitDirect3DApp::UpdateScene(float dt)
{ } void InitDirect3DApp::DrawScene()
{
assert(m_pImmediateContext);
assert(m_pSwapChain); float ClearColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };
m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, ClearColor);
m_pImmediateContext->ClearDepthStencilView(m_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, );
HR(m_pSwapChain->Present(, ));
}
Directx11学习笔记【八】 龙书D3DApp的实现的更多相关文章
- Directx11学习笔记【一】 最简单的windows程序HelloWin
声明:本系列教程代码有部分来自dx11龙书及dx11游戏编程入门两本书,后面不再说明 首先,在vs2013中创建一个空的解决方案Dx11Demo,以后的工程都会放在这个解决方案下面.然后创建一个win ...
- Directx11学习笔记【二十二】 用高度图实现地形
本文由zhangbaochong原创,转载请注明出处http://www.cnblogs.com/zhangbaochong/p/5827714.html 在前面我们曾经实现过简单的地形(Direct ...
- Directx11学习笔记【二】 将HelloWin封装成类
我们把上一个教程的代码封装到一个类中来方便以后的使用. 首先新建一个空工程叫做MyHelloWin,添加一个main.cpp文件,然后新建一个类叫做MyWindow,将于窗体有关的操作封装到里面 My ...
- Learning ROS forRobotics Programming Second Edition学习笔记(八)indigo rviz gazebo
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...
- python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑
python3.4学习笔记(八) Python第三方库安装与使用,包管理工具解惑 许多人在安装Python第三方库的时候, 经常会为一个问题困扰:到底应该下载什么格式的文件?当我们点开下载页时, 一般 ...
- Go语言学习笔记八: 数组
Go语言学习笔记八: 数组 数组地球人都知道.所以只说说Go语言的特殊(奇葩)写法. 我一直在想一个人参与了两种语言的设计,但是最后两种语言的语法差异这么大.这是自己否定自己么,为什么不与之前统一一下 ...
- 【opencv学习笔记八】创建TrackBar轨迹条
createTrackbar这个函数我们以后会经常用到,它创建一个可以调整数值的轨迹条,并将轨迹条附加到指定的窗口上,使用起来很方便.首先大家要记住,它往往会和一个回调函数配合起来使用.先看下他的函数 ...
- Directx11学习笔记【二十一】 封装键盘鼠标响应类
原文:Directx11学习笔记[二十一] 封装键盘鼠标响应类 摘要: 本文由zhangbaochong原创,转载请注明出处:http://www.cnblogs.com/zhangbaochong/ ...
- Directx11学习笔记【九】 3D渲染管线
原文:Directx11学习笔记[九] 3D渲染管线 原文地址:http://blog.csdn.net/bonchoix/article/details/8298116 3D图形学研究的基本内容,即 ...
随机推荐
- 每日上亿请求量的电商系统,JVM年轻代垃圾回收参数如何优化? ----实战教会你如何配置
目录: 案例背景引入 特殊的电商大促场景 抗住大促的瞬时压力需要几台机器? 大促高峰期订单系统的内存使用模型估算 内存到底该如何分配? 新生代垃圾回收优化之一:Survivor空间够不够 新生代对象躲 ...
- HDU2056
/* * 指数型母函数 */ #include<cstdio> #define mod 100 typedef long long LL;//杭电需用int64 int powerMo ...
- C++/CLI 创建WinForm程序
本文演示下用CLR创建一个简单的winform程序,IDE:VS2015 可以参考另一篇文章:http://blog.csdn.net/wcc27857285/article/details/7813 ...
- 【arc077f】AtCoder Regular Contest 074 F - Lotus Leaves
题意 给定一个n*m的池塘,每个格子上可能有叶子. 从一个叶子出发,可以跳到相同行或相同列的叶子. 问至少去掉多少叶子,使得起点不能到达终点. \(n,m<=100\) 解法 很显然的最小割模型 ...
- iostat统计信息
用途:报告中央处理器(CPU)统计信息和整个系统.适配器.tty 设备.磁盘和 CD-ROM 的输入/输出统计信息. 语法:iostat [ -c | -d ] [ -k ] [ -t | -m ] ...
- mybatis添加数据返回主键
程序结构图: 表结构: 创表sql: Create Table CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `us ...
- bzoj 3209 花神的数论题——二进制下的数位dp
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3209 可以枚举 “1的个数是...的数有多少个” ,然后就是用组合数算在多少位里选几个1. ...
- 问题解决:listview多次调用addHeaderView和addFooterView
情景: 有两个分类,每个分类下的数据用listview显示,分类1需要显示头视图和尾视图,分类2不要显示头视图和尾视图 .两个分类可以来回切换. 实现的步骤: 1. addHeaderView . a ...
- Sass @at-root (2)
@at-root和&的结合 &在Sass中所起的作用,文章开头就简单的进行演示了.在@at-root中也同样可以配合&一起使用,下面我们同样来看几个用例: SCSS .foo ...
- 利用ajax异步校验验证码(转)
利用ajax异步校验验证码 示例结果如图所示 具体步骤如下: step1: jsp页面及js脚本 <%@page pageEncoding="utf-8" contentTy ...