使用常量缓冲:
void mGraphics::DrawTriangle(float angle)
{
struct ConstantBuffer //用于创建常量缓冲的布局
{
float rotaror[4][4];
};
ConstantBuffer cBuffer{ //用于创建常量缓冲的数据
cos(angle),sin(angle),0,0,
-sin(angle),cos(angle),0,0,
0,0,1,0,
0,0,0,1
};
Microsoft::WRL::ComPtr < ID3D11Buffer> pConstantBuffer;
D3D11_BUFFER_DESC cbd{};
cbd.ByteWidth = sizeof(ConstantBuffer); //字节宽度,缓冲区的总大小,
cbd.Usage = D3D11_USAGE_DYNAMIC; //该Buffer的用法,GPU读CPU写 (虽然float angle变化 由于函数逐帧调用,每次都会创建,所以设置用途不大)
cbd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; //CPU可否更改,0表示不需要CPU访问功能
cbd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; //缓冲绑定pipeline的阶段,作为 顶点/索引/常量缓冲 绑定
cbd.MiscFlags = 0u; //其他标志:0表示不使用
cbd.StructureByteStride = 0; //Buffer中,单组数据的大小
D3D11_SUBRESOURCE_DATA csd{};
csd.pSysMem = &cBuffer;
pDevice->CreateBuffer(&cbd, &csd, &pConstantBuffer);
pContext->VSSetConstantBuffers(0u, 1u, pConstantBuffer.GetAddressOf());
//创建顶点Buffer
struct Vertex {
struct { float x; float y; }position;
struct { unsigned char r; unsigned char g; unsigned char b; }color;
};
Vertex vertices[] = {
{0.f,0.f,255,0,0},
{0.25f,-1.f,0,0,255},
{-0.25f,-1.f,0,255,0},
{-1.f,1.f,0,0,0},
{1.0f,1.f,127,127,127},
{-1.f,-1.f,127,127,127},
{1.f,-1.f,255,255,255},
};
D3D11_BUFFER_DESC bd{};
bd.ByteWidth = sizeof(vertices); //字节宽度,缓冲区的总大小,
bd.Usage = D3D11_USAGE_DEFAULT; //该Buffer的用法,常用该默认值,表示GPU可读写,其他:GPU读,GPU读,CPU仅写,
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; //缓冲绑定pipeline的阶段,作为 顶点/索引/常量缓冲 绑定
bd.CPUAccessFlags = 0u; //CPU可否更改,0表示不需要CPU访问功能
bd.MiscFlags = 0u; //其他标志:0表示不使用
bd.StructureByteStride = sizeof(Vertex); //Buffer中,单组数据的大小
D3D11_SUBRESOURCE_DATA sd{};
sd.pSysMem = vertices; //初始化数据,表示使用vertices数组中的数据初始化Buffer,
Microsoft::WRL::ComPtr<ID3D11Buffer> pVertexBuffer;
pDevice->CreateBuffer(&bd, &sd, &pVertexBuffer); //ComPtr用于填充,使用 & 获取地址,而不是GetAddressOf函数
//绑定顶点缓冲区到pipeline
const UINT stride = sizeof(Vertex);
const UINT offset = 0u;
pContext->IASetVertexBuffers(0u, 1u, pVertexBuffer.GetAddressOf(), &stride, &offset);//参数:StartSlot,NumBuffer,缓冲区指针,步幅 单组顶点数据大小,从缓冲区的第几个字节开始
//索引缓冲区
unsigned int index[] = {
3,4,5,
5,4,6,
0,1,2, //用于DrawIndexed 用于画三角形,每三个值一组有效
};
D3D11_BUFFER_DESC ibd{};
ibd.ByteWidth = sizeof(index);
ibd.Usage = D3D11_USAGE_DEFAULT;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0u;
ibd.MiscFlags = 0u;
ibd.StructureByteStride = sizeof(unsigned int);
D3D11_SUBRESOURCE_DATA isd{};
isd.pSysMem = index;
Microsoft::WRL::ComPtr< ID3D11Buffer>pIndexBuffer;
pDevice->CreateBuffer(&ibd, &isd, &pIndexBuffer);
pContext->IASetIndexBuffer(pIndexBuffer.Get(),DXGI_FORMAT_R32_UINT, 0);
Microsoft::WRL::ComPtr<ID3DBlob> pBlob;
//创建,读取,绑定顶点着色器
Microsoft::WRL::ComPtr<ID3D11VertexShader> pVertexShader;// 用作函数输出,指向顶点着色器
D3DReadFileToBlob(L"VertexShader.cso", &pBlob); //从目录中 加载cso文件,注意要把hlsl文件编译方式:"$(ProjectDir)%filename).cso"
pDevice->CreateVertexShader(pBlob->GetBufferPointer(), pBlob->GetBufferSize(), nullptr, &pVertexShader);
pContext->VSSetShader(pVertexShader.Get(), nullptr, 0u);
//顶点输入布局input layout
Microsoft::WRL::ComPtr<ID3D11InputLayout>pInputLayout;
const D3D11_INPUT_ELEMENT_DESC ied[] =
{
{
"Position",0, //"Position"和0 表示vertexS中的"Position"语义,1表示"Position1"语义
DXGI_FORMAT_R32G32_FLOAT,
0,
0,
D3D11_INPUT_PER_VERTEX_DATA,0
},
{
"Color",0,
DXGI_FORMAT_R8G8B8A8_UNORM, //0到255 转为 0到1,
0,
8, //偏移一组数据中的 float x,y
D3D11_INPUT_PER_VERTEX_DATA,0
}
};
pDevice->CreateInputLayout(
ied, //描述数组
(UINT)std::size(ied), //描述数组元素数量,表示 Buffer中一组顶点数据如何分段 此处float x,y输入语义Position,unsigned char r,g,b,输入语义Color
pBlob->GetBufferPointer(), //pBlob现在仍然读取的是 VertexShader.cso文件的信息,这个参数用于检查 用户给的信息是 否与 着色器文件 相符 生成编译期的警告
pBlob->GetBufferSize(), //数据的字节大小
&pInputLayout //用作输出layout的指针
);
pContext->IASetInputLayout(pInputLayout.Get());
//创建,读取,绑定像素着色器
Microsoft::WRL::ComPtr<ID3D11PixelShader> pPixelShader;// 用作函数输出,指向像素着色器
D3DReadFileToBlob(L"PixelShader.cso", &pBlob); //从目录中 加载cso文件,注意要把hlsl文件编译方式:"$(ProjectDir)%filename).cso"
pDevice->CreatePixelShader(pBlob->GetBufferPointer(), pBlob->GetBufferSize(), nullptr, &pPixelShader);
pContext->PSSetShader(pPixelShader.Get(), nullptr, 0u);
//绑定渲染目标,作为输出
pContext->OMSetRenderTargets(1u, pTarget.GetAddressOf(), nullptr); //注意:对ComPtr取地址,“&PTarget”表示先release掉,再返回地址
//归一化设备坐标(NDC)映射到屏幕,配置视口,1/4大小,居中
D3D11_VIEWPORT vp;
vp.Width = 400;
vp.Height = 300;
vp.MinDepth = 0;
vp.MaxDepth = 1;
vp.TopLeftX = 200;
vp.TopLeftY = 150;
pContext->RSSetViewports(1u, &vp);
//绘制背景
pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
//画六边形
pContext->DrawIndexed((UINT)std::size(index), 0u, 0u);
}
struct VSOutput
{
float3 color:Color;
float4 position:SV_Position;
};
cbuffer constantBuffer//保证布局一致
{
row_major matrix transform;//CPU 二维数组按行存储,GPU按列存储,所以要转置, GPU计算行矩阵比列矩阵稍慢
};
struct VSOutput main(float2 pos : Position, float3 color: Color)
{
VSOutput vsout;
vsout.position = mul(float4(pos.x, pos.y, 0.0f, 1.0f), transform);
vsout.color = color;
return vsout;
}
更新常量缓冲:
D3D11_MAPPED_SUBRESOURCE mappedSubresource;
pContext->Map(pConstBuffer.Get(), 0u, D3D11_MAP_WRITE_DISCARD, 0u, &mappedSubresource);
memcpy(mappedSubresource.pData, pCBuffer, cBufferSize);
pContext->Unmap(pConstBuffer.Get(), 0u);