矩阵
对于XMMATRIX的初始化,可以有多种方法,一种方法是传4个XMVECTOR参数,每个XMVECTOR对应矩阵的一行;第二种方法是直接传递16个浮点数,代表整个矩阵的内容;第三种方法是用一个FLOAT型的数组,代表整个矩阵的内容。当然,这三种方法都有点麻烦,不过在实际中,自己来手动初始化矩阵的地方也不多,了解下其初始化方法即可。其次,XMMATRIX重载了()操作符,用来访问矩阵中的成员,用法跟正常矩阵访问完全一样,即传递两个参数(row, col)即可。 XMMATRIX也重载了*和*=操作符,用途很明显,用来进行矩阵的乘积。
在函数定义中,类型为XMMATRIX的形参必须用CXMMATRIX类型代替。
1、 矩阵相关函数
- XMMATRIX XMMatrixIdentity(); //返回单位矩阵,即对角线全1,其他全0
- BOOL XMMatrixIsIdentity(CXMMATRIX M); //判断一个矩阵是否为单位矩阵
- XMMATRIX XMMatrixMultiply(CXMMATRIX A, CXMMATRIX B); //两矩阵相乘
- XMMATRIX XMMatrixTranspose(CXMMATRIX M); //矩阵转置
- XMVECTOR XMMatrixDeterminant(CXMMATRIX M); //求矩阵对应行列式的值det
- XMMATRIX XMMatrixInverse(XMVECTOR *pDet, CXMMATRIX M); //求矩阵M的逆,*pDet为该矩阵的det
2、 3D中矩阵变换相关函数
- XMMATRIX XMMatrixScaling(FLOAT scaleX, FLOAT scaleY, FLOAT scaleZ); //伸缩变化,指定三个方向上的伸缩比
- XMMATRIX XMMatrixScalingFromVector(FXMVECTOR scale); //通过向量指定三个方向伸缩比,求伸缩变换
- XMMATRIX XMMatrixRotationX(FLOAT angle); //围绕x轴的旋转变换
- XMMATRIX XMMatrixRotationY(FLOAT angle); //围绕y轴的旋转变换
- XMMATRIX XMMatrixRotationZ(FLOAT angle); //围绕z轴的旋转变换
- XMMATRIX XMMatrixRotationAxis(FXMVECTOR axis, FLOAT angle); //围绕任意轴axis的旋转变换
- XMMATRIX XMMatrixTranslation(FLOAT x, FLOAT y, FLOAT z); //*移变换,指定三个方向的*移量
- XMMATRIX XMMatrixTranslationFromVector(FXMVECTOR offset); //通过向量指定三个方向的*移量,求*移变换
- XMVECTOR XMVector3Transform(FXMVECTOR v, CXMMATRIX m); //向量、矩阵相乘
- XMVECTOR XMVector3TransformCoord(FXMVECTOR v, CXMMATRIX m); //向量、矩阵相乘,但向量w=1,因此为点的变换
- XMVECTOR XMVector3TransformNormal(FXMVECTOR v, CXMMATRIX m); //向量、矩阵相乘,但向量w=0,因此为向量的变换
数据格式
D3D应用程序中,无论是纹理图片,还是创建的缓冲区,都有着特定的数据格式。D3D11支持有限的数据格式,以枚举变量形式存在,如下几种:
DXGI_FORMAT_R32G32B32_FLOAT: 3个32位单精度符点数组成,比如用于代表三维空间坐标,以及24位颜色;
DXGI_FORMAT_R16G16B16A16_UNORM: 4个16位数组成,每个成员位于[0,1.0f]之间,UNORM意指:unsigned normalized,即无符号,且归一化的;
DXGI_FORMAT_R32G32_UINT:2个32位数组成,每个成员为无符号整型(unsigned int);
DXGI_FORMAT_R8G8B8A8_UNORM:4个8位数组成,每个成员为[0,1.f]之间;
DXGI_FORMAT_R8G8B8A8_SNORM:4个8位数组成,每个成员为[-1.0f, 1.0f]之间,SNORM意指:signed normalized;
DXGI_FORMAT_R8G8B8A8_SINT:4个8位数组成,每个成员为有符号整型;
此外还有很多其他类型的数据格式,熟悉各部分的意义后对任何类型可以很快从名字中得知其意思,也很容易写出指定意义的数据格式对应的枚举变量。数据格式在程序中使用相当频繁,因此很有必要提前熟悉该枚举类型变量的特点。
多重采样抗锯齿 Multisampling Atialiasing
- typedef struct DXGI_SAMPLE_DESC {
- UINT Count;
- UINT Quality;
- } DXGI_SAMPLE_DESC, *LPDXGI_SAMPLE_DESC;
Count为我们设置的采样的个数,Quality为机器支持的不同的等级,初始化过程中我们会对Quality进行检测。
注意Multisampling区别于super sampling的关键点:不同采样点是分别计算颜色值(super sampling)还是共享同一颜色值(Multisampling)。详细情况有很多参考书介绍。
Direct3D 初始化
Direct3D 初始化
初始化Direct3D,我们需要完成以下四个步骤:
1.定义我们需要检查的设备类型(device types)和特征级别(feature levels)
2.创建Direct3D设备,渲染设备(context)和交换链(swap chain)。
3.创建渲染目标(render target)。
4.设置视口(viewport)
交换链是设备和上下文将要绘制的渲染目标。
DXGI 即DirectX图形学基础,用于Direct3D交换链swap chains和枚举设备适配器
enumeration of deviceadapters的创建。
XInput 是之前版本DirectInput的一个补充,但XInput不支持键盘和鼠标等PC最常见的输入设备,所以涉及到键盘及鼠标消息的处理,还是需要使用DirectInput。
REFERENCED_PARAMETER用于避免变量定义后没在函数体中使用的编译警告
————————————————————————————————————————————————————————————
D3D11的初始化主要有以下几个步骤:
1. 创建设备ID3D11Device和设备上下文ID3D11DeviceContext;
2. 检测多重采样支持的等级:CheckMultisampleQualityLevels
3. 创建交换链
4. 创建RenderTargetView
5. 创建DepthStencilView
6. 把上述两个视图绑定到渲染管线相应的阶段
7. 设置Viewport
********************************************************************************
1 #include <Windows.h> 2 #include <string> 3 #include <D3D11.h> 4 #include <xnamath.h> 5 6 using namespace std; 7 8 //重要的全局变量 9 //在后面学习过程中,这些全局将作为框架类的成员变量存在 10 HINSTANCE g_hInstance(NULL); 11 HWND g_hWnd(NULL); 12 13 wstring g_clsName(L"d3d11"); 14 wstring g_wndTitle(L"D3D11初始化"); 15 16 UINT g_winWidth(640); 17 UINT g_winHeight(480); 18 19 //D3D相关全局变量 20 ID3D11Device *g_device(NULL); 21 ID3D11DeviceContext *g_deviceContext(NULL); 22 IDXGISwapChain *g_swapChain(NULL); 23 24 ID3D11DepthStencilView *g_depthStencilView(NULL); 25 ID3D11RenderTargetView *g_renderTargetView(NULL); 26 27 //初始化 28 BOOL InitWin32(); 29 //初始化D3D 30 BOOL InitD3D(); 31 void Render(); 32 //主循环 33 int Run(); 34 //回收资源 35 void Release(); 36 37 LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); 38 39 //程序入口 40 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow) 41 { 42 g_hInstance = hInstance; 43 44 if(!InitWin32()) 45 return -1; 46 if(!InitD3D()) 47 return -1; 48 49 return Run(); 50 } 51 52 BOOL InitWin32() 53 { 54 //创建窗口类 55 WNDCLASS wndcls; 56 wndcls.cbClsExtra = 0; 57 wndcls.cbWndExtra = 0; 58 wndcls.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); 59 wndcls.hCursor = LoadCursor(NULL,IDC_ARROW); 60 wndcls.hIcon = LoadIcon(NULL,IDI_APPLICATION); 61 wndcls.hInstance = g_hInstance; 62 wndcls.lpfnWndProc = WinProc; 63 wndcls.lpszClassName = g_clsName.c_str(); 64 wndcls.lpszMenuName = NULL; 65 wndcls.style = CS_HREDRAW | CS_VREDRAW; 66 67 //注册窗口类 68 if(!RegisterClass(&wndcls)) 69 { 70 MessageBox(NULL,L"窗口注册失败!",L"错误",MB_OK); 71 return FALSE; 72 } 73 74 //创建窗口 75 g_hWnd = CreateWindow(g_clsName.c_str(), 76 g_wndTitle.c_str(), 77 WS_OVERLAPPEDWINDOW, 78 CW_USEDEFAULT,CW_USEDEFAULT, 79 g_winWidth,g_winHeight, 80 NULL, 81 NULL, 82 g_hInstance, 83 NULL); 84 if(!g_hWnd) 85 { 86 MessageBox(NULL,L"窗口创建失败!",L"错误",MB_OK); 87 return FALSE; 88 } 89 90 //显示、更新窗口 91 ShowWindow(g_hWnd,SW_SHOW); 92 UpdateWindow(g_hWnd); 93 94 //Win32初始化完毕 95 return TRUE; 96 } 97 98 BOOL InitD3D() 99 { 100 //创建设备及上下文 101 D3D_FEATURE_LEVEL features[3] = {D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3}; 102 D3D_FEATURE_LEVEL myFeatureLevel; 103 HRESULT hr = D3D11CreateDevice(NULL,D3D_DRIVER_TYPE_HARDWARE,0,0,features,3,D3D11_SDK_VERSION,&g_device,&myFeatureLevel,&g_deviceContext); 104 if(FAILED(hr)) 105 { 106 MessageBox(NULL,L"创建d3d11设备失败!",L"错误",MB_OK); 107 return FALSE; 108 } 109 110 //检测4x采样等级 111 UINT msaa4xQuality(0); 112 g_device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM,4,&msaa4xQuality); 113 114 //创建交换链 115 //先描述其属性 116 DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; 117 swapChainDesc.BufferDesc.Width = g_winWidth; //宽、高 118 swapChainDesc.BufferDesc.Height = g_winHeight; 119 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; //刷新率 120 swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; 121 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; //恒定参数,按照这样指明即可 122 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; //同上 123 swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //数据格式,一个为RGBA四元色格式 124 swapChainDesc.BufferCount = 1; //后缓冲区个数,1个足够 125 swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; //Usage,很好理解 126 swapChainDesc.Flags = 0; 127 swapChainDesc.OutputWindow = g_hWnd; //主窗口句柄 128 swapChainDesc.SampleDesc.Count = 4; //多重采样 129 swapChainDesc.SampleDesc.Quality = msaa4xQuality-1; 130 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //交换:绝大多数情况用DISCARD 131 swapChainDesc.Windowed = true; //窗口模式 132 133 //获取IDXGIFactory以创建交换链 134 IDXGIDevice *dxgiDevice(NULL); 135 g_device->QueryInterface(__uuidof(IDXGIDevice),reinterpret_cast<void**>(&dxgiDevice)); 136 IDXGIAdapter *dxgiAdapter(NULL); 137 dxgiDevice->GetParent(__uuidof(IDXGIAdapter),reinterpret_cast<void**>(&dxgiAdapter)); 138 IDXGIFactory *dxgiFactory(NULL); 139 dxgiAdapter->GetParent(__uuidof(IDXGIFactory),reinterpret_cast<void**>(&dxgiFactory)); 140 hr = dxgiFactory->CreateSwapChain(g_device,&swapChainDesc,&g_swapChain); 141 if(FAILED(hr)) 142 { 143 MessageBox(NULL,L"创建d3d11交换链失败!",L"错误",MB_OK); 144 return FALSE; 145 } 146 dxgiFactory->Release(); 147 dxgiAdapter->Release(); 148 dxgiDevice->Release(); 149 150 //创建视图 151 //需要先获得资源 152 ID3D11Texture2D *backBuffer(NULL); 153 g_swapChain->GetBuffer(0,__uuidof(ID3D11Texture2D),reinterpret_cast<void**>(&backBuffer)); 154 hr = g_device->CreateRenderTargetView(backBuffer,NULL,&g_renderTargetView); 155 if(FAILED(hr)) 156 { 157 MessageBox(NULL,L"创建RenderTargetView失败!",L"错误",MB_OK); 158 return FALSE; 159 } 160 backBuffer->Release(); 161 162 //创建深度缓冲区视图 163 //要先创建对应缓冲区 164 //创建缓冲区Texture2D,要先给出描述 165 D3D11_TEXTURE2D_DESC desc = {0}; 166 desc.Width = g_winWidth; 167 desc.Height = g_winHeight; 168 desc.MipLevels = 1; 169 desc.ArraySize = 1; 170 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; 171 desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; 172 desc.MiscFlags = 0; 173 desc.SampleDesc.Count = 4; 174 desc.SampleDesc.Quality = msaa4xQuality-1; 175 desc.Usage = D3D11_USAGE_DEFAULT; 176 desc.CPUAccessFlags = 0; 177 ID3D11Texture2D *depthStencilBuffer(NULL); 178 hr = g_device->CreateTexture2D(&desc,NULL,&depthStencilBuffer); 179 if(FAILED(hr)) 180 { 181 MessageBox(NULL,L"创建d3d11深度缓冲区失败!",L"错误",MB_OK); 182 return FALSE; 183 } 184 hr = g_device->CreateDepthStencilView(depthStencilBuffer,NULL,&g_depthStencilView); 185 if(FAILED(hr)) 186 { 187 MessageBox(NULL,L"创建DepthStencilView失败!",L"错误",MB_OK); 188 return FALSE; 189 } 190 191 //有了视图要绑定到管线相应阶段 192 g_deviceContext->OMSetRenderTargets(1,&g_renderTargetView,g_depthStencilView); 193 depthStencilBuffer->Release(); 194 195 //最后设置视口 196 D3D11_VIEWPORT viewPort = {0}; 197 viewPort.Width = static_cast<FLOAT>(g_winWidth); 198 viewPort.Height = static_cast<FLOAT>(g_winHeight); 199 viewPort.MinDepth = 0.f; 200 viewPort.MaxDepth = 1.f; 201 viewPort.TopLeftX = 0.f; 202 viewPort.TopLeftY = 0.f; 203 g_deviceContext->RSSetViewports(1,&viewPort); 204 205 return TRUE; 206 } 207 208 void Render() 209 { 210 //渲染一个绿色的窗口 211 XMVECTORF32 color = {0.f, 1.f, 0.f, 1.6f}; 212 g_deviceContext->ClearRenderTargetView(g_renderTargetView,reinterpret_cast<float*>(&color)); 213 g_deviceContext->ClearDepthStencilView(g_depthStencilView,D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL,1.f,0); 214 215 //全部的场景绘制工作在这里面进行..... 216 217 //最后显示 218 g_swapChain->Present(0,0); 219 } 220 221 int Run() 222 { 223 MSG msg = {0}; 224 //主消息循环,也是游戏当中的主循环 225 while(msg.message != WM_QUIT) 226 { 227 if(PeekMessage(&msg,NULL,NULL,NULL,PM_REMOVE)) 228 { 229 TranslateMessage(&msg); 230 DispatchMessage(&msg); 231 } 232 else 233 { 234 //在这里做该做的事:渲染 235 Render(); 236 } 237 } 238 239 Release(); 240 241 return msg.wParam; 242 } 243 244 void Release() 245 { 246 g_depthStencilView->Release(); 247 g_renderTargetView->Release(); 248 g_swapChain->Release(); 249 g_deviceContext->Release(); 250 g_device->Release(); 251 } 252 253 LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 254 { 255 switch(msg) 256 { 257 case WM_DESTROY: 258 PostQuitMessage(0); 259 return 0; 260 } 261 262 return DefWindowProc(hwnd,msg,wParam,lParam); 263 }