上一讲我们说了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<void**>(&
dxgiDevice));
IDXGIDevice 可以获取IDXGIAdapter接口,IDXGIAdapter接口最终可以获取我们的工厂接口IDXGIFactory。
IDXGIAdapter *dxgiAdapter(NULL);
dxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&
dxgiAdapter));
IDXGIFactory *dxgiFactory(NULL);
dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&
dxgiFactory));
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<unsigned>indexs;
std::vector<BasicPCT>points;
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;
staticfloat walk = -0.01;
mCamera.dx_Walk(walk);
mCamera.dx_UpDateMatrix();
staticfloat 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<
float*>(&
word));
D3DX11_TECHNIQUE_DESC techdesc = pLayoutManager->dx_GetTichDescFromEF(“MDx11WindowTech”);
for (int i = 0;
i <techdesc.Passes;
++i){
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的东西,接下来就是大家慢慢摸索的事啦,哈哈。
///========================
回复D查看目录,回复数字查看相应章节
原文始发于微信公众号(
C/C++的编程教室
):第128讲 MDx11Frame(8)
|