上次讲了directx的初始化 ,今天就来运用directx实现两个简单的效果-三角形和立方体好了下面给出效果图:
好了开始进入主题:
在DX中要想绘制一个简单的图形,就得涉及到顶点知识 ,顶点是3D几何学中的基本元素,顶点的属性有,位置,颜色,纹理坐标等等,可通过struct结构体对顶点进行设计,如下
struct VERTEX
{
XMFLOAT3 pos;//位置
};
struct VERTEX
{
XMFLOAT3 pos;
XMFLOAT4 color;//颜色
};
为本实例的中的定点设计,当然可根据具体情况进行设计。
顶点的属性是有了,但是得让DX识别顶点属性啊,DX11中用于描述顶点的结构体为 D3D11_INPUT_ELEMENT_DESC ,msdn中定义如下:
typedef struct D3D11_INPUT_ELEMENT_DESC {
LPCSTR SemanticName;//语义
UINT SemanticIndex;//索引(出现在相同的语义时)
DXGI_FORMAT Format;//格式
UINT InputSlot;//出入巢
UINT AlignedByteOffset;//偏移量
D3D11_INPUT_CLASSIFICATION InputSlotClass;//
UINT InstanceDataStepRate;//
} D3D11_INPUT_ELEMENT_DESC;
该结构体的填充与之前设计的顶点结构体相对应:如下是本实例结构体的填充:
三角形顶点:
D3D11_INPUT_ELEMENT_DESC vertexLayout[]=
{
{ "POSITION", 0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0}
};
立方体顶点:
D3D11_INPUT_ELEMENT_DESC inputDesc[]=
{
{ "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 }
};
结构体填充好了之后,就可以创建顶点布局,这样DX就能关联到你设计的顶点了,DX11中输入布局的创建用到
HRESULT CreateInputLayout(
[in] const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,//所填充的结构体
[in] UINT NumElements,//结构体大小
[in] const void *pShaderBytecodeWithInputSignature,//
[in] SIZE_T BytecodeLength,//这两个不知道怎么翻译
[out] ID3D11InputLayout **ppInputLayout
);
代码如下:
hr = g_d3dDevice->CreateInputLayout(vertexLayout, totalVertexLayout, vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(), &g_inputLayout);
输入布局创建好之后,就是顶点缓存或者索引顶点缓存的创建,这些缓存就是用来存储顶点的,DX11中缓存结构体为:
typedef struct D3D11_BUFFER_DESC {
UINT ByteWidth;//缓存的大小
D3D11_USAGE Usage;//用途
UINT BindFlags;//绑定的标志(顶点缓存还是索引顶点缓存)
UINT CPUAccessFlags;//0
UINT MiscFlags;//0
UINT StructureByteStride;<pre name="code" class="cpp">typedef struct D3D11_SUBRESOURCE_DATA {
const void *pSysMem;
UINT SysMemPitch;
UINT SysMemSlicePitch;
} D3D11_SUBRESOURCE_DATA;
} D3D11_BUFFER_DESC;
代码如下:
D3D11_BUFFER_DESC vbDesc;
ZeroMemory(&vbDesc, sizeof(vbDesc));
vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbDesc.ByteWidth = sizeof(VERTEX)* 3;
D3D11_SUBRESOURCE_DATA vbsrs;
vbsrs.pSysMem = vertex;
通过这两个结构体的填充,即可创建缓存:
hr = g_d3dDevice->CreateBuffer(&vbDesc, &vbsrs, &g_vertexBuffer);
这些写好之后就可以进行着色器代码的编写了,DX11中 着色器有,顶点着色器(对顶点进行处理),像素着色器(对像素处理),几何着色器(图元的处理),域着色器(还没学到), 本次指用到前两个,关于着色器的相关知识可以查阅相关资料,我就不误人子弟了,本实例中的着色器代码如下:
float4 VS(float4 pos :POSITION):SV_POSITION
{
return pos;
}
float4 PS(float4 pos:SV_POSITION):SV_TARGET
{
return float4(0.0f, 0.0f, 1.0f, 1.0f);
}
其中的VS为顶点着色器,PS为像素着色器,分别对顶点和像素进行处理,着色器代码写好之后,在C++中还得对着色器进行编译和创建,这样才能使用。
编译用到:
HRESULT D3DX11CompileFromFile(
_In_ LPCTSTR pSrcFile,//着色器明
_In_ const D3D10_SHADER_MACRO *pDefines,//null
_In_ LPD3D10INCLUDE pInclude,//null
_In_ LPCSTR pFunctionName,//VS或者PS 入口函数,如果使用effect的话,为空
_In_ LPCSTR pProfile,//VS 或者PS的版本号(vs_5_0,ps_5_0)
_In_ UINT Flags1,//0
_In_ UINT Flags2,//0
_In_ ID3DX11ThreadPump *pPump,//0
_Out_ ID3D10Blob **ppShader,
_Out_ ID3D10Blob **ppErrorMsgs,
_Out_ HRESULT *pHResult
);
编译好之后就可以创建了
HRESULT CreateVertexShader(
[in] const void *pShaderBytecode,
[in] SIZE_T BytecodeLength,
[in] ID3D11ClassLinkage *pClassLinkage,
[out] ID3D11VertexShader **ppVertexShader
);
HRESULT CreatePixelShader(
[in] const void *pShaderBytecode,
[in] SIZE_T BytecodeLength,
[in] ID3D11ClassLinkage *pClassLinkage,
[out] ID3D11PixelShader **ppPixelShader
);
具体代买如下:
hr = D3DX11CompileFromFile(filepath, 0, 0, entryport, shahermodel, shaderFlags, 0, NULL, buffer, &errorBuffer,NULL);
hr = g_d3dDevice->CreateVertexShader(vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(), NULL, &g_vertexShader);
hr = g_d3dDevice->CreatePixelShader(psBuffer->GetBufferPointer(), psBuffer->GetBufferSize(), NULL, &g_pixelShader);
着色器创建好了之后,之后就是各种把各种资源绑定到相应的流水线中去,即可,DX11的流水线如下 :
代码如下:
g_d3dDeviceContext->IASetVertexBuffers(0, 1, &g_vertexBuffer, &stride, &offset);
g_d3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
g_d3dDeviceContext->VSSetShader(g_vertexShader, 0, 0);
g_d3dDeviceContext->PSSetShader(g_pixelShader, 0, 0);
g_d3dDeviceContext->Draw(3, 0);
g_swapChain->Present(0, 0);
首先是输入装配阶段对顶点缓存的设置,接着是顶点,像素着色器的绑定,这些弄好之后,就是图形的现实,DX11 图形的形式可参见
D3D11_PRIMITIVE_TOPOLOGY
结构体,
设置图元只好,即可使用
void Draw(
[in] UINT VertexCount,
[in] UINT StartVertexLocation
);
或者:
void DrawIndexed(
[in] UINT IndexCount,
[in] UINT StartIndexLocation,
[in] INT BaseVertexLocation
);
来绘制所涉及的图形了,前者没有使用索引顶点缓存,后者是有了索引。
好了由于篇幅较大,就只讲三角形的绘制方法了,之后在讲立方体是如何使用索引以及Effect
本章代码如下:点击打开链接