首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在DirectX12 & C++中渲染纹理?这个过程是什么?

如何在DirectX12 & C++中渲染纹理?这个过程是什么?
EN

Stack Overflow用户
提问于 2021-05-15 16:31:54
回答 1查看 2.4K关注 0票数 2

我一直在努力弄清楚如何在DX12中将整个场景呈现为纹理。我知道如何在OpenGL中做到这一点,但我在DirectX12中找出了困难。另外,网上没有多少关于它是如何做到的资源。

(目前,我们在场景中使用了三维模型绘制,并应用了纹理)

有人能告诉我一些资源,我可以用这些资源来学习渲染目标和渲染到DX12中的纹理吗?或者有什么好网站?

任何帮助都是非常感谢的。

你好,查理

EN

Stack Overflow用户

发布于 2021-05-16 04:25:55

OpenGL更像Direct3D 11,其中Direct3D 12和Vulkan在设计/使用以及有效使用它们所需的图形知识水平上更加相似。因此,在进入Direct3D 12呈现之前,您可能会发现从Direct3D 11开始比较容易。概念和HLSL编程在11到12之间都是非常相似的,所以它可以是一个很好的起点。

对DirectX 12最需要了解的是,它使应用程序(即程序员)负责Direct3D 11运行时处理的许多方面: CPU/GPU同步、内存管理、资源调度等。DirectX 12的目的是为有经验的图形程序员提供更多的控制,从而能够在同样复杂的渲染过程中实现更高级别的CPU端性能。然而,对于刚接触过图形或DirectX的人来说,这种额外的控制和责任可能会让人不堪重负。在DX12中,编写“在我的机器上工作”但不会在其他人的机器上运行甚至崩溃的东西要容易得多。

提供了,一些从Direct3D 12开始的很好的资源:

  • 这里为DirectX提供了一个新的“登陆页面”,为DirectX 12开发提供了许多有用的链接和资源:https://devblogs.microsoft.com/directx/landing-page/
  • 由DirectX图形小组编写的官方DirectX 12示例位于DirectX-图形学-样本
  • 编写的公共示例位于Xbox样品。特别是,请参阅IntroGraphics示例,它提供了DX11和DX12两种形式的许多基本示例。
  • DirectX工具包是一个开放源代码的C++库,它为Direct3D开发提供了帮助。有DirectX 11DirectX 12两种版本。如果您首先学习DX 11版本,那么从那里迁移到DX 12非常简单,因为它在您学习新API时为您处理了许多“家务”任务。

关于DirectX 12中的“呈现到纹理”的问题,有一些特定的示例需要查看:

第二种方法使用这个助手类H / cpp

代码语言:javascript
运行
复制
    class RenderTexture
    {
    public:
        RenderTexture(DXGI_FORMAT format) noexcept;

        void SetDevice(_In_ ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor);

        void SizeResources(size_t width, size_t height);

        void ReleaseDevice() noexcept;

        void TransitionTo(_In_ ID3D12GraphicsCommandList* commandList, D3D12_RESOURCE_STATES afterState);

        void BeginScene(_In_ ID3D12GraphicsCommandList* commandList)
        {
            TransitionTo(commandList, D3D12_RESOURCE_STATE_RENDER_TARGET);
        }

        void EndScene(_In_ ID3D12GraphicsCommandList* commandList)
        {
            TransitionTo(commandList, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
        }

        void SetClearColor(DirectX::FXMVECTOR color)
        {
            DirectX::XMStoreFloat4(reinterpret_cast<DirectX::XMFLOAT4*>(m_clearColor), color);
        }

        ID3D12Resource* GetResource() const noexcept { return m_resource.Get(); }
        D3D12_RESOURCE_STATES GetCurrentState() const noexcept { return m_state; }

        void SetWindow(const RECT& rect);

        DXGI_FORMAT GetFormat() const noexcept { return m_format; }

    private:
        Microsoft::WRL::ComPtr<ID3D12Device>                m_device;
        Microsoft::WRL::ComPtr<ID3D12Resource>              m_resource;
        D3D12_RESOURCE_STATES                               m_state;
        D3D12_CPU_DESCRIPTOR_HANDLE                         m_srvDescriptor;
        D3D12_CPU_DESCRIPTOR_HANDLE                         m_rtvDescriptor;
        float                                               m_clearColor[4];

        DXGI_FORMAT                                         m_format;

        size_t                                              m_width;
        size_t                                              m_height;
    };
代码语言:javascript
运行
复制
RenderTexture::RenderTexture(DXGI_FORMAT format) noexcept :
    m_state(D3D12_RESOURCE_STATE_COMMON),
    m_srvDescriptor{},
    m_rtvDescriptor{},
    m_clearColor{},
    m_format(format),
    m_width(0),
    m_height(0)
{
}

void RenderTexture::SetDevice(_In_ ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE srvDescriptor, D3D12_CPU_DESCRIPTOR_HANDLE rtvDescriptor)
{
    if (device == m_device.Get()
        && srvDescriptor.ptr == m_srvDescriptor.ptr
        && rtvDescriptor.ptr == m_rtvDescriptor.ptr)
        return;

    if (m_device)
    {
        ReleaseDevice();
    }

    {
        D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport = { m_format, D3D12_FORMAT_SUPPORT1_NONE, D3D12_FORMAT_SUPPORT2_NONE };
        if (FAILED(device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &formatSupport, sizeof(formatSupport))))
        {
            throw std::runtime_error("CheckFeatureSupport");
        }

        UINT required = D3D12_FORMAT_SUPPORT1_TEXTURE2D | D3D12_FORMAT_SUPPORT1_RENDER_TARGET;
        if ((formatSupport.Support1 & required) != required)
        {
#ifdef _DEBUG
            char buff[128] = {};
            sprintf_s(buff, "RenderTexture: Device does not support the requested format (%u)!\n", m_format);
            OutputDebugStringA(buff);
#endif
            throw std::runtime_error("RenderTexture");
        }
    }

    if (!srvDescriptor.ptr || !rtvDescriptor.ptr)
    {
        throw std::runtime_error("Invalid descriptors");
    }

    m_device = device;

    m_srvDescriptor = srvDescriptor;
    m_rtvDescriptor = rtvDescriptor;
}

void RenderTexture::SizeResources(size_t width, size_t height)
{
    if (width == m_width && height == m_height)
        return;

    if (m_width > UINT32_MAX || m_height > UINT32_MAX)
    {
        throw std::out_of_range("Invalid width/height");
    }

    if (!m_device)
        return;

    m_width = m_height = 0;

    auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);

    D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Tex2D(m_format,
        static_cast<UINT64>(width),
        static_cast<UINT>(height),
        1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);

    D3D12_CLEAR_VALUE clearValue = { m_format, {} };
    memcpy(clearValue.Color, m_clearColor, sizeof(clearValue.Color));

    m_state = D3D12_RESOURCE_STATE_RENDER_TARGET;

    // Create a render target
    ThrowIfFailed(
        m_device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES,
            &desc,
            m_state, &clearValue,
            IID_GRAPHICS_PPV_ARGS(m_resource.ReleaseAndGetAddressOf()))
    );

    SetDebugObjectName(m_resource.Get(), L"RenderTexture RT");

    // Create RTV.
    m_device->CreateRenderTargetView(m_resource.Get(), nullptr, m_rtvDescriptor);

    // Create SRV.
    m_device->CreateShaderResourceView(m_resource.Get(), nullptr, m_srvDescriptor);

    m_width = width;
    m_height = height;
}

void RenderTexture::ReleaseDevice() noexcept
{
    m_resource.Reset();
    m_device.Reset();

    m_state = D3D12_RESOURCE_STATE_COMMON;
    m_width = m_height = 0;

    m_srvDescriptor.ptr = m_rtvDescriptor.ptr = 0;
}

void RenderTexture::TransitionTo(_In_ ID3D12GraphicsCommandList* commandList, D3D12_RESOURCE_STATES afterState)
{
    TransitionResource(commandList, m_resource.Get(), m_state, afterState);
    m_state = afterState;
}

void RenderTexture::SetWindow(const RECT& output)
{
    // Determine the render target size in pixels.
    auto width = size_t(std::max<LONG>(output.right - output.left, 1));
    auto height = size_t(std::max<LONG>(output.bottom - output.top, 1));

    SizeResources(width, height);
}

你会像这样使用它:

代码语言:javascript
运行
复制
// Setup
m_scene = std::make_unique<DX::RenderTexture>( /* format that matches your resource and your Pipeline State Objects you will use to render */ );
m_scene->SetClearColor( /* color value you use to clear */ );

m_scene->SetDevice(m_device,
    /* CPU descriptor handle for your scene as a SRV texture */,
    /* CPU descriptor handle for your scene as a RTV texture */);

m_scene->SetWindow( /* provide viewport size for your render texture */ );
代码语言:javascript
运行
复制
// Reset command list and allocator.

// Transition the backbuffer target into the correct state to allow for 

// Clear the render texture
CD3DX12_CPU_DESCRIPTOR_HANDLE rtvDescriptor(
        /* CPU descriptor handle for your scene as a RTV texture */
        static_cast<INT>(m_backBufferIndex), m_rtvDescriptorSize);

CD3DX12_CPU_DESCRIPTOR_HANDLE dsvDescriptor(m_dsvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());

m_commandList->OMSetRenderTargets(1, &rtvDescriptor, FALSE, &dsvDescriptor);
m_commandList->ClearRenderTargetView(rtvDescriptor, /* clear color */, 0, nullptr);
m_commandList->ClearDepthStencilView(dsvDescriptor, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);

// Set the viewport and scissor rect.
D3D12_VIEWPORT viewport = { 0.0f, 0.0f, /* width/height of your render texture */, D3D12_MIN_DEPTH, D3D12_MAX_DEPTH };
D3D12_RECT scissorRect = { 0, 0, /* width/height of your render texture */ };
m_commandList->RSSetViewports(1, &viewport);
m_commandList->RSSetScissorRects(1, &scissorRect);

// Tell helper we are starting the render
m_scene->BeginScene(m_commandList);
    
/* Do rendering to m_commandList */

m_scene->EndScene(m_commandList);

在这里,我们已经安排了转换来呈现目标资源状态,填充了所有的绘图调用,然后将一个屏障插入到像素着色器资源状态。此时,您可以使用渲染纹理的SRV的描述符句柄来渲染。与所有DirectX 12一样,在实际关闭命令列表并将其提交以供执行之前,不会发生任何事情。

票数 11
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67548981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档