前言
在上一篇已经展示了如何绘制一个2d三角形,此篇将展示如何给这个三角形添加纹理
流程
shader file
struct PSInput
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD;
};
Texture2D g_texture : register(t0);
SamplerState g_sampler : register(s0);
PSInput VSMain(float4 position : POSITION, float4 uv : TEXCOORD)
{
PSInput result;
result.position = position;
result.uv = uv;
return result;
}
float4 PSMain(PSInput input) : SV_TARGET
{
return g_texture.Sample(g_sampler, input.uv); //Sample用于采样纹理
}
header file
因为要添加纹理,所以头文件也有些变化
class D3D12HelloTexture : public DXSample
{
//...
private:
//...
//描述一张纹理图的属性
static const UINT TextureWidth = 256;
static const UINT TextureHeight = 256;
static const UINT TexturePixelSize = 4; // 像素的字节数
struct Vertex
{
XMFLOAT3 position;
XMFLOAT2 uv; //顶点结构体需要传递映射后的uv值
};
ComPtr<ID3D12DescriptorHeap> m_srvHeap; //存储着色器资源描述符句柄
ComPtr<ID3D12Resource> m_texture; //存储纹理描述符
ComPtr<ID3D12Resource> textureUploadHeap; //纹理缓冲区
std::vector<UINT8> GenerateTextureData(); //程序性纹理
}
source file
初始化管线
大部分和上篇一致,仅仅多了创建SRV描述符堆这一步
/*Describe and create a shader resource view (SRV) heap for the texture*/
D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
srvHeapDesc.NumDescriptors = 1;
srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
ThrowIfFailed(m_device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_srvHeap)));
加载资源
创建根描述符
/*create the root signature*/
D3D12_FEATURE_DATA_ROOT_SIGNATURE featureData = {};
//specified the highestVersion of signature
// This is the highest version the sample supports. If CheckFeatureSupport succeeds, the HighestVersion returned will not be greater than this.
featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_1;
if (FAILED(m_device->CheckFeatureSupport(D3D12_FEATURE_ROOT_SIGNATURE, &featureData, sizeof(featureData))))
{
featureData.HighestVersion = D3D_ROOT_SIGNATURE_VERSION_1_0;
}
//set the descriptor range
CD3DX12_DESCRIPTOR_RANGE1 ranges[1];
ranges[0].Init(
D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
1,
0,
0,
D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC //Both descriptors and data are static. This maximizes the potential for driver optimization
);
//set the root parameter
CD3DX12_ROOT_PARAMETER1 rootParameters[1];
rootParameters[0].InitAsDescriptorTable(
1,
&ranges[0],
D3D12_SHADER_VISIBILITY_PIXEL
);
//创建静态采样器
D3D12_STATIC_SAMPLER_DESC sampler = {};
sampler.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; //对纹理图与mipmap层级进行点采样
sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER; //边框颜色寻址
sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
sampler.MipLODBias = 0; //mipmap层级的offset
sampler.MaxAnisotropy = 0; //最大各项异性过滤值
sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; //不调用比较函数
sampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; //指定边框颜色寻址的颜色
sampler.MinLOD = 0.0f; //mipmap最小层级
sampler.MaxLOD = D3D12_FLOAT32_MAX; //mipmap最大层级
sampler.ShaderRegister = 0;
sampler.RegisterSpace = 0;
sampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc; //保存根签名版本,该结构体设计用于序列化/反序列化函数配合
rootSignatureDesc.Init_1_1(_countof(rootParameters), rootParameters, 1, &sampler, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
//序列化和创建根签名
ComPtr<ID3DBlob> signature;
ComPtr<ID3DBlob> error;
//与CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC搭配使用
ThrowIfFailed(D3DX12SerializeVersionedRootSignature(&rootSignatureDesc, featureData.HighestVersion, &signature, &error));
ThrowIfFailed(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)));
创建顶点描述布局
D3D12_INPUT_ELEMENT_DESC inputElementDescs[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};
创建纹理描述符堆和上传堆
/*创建2d纹理描述符堆*/
D3D12_RESOURCE_DESC textureDesc = {};
textureDesc.MipLevels = 1;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.Width = TextureWidth;
textureDesc.Height = TextureHeight;
textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
textureDesc.DepthOrArraySize = 1;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&textureDesc,
D3D12_RESOURCE_STATE_COPY_DEST, //作为复制目标,进行复制时需要采用此状态
nullptr,
IID_PPV_ARGS(&m_texture)));
const UINT64 uploadBufferSize = GetRequiredIntermediateSize(m_texture.Get(), 0, 1);
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&textureUploadHeap)));
生成程序性纹理
std::vector<UINT8> D3D12HelloTexture::GenerateTextureData()
{
const UINT rowPitch = TextureWidth * TexturePixelSize;
const UINT cellPitch = rowPitch >> 3; // The width of a cell in the checkboard texture.
const UINT cellHeight = TextureWidth >> 3; // The height of a cell in the checkerboard texture.
const UINT textureSize = rowPitch * TextureHeight;
std::vector<UINT8> data(textureSize);
UINT8* pData = &data[0];
for (UINT n = 0; n < textureSize; n += TexturePixelSize)
{
UINT x = n % rowPitch;
UINT y = n / rowPitch;
UINT i = x / cellPitch;
UINT j = y / cellHeight;
if (i % 2 == j % 2)
{
pData[n] = 0x00; // R
pData[n + 1] = 0x00; // G
pData[n + 2] = 0x00; // B
pData[n + 3] = 0xff; // A
}
else
{
pData[n] = 0xff; // R
pData[n + 1] = 0xff; // G
pData[n + 2] = 0xff; // B
pData[n + 3] = 0xff; // A
}
}
return data;
}
std::vector<UINT8> texture = GenerateTextureData();
将纹理通过上传堆复制到默认堆
D3D12_SUBRESOURCE_DATA textureData = {};
textureData.pData = &texture[0]; //指向包含子资源数据的内存块
textureData.RowPitch = TextureWidth * TexturePixelSize; //子资源一行所占的字节数
textureData.SlicePitch = textureData.RowPitch * TextureHeight; //子资源一个完整切片所占的字节数.该参数针对3d纹理
UpdateSubresources(
m_commandList.Get(), //命令列表
m_texture.Get(),
textureUploadHeap.Get(),
0,
0,
1,
&textureData);
//资源状态转换,转换为该资源与像素着色器一起使用
m_commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_texture.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
描述创建着色器资源视图
/* Describe and create a SRV for the texture */
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = textureDesc.Format;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
m_device->CreateShaderResourceView(m_texture.Get(), &srvDesc, m_srvHeap->GetCPUDescriptorHandleForHeapStart());
关闭并执行命令列表
ThrowIfFailed(m_commandList->Close());
ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
m_commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
渲染
填充命令列表
设置描述符堆
ID3D12DescriptorHeap* ppHeaps[] = { m_srvHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
设置根描述符表
m_commandList->SetGraphicsRootDescriptorTable(0, m_srvHeap->GetGPUDescriptorHandleForHeapStart());
指定rtv描述符堆首个句柄的地址
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_rtvHeap->GetCPUDescriptorHandleForHeapStart(), m_frameIndex, m_rtvDescriptorSize);
输出
reference
原文链接: https://www.cnblogs.com/chenglixue/p/17123206.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/318261
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!