Hello Texture

前言

​ 在上一篇已经展示了如何绘制一个2d三角形,此篇将展示如何给这个三角形添加纹理

流程

Hello Texture

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);

输出

image-20230215202931733

reference

https://github.com/microsoft/DirectX-Graphics-Samples

原文链接: https://www.cnblogs.com/chenglixue/p/17123206.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    Hello Texture

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/318261

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月16日 下午3:04
下一篇 2023年2月16日 下午3:04

相关推荐