本文将在上文绘制的矩形中,绘制图片。
读取图片,并转化为纹理。
将该纹理绑定到 Pipeline
设置采样器,像素着色器通过该采样器对输出的纹理进行采样
通过该函数将图片数据,读取到纹理中。 该函数来自于,引用了WICTextureLoader11.cpp / WICTextureLoader11.h
读取图片到纹理,然后将该纹理设置为 shader 的资源
设置图片的采样方式
设置完这两个参数之后,每个空间上的点,需要知道他在图片中的相对位置,才能对图片进行采样,以获取其真正的 rgb 颜色,所以顶点缓存中除了设置了每个点的空间位置又增加了其对应的图片坐标。
图片坐标系是 uv 坐标系,坐标原点在图片的左上方,x轴向右,y轴向下。图片的宽为1,高为1,所以图片左上角坐标为(0,0),右下角坐标为(1,1)
Texture2D tex : register(t0); 表示 tex 从 t的第0个位置取出纹理数据,需要和 PSSetShaderResources 放入的位置对应。
SamplerState samplerLinear : register(s0); 同上
tex.Sample(samplerLinear, pIn.tex); 对 tex 采用 samplerLinear 方式采样 pIn.tex 位置的颜色信息,作为该点的颜色。
void Graphics::InitEffect()
{
/************************************* 顶点着色器阶段 **************************************/
ID3DBlob* pBlob = NULL;
D3DReadFileToBlob(L"HLSL/vs.cso", &pBlob);
m_pDevice->CreateVertexShader(pBlob->GetBufferPointer(), pBlob->GetBufferSize(), nullptr, &m_pVertexShader);
m_pDevice->CreateInputLayout(layout,
2,
pBlob->GetBufferPointer(), // 该 shader 有 layout 中定义的 SemanticName
pBlob->GetBufferSize(),
&m_inputLayout);
/************************************* 像素着色器阶段 **************************************/
D3DReadFileToBlob(L"HLSL/ps.cso", &pBlob);
m_pDevice->CreatePixelShader(pBlob->GetBufferPointer(), pBlob->GetBufferSize(), nullptr, &m_pPixelShader);
}
void Graphics::DrawTriangle()
{
InitEffect();
/************************************* 输入装配阶段 **************************************/
//创建顶点缓存
struct SimpleVertex
{
DirectX::XMFLOAT3 pos;
DirectX::XMFLOAT2 tex;
};
SimpleVertex vertices[] =
{
{DirectX::XMFLOAT3(-0.5f, -0.5f, 0.5f), XMFLOAT2(0.0f, 1.0f)},
{DirectX::XMFLOAT3(-0.5f, 0.5f, 0.5f), XMFLOAT2(0.0f, 0.0f)},
{DirectX::XMFLOAT3(0.5f, 0.5f, 0.5f), XMFLOAT2(1.0f, 0.0f)},
{DirectX::XMFLOAT3(0.5f, -0.5f, 0.5f), XMFLOAT2(1.0f, 1.0f)},
};
D3D11_BUFFER_DESC verticsDesc = {};
verticsDesc.ByteWidth = sizeof(vertices) * 5; // 字节数
// 将 usage 设为 D3D11_USAGE_IMMUTABLE D3D11_USAGE_DEFAULT 可行
verticsDesc.Usage = D3D11_USAGE_IMMUTABLE; // 资源的使用,gpu和cpu 的读写权限
verticsDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; // 标识如何将资源绑定到 pipeline
verticsDesc.CPUAccessFlags = 0; // CPU 的读写权限
verticsDesc.MiscFlags = 0;
verticsDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA resourceData = {};
resourceData.pSysMem = vertices;
resourceData.SysMemPitch = 0;
resourceData.SysMemSlicePitch = 0;
ID3D11Buffer* verticesBuffer = NULL;
m_pDevice->CreateBuffer(&verticsDesc, &resourceData, &verticesBuffer);
UINT strider = sizeof(SimpleVertex);
UINT offset = 0;
m_pContext->IASetVertexBuffers(
0, // start slot
1, // buffer 数量 (start slot ~ start slot + buffer number
&verticesBuffer,// 顶点缓存
&strider, // 每组数据的字节数
&offset); // 偏移量
DirectX::XMUINT3 index[] = {
{0, 1, 2},
{0, 2, 3}};
D3D11_BUFFER_DESC indexDesc = {};
indexDesc.ByteWidth = sizeof(index) * 2; // 字节数
// 将 usage 设为 D3D11_USAGE_IMMUTABLE D3D11_USAGE_DEFAULT 可行
indexDesc.Usage = D3D11_USAGE_IMMUTABLE; // 资源的使用,gpu和cpu 的读写权限
indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; // 标识如何将资源绑定到 pipeline
indexDesc.CPUAccessFlags = 0; // CPU 的读写权限
indexDesc.MiscFlags = 0;
indexDesc.StructureByteStride = 0;
resourceData.pSysMem = index;
resourceData.SysMemPitch = 0;
resourceData.SysMemSlicePitch = 0;
ID3D11Buffer* indexBuffer = NULL;
m_pDevice->CreateBuffer(&indexDesc, &resourceData, &indexBuffer);
// 设置所引缓存
m_pContext->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0);
// 输入布局
m_pContext->IASetInputLayout(m_inputLayout);
// 图元拓扑结构
m_pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
/************************************* 顶点着色器阶段 **************************************/
m_pContext->VSSetShader(m_pVertexShader, nullptr, 0);
/************************************* 像素着色器阶段 **************************************/
m_pContext->PSSetShader(m_pPixelShader, nullptr, 0);
ID3D11Resource* inputResource = NULL;
ID3D11ShaderResourceView* shaderResourceView = NULL;
std::wstring path = L"res\\image\\dog.jpg";
CreateWICTextureFromFile(m_pDevice,
path.c_str(),
&inputResource,
&shaderResourceView);
m_pContext->PSSetShaderResources(0, 1, &shaderResourceView);
ID3D11SamplerState* sampler;
D3D11_SAMPLER_DESC sampleDesc = {};
sampleDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampleDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; // 平铺整数个
sampleDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
sampleDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
sampleDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampleDesc.MinLOD = 0;
sampleDesc.MaxLOD = D3D11_FLOAT32_MAX;
m_pDevice->CreateSamplerState(&sampleDesc, &sampler);
m_pContext->PSSetSamplers(0, 1, &sampler);
/************************************* 输出阶段 **************************************/
// 设置渲染目标
m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, NULL);
// 设置视口
D3D11_VIEWPORT viewPort = {};
viewPort.TopLeftX = 0;
viewPort.TopLeftY = 0;
viewPort.Width = 800;
viewPort.Height = 600;
viewPort.MinDepth = 0.0f;
viewPort.MaxDepth = 1.0f;
m_pContext->RSSetViewports(1, &viewPort);
// 开始绘制
m_pContext->DrawIndexed(6, 0, 0);
}
struct VSOut
{
float4 pos : SV_Position;
float2 tex : TEXCOORD;
};
struct VSIn
{
float3 pos : POSITION;
float3 tex : TEXCOORD;
};
VSOut MyVs(VSIn vIn)
{
VSOut vsOut;
vsOut.pos = float4(vIn.pos.x, vIn.pos.y, vIn.pos.z, 1.0);
vsOut.tex = vIn.tex;
return vsOut;
}
Texture2D tex : register(t0);
SamplerState samplerLinear : register(s0);
struct VSOut
{
float4 pos : SV_Position;
float2 tex : TEXCOORD;
};
float4 MyPs(VSOut pIn) : SV_Target
{
return tex.Sample(samplerLinear, pIn.tex);
}
因篇幅问题不能全部显示,请点此查看更多更全内容