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图形学研究的基本内容,即 ...
随机推荐
- TZOJ 5986 玄武密码(AC自动机)
描述 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老人们说,这是玄武神灵将天书藏匿在此. 很多年后,人们终于在 ...
- Leetcode447.Number of Boomerangs回旋镖的数量
给定平面上 n 对不同的点,"回旋镖" 是由点表示的元组 (i, j, k) ,其中 i 和 j 之间的距离和 i 和 k 之间的距离相等(需要考虑元组的顺序). 找到所有回旋镖的 ...
- 跟我一起做一个vue的小项目(十一)
接下来我们进行的是详情页动态路由及banner布局 先看页面的效果 下面是代码部分 <template> <div> <div class="banner&qu ...
- ES6学习笔记之块级作用域
ES6学习笔记:块级作用域 作用域分类 全局作用域 局部作用域 块级作用域 全局作用域示例 var i=2; for (var i = 0; i < 10; i++) { } console.l ...
- 字符串无法分割 split无效: java split()使用“.” “\” "|" "*" "+"要转义
.是特殊字符 特殊字符需要转义. 改成split(“\\.”)
- [待验证]使用hibernate注解忘记引入mapping导致的问题
这个问题好像是注解主键的时候,主键没有设置为int型,我设置了个string(想直接用uuid)导致的 后来学习了一下,这个主键的注解,生成策略有很多种,换成别的,就可以使用string类型 编译报错 ...
- IO流8 --- 使用FileReader和FileWriter实现文本文件的复制 --- 技术搬运工(尚硅谷)
@Test public void test4(){ FileReader fr = null; FileWriter fw = null; try { fr = new FileReader(&qu ...
- IO流3 --- File类的常用方法2 --- 技术搬运工(尚硅谷)
File类的判断功能 @Test public void test5(){ File file = new File("hello.txt"); //判断是否是文件目录 Syste ...
- 下载android4.4.2源代码全过程(附已下载的源代码)
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/maosidiaoxian/article/details/36625727 今天在下载andriod ...
- python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁
ps:python解释器有很多种,最常见的就是C python解释器 GIL全局解释器锁: GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全 用来阻止同一个进程下的多个线程的同时执行 ...