上一讲我们说了DirectX11的初始化,初始化很简单,因为是固定的步骤和方法,简单的理一下:
1,使用D3D11CreateDevice接口创建ID3D11Device和ID3D11DeviceContext。
2,使用ID3D11Device::CheckMultisampleQualityLevels检查是否支持多重采样。
3,填充DXGI_SWAP_CHAIN_DESC结构体创建交换链。
4,IDXGISwapChain的创建需要几个步骤,相对来说这是最讨厌的一个了,下面大概说一下创建过程:
DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
swapChainDesc.BufferDesc.Width = width; //窗口的宽度
swapChainDesc.BufferDesc.Height = height;//窗口高度
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;// 刷新率 分子
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; // 分母
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;//用于秒速缩放枚举,想要了解更多查看MSDN
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;//用于描述扫描线绘制模式的枚举,同上
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;//用于描述显示格式的枚举类型,同上
swapChainDesc.BufferCount = 1;//后缓冲区个数,1个足够
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;//Usage,这些具体的查看MSDN就好
swapChainDesc.Flags = 0;// 描述交换链行为,默认为0既可
swapChainDesc.OutputWindow = m_hwnd; //主窗口句柄,指定显示的窗口
这个结构体这么填充即可,如果想要了解得更多,可以查看MSDN。
在填充好这个结构体后我们接下来看看怎么创建交换链,这个过程不是有参考的书籍我也不知道怎么创建,或者要慢慢的查阅MSDN了。
为了创建交换链,我们需要获取IDXGIFactory工厂接口,但是没有一个方法可以直接获取该接口,所以我们需要从ID3D11Device着手,COM组件就是这样,很多东西没有直接暴露,但是我们可以通过一个现有的查询未知的,所以我们现在拥有ID3D11Device接口,于是可以查询IDXGIDevice接口。
IDXGIDevice *dxgiDevice(NULL);
p_d3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast IDXGIDevice 可以获取IDXGIAdapter接口,IDXGIAdapter接口最终可以获取我们的工厂接口IDXGIFactory。 IDXGIAdapter *dxgiAdapter(NULL); dxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast IDXGIFactory *dxgiFactory(NULL); dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast result = dxgiFactory->CreateSwapChain(p_d3dDevice, &swapChainDesc, &p_swapChain); 最后终于创建出我们想要的交换链。 5,有了交换链后可以创建渲染目标视图: ID3D11Texture2D* backBufferTexture; result = p_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferTexture); result = p_d3dDevice->CreateRenderTargetView(backBufferTexture, 0, &p_backBufferTarget); 6, 创建深度模板buffer 7,将深度模板buffer和渲染目标视图绑定到渲染管道。 8,设置渲染窗口 ok,整个DirectX11的初始化就这样,好吧,我不善于说,也不善于写,不过还是希望能够对家有点帮助。 上一讲我们将DirectX的第一个程序给跑起来了,不过上面没啥东西,这一讲我们准备在上面花点什么东西,那就从最简单的开始,画一个正方行。 DirectX 对图元的绘制主要是按三角形来绘制,好吧,我的表达感觉怎么这么怪呢,当然不是只能画三角形,只是常规都是画三角形,因为三角形效率高啊,嗯,这可能不是很有力的说服力,它可以绘制各种图元,这里不展开说,为什么呢,因为等大家熟悉了之后这些东西也就全都明白了,这里我们还是说三角形吧。 我们来看看这么绘制三角形,三角形当然要有三个点,所以如果要绘制一个四边形那么我们就要绘制两个三角形,那么就是6个点,比如说四边形的四个顶点为ABCD,那么我们绘制的时候就要准备两组三角形的数据,分别为什么ABC和CBD。每一个顶点要有属于的自己的坐标,当然这时最基本的,我们可以还有色彩,在DirectX里面色彩通常用四个浮点数表示,分别为rgba,同样我们可以纹理坐标,纹理为什么先预留,后面再说。 在DirectX里面通常用XMFLOAT3类型表示顶点,他有xyz三个分量,用XMFLOAT4表示颜色,有xyzw分量,用XMFLOAT2表示二维纹理坐标,有xy分量。ok,知道这些后我们可以简单的定义出四边形的顶点类型: //------------------- statuc VertexType{ XMFLOAT3 Pos; XMFLOAT4 Colour; XMFLOAT2 Tex; }; D3D11_INPUT_ELEMENT_DESC PCTLayout[3] = { { 'POSITION', 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { 'COLOR', 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { 'TEXCOORD', 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; //------------------ D3D11_INPUT_ELEMENT_DESC 关于这个结构体 ,怎么说呢,要写说的话得不少篇幅,好吧,但又好像没多大用,自己百度一下就好了,那就这么愉快的决定了,我们继续向前。我们接下来创建一个布局和顶点buffer //-------------------- pLayoutManager = new MDx11LayoutManage(dx_GetDevice()); pBufferManager = new MDx11BufferManage(dx_GetDevice()); pLayoutManager->dx_FxComplieFile('FX/MDx11WindowFX.fx'); pTechnique = pLayoutManager->dx_GetTechFromEF('MDx11WindowTech'); pLayout = pLayoutManager->dx_CreatInputLayout(PCTLayout, ARRAYSIZE(PCTLayout), 'MDx11WindowTech'); VertexType Points[] = { { { -100.5, 100.5, 1 }, { 1.f, 0.f, 0.f, 1.f }, { 0.f, 0.f } }, { { 100.5, 100.5, 1 }, { 0.f, 1.f, 0.f, 1.f }, { 0.f, 0.f } }, { { -100.5, -100.5, 1 }, { 0.f, 0.f, 1.f, 1.f }, { 0.f, 0.f } }, { { -100.5, -100.5, 1 }, { 0.f, 0.f, 1.f, 1.f }, { 0.f, 0.f } }, { { 100.5, 100.5, 1 }, { 0.f, 1.f, 0.f, 1.f }, { 0.f, 0.f } }, { { 100.5, -100.5, 1 }, { 1.f, 0.f, 0.f, 1.f }, { 0.f, 0.f } } }; pVertexBuffer = pBufferManager->dx_CreateVectexBuffer(Points, ARRAYSIZE(Points)); //------------------------ MDx11WindowFX.fx 文件的内容待会贴出。ok,现在我们可以绘制了 //------------------------ class FirstDirectWindow : public MDx11Base{ public: FirstDirectWindow(){ } ~FirstDirectWindow(){} bool dx_LoadContent(){ try{ std::vector std::vector points.push_back({ { -100.5, 100.5, 1 }, { 1.f, 0.f, 0.f, 1.f }, { 0.f, 0.f } }); points.push_back({ { 100.5, 100.5, 1 }, { 0.f, 1.f, 0.f, 1.f }, { 0.f, 0.f } }); points.push_back({ { -100.5, -100.5, 1 }, { 0.f, 0.f, 1.f, 1.f }, { 0.f, 0.f } }); points.push_back({ { -100.5, -100.5, 1 }, { 0.f, 0.f, 1.f, 1.f }, { 0.f, 0.f } }); points.push_back({ { 100.5, 100.5, 1 }, { 0.f, 1.f, 0.f, 1.f }, { 0.f, 0.f } }); points.push_back({ { 100.5, -100.5, 1 }, { 1.f, 0.f, 0.f, 1.f }, { 0.f, 0.f } }); pLayoutManager = new MDx11LayoutManage(dx_GetDevice()); pBufferManager = new MDx11BufferManage(dx_GetDevice()); pLayoutManager->dx_FxComplieFile('FX/MDx11WindowFX.fx'); pTechnique = pLayoutManager->dx_GetTechFromEF('MDx11WindowTech'); pLayout = pLayoutManager->dx_CreatInputLayout(PCTLayout, ARRAYSIZE(PCTLayout), 'MDx11WindowTech'); pVertexBuffer = pBufferManager->dx_CreateVectexBuffer(&points[0], points.size()); return true; } catch (std::runtime_error e){ box::ErrorBox(e.what()); return false; } } void dx_Render(); private: MDx11BufferManage* pBufferManager{ nullptr }; MDx11LayoutManage* pLayoutManager{ nullptr }; LPD3D11EFFECTTECHNIQUE pTechnique{ nullptr }; ID3D11Buffer* pVertexBuffer{ nullptr };; ID3D11InputLayout* pLayout{ nullptr }; }; void FirstDirectWindow::dx_Render(){ if (!dx_GetDevice() || !dx_GetContext()){ return; } float clearColor[4] = { 0.f, 0.f, 0.25f, 1.0f }; dx_GetContext()->ClearRenderTargetView(p_backBufferTarget, clearColor); dx_GetContext()->ClearDepthStencilView(p_depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0.0f); size_t strit = sizeof(BasicPCT); size_t offset = 0; static float walk = -0.01; mCamera.dx_Walk(walk); mCamera.dx_UpDateMatrix(); static float angle = 0; angle += 0.1; dx_GetContext()->IASetVertexBuffers(0, 1, &pVertexBuffer, &strit, &offset); dx_GetContext()->IASetIndexBuffer(pIndexBuffer, DXGI_FORMAT_R32_UINT, 0); dx_GetContext()->IASetInputLayout(pLayout); dx_GetContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); XMMATRIX word = XMMatrixIdentity(); word = word*mCamera.dx_GetModeViewMatrix() *mCamera.dx_GetProjectMatrix(); pLayoutManager->dx_GetMatrixFromEF('MWorldMatrix')->SetMatrix(reinterpret_cast D3DX11_TECHNIQUE_DESC techdesc = pLayoutManager->dx_GetTichDescFromEF('MDx11WindowTech'); for (int i = 0; i < techdesc.passes;=""> pTechnique->GetPassByIndex(i)->Apply(i, dx_GetContext()); dx_GetContext()->Draw(6, 0); } dx_GetSwapChain()->Present(0, 0); } 下面是Fx文件 //==================// matrix MWorldMatrix; struct VSSceneIn { float3 pos : POSITION; float4 colour : COLOR; float2 tex : TEXCOORD; }; struct PSSceneIn { float4 pos : SV_Position; float4 colour : COLOR; float2 tex : TEXCOORD; }; DepthStencilState DisableDepth { DepthEnable = FALSE; DepthWriteMask = ZERO; }; DepthStencilState LessEqualDSS { DepthEnable = TRUE; DepthFunc = LESS_EQUAL; }; SamplerState WindowSampler { Filter = MIN_MAG_MIP_LINEAR; AddressU = Border; AddressV = Border; }; RasterizerState Rasterstate { DepthClipEnable = false; FillMode = Solid; CullMode = Back; FrontCounterClockwise = false; ScissorEnable = false; }; RasterizerState RasterstateForObj { DepthClipEnable = false; FillMode = Solid; CullMode = Back; FrontCounterClockwise = true; ScissorEnable = false; }; // Vertex shader PSSceneIn VSMain(VSSceneIn input) { PSSceneIn output = (PSSceneIn)0.0; output.pos = mul(float4(input.pos,1),MWorldMatrix); output.tex = input.tex; output.colour = input.colour; return output; } float4 PSMain(PSSceneIn input) : SV_Target { return input.colour; float4 colour = MWindowTexture.Sample(WindowSampler, input.tex); return input.colour*colour; } // Techniques technique11 MDx11WindowTech { pass P0 { SetVertexShader(CompileShader(vs_5_0, VSMain())); SetGeometryShader(NULL); SetPixelShader(CompileShader(ps_5_0, PSMain())); SetDepthStencilState(LessEqualDSS, 0); SetRasterizerState(Rasterstate); } } //=================// //----------------------- 下面我们来执行程序看看。 //======================== int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPWSTR cmdLine, int cmdShow) { INITCOM; MWindow w; TestDirctWindow d3dwindow; if (!d3dwindow.dx_Init(&w)){ return 0; } w.Show(); return w.Run(); } //======================== 好吧,我们算是接触了DirectX的东西,接下来就是大家慢慢摸索的事啦,哈哈。 ///========================
联系客服