首页 > 解决方案 > Direct X:如何显示加载到纹理中的图像?

问题描述

我是 DirectX 的新手,并且一直在阅读大量教程和示例,但是我找不到任何有关如何直接显示加载到Texture2D屏幕上的图像的文档。我见过的几乎所有教程都涉及 3D 图形、着色器等。但是,我只想显示纹理的内容。

这是我到目前为止所拥有的:

设备资源.cpp

#include "DeviceResources.h"
#include "Renderer.h"

DeviceResources::DeviceResources()
{

}


HRESULT DeviceResources::CreateDeviceResources(HWND hwnd)
{
    D3D_FEATURE_LEVEL levels[] = {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_12_0,
        D3D_FEATURE_LEVEL_12_1
    };

    UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;

    DXGI_SWAP_CHAIN_DESC swap_chain_desc;
    ZeroMemory(&swap_chain_desc, sizeof(DXGI_SWAP_CHAIN_DESC));

    swap_chain_desc.Windowed = TRUE;
    swap_chain_desc.BufferCount = 2;
    swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;

    swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swap_chain_desc.SampleDesc.Count = 1;
    swap_chain_desc.SampleDesc.Quality = 0;

    swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
    swap_chain_desc.OutputWindow = hwnd;

    Microsoft::WRL::ComPtr<ID3D11Device> device;
    Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
    Microsoft::WRL::ComPtr<IDXGISwapChain> swapChain;

    D3D11CreateDeviceAndSwapChain(
        nullptr,
        D3D_DRIVER_TYPE_HARDWARE,
        nullptr,
        flags,
        levels,
        ARRAYSIZE(levels),
        D3D11_SDK_VERSION,
        &swap_chain_desc,
        swapChain.GetAddressOf(),
        device.GetAddressOf(),
        &m_feature_level,
        context.GetAddressOf()
    );

    device.As(&m_device);
    context.As(&m_context);
    swapChain.As(&m_swapChain);

    cv::directx::ocl::initializeContextFromD3D11Device(m_device.Get());

    auto hdr = Renderer::HDRMetadata();
    m_swapChain->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_HDR10, sizeof(DXGI_HDR_METADATA_HDR10), &hdr);
    m_swapChain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020);

    m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), static_cast<void**>(& m_backBuffer));
    m_backBuffer->GetDesc(&m_bbDesc);

    ZeroMemory(&m_viewport, sizeof(D3D11_VIEWPORT));

    m_viewport.Height = static_cast<float>(m_bbDesc.Height);
    m_viewport.Width = static_cast<float>(m_bbDesc.Width);

    m_viewport.MinDepth = 0;
    m_viewport.MaxDepth = 1;

    m_context->RSSetViewports(1, &m_viewport);
    m_device->CreateRenderTargetView(m_backBuffer.Get(), nullptr, m_renderTargetView.GetAddressOf());

    return S_OK;
}

HRESULT DeviceResources::ConfigureBackBuffer()
{
    m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), static_cast<void**>(& m_backBuffer));
    m_device->CreateRenderTargetView(m_backBuffer.Get(), nullptr, m_renderTargetView.GetAddressOf());

    m_backBuffer->GetDesc(&m_bbDesc);

    ZeroMemory(&m_viewport, sizeof(D3D11_VIEWPORT));

    m_viewport.Height = static_cast<float>(m_bbDesc.Height);
    m_viewport.Width = static_cast<float>(m_bbDesc.Width);

    m_viewport.MinDepth = 0;
    m_viewport.MaxDepth = 1;

    m_context->RSSetViewports(1, &m_viewport);

    return S_OK;
}

HRESULT DeviceResources::ReleaseBackBuffer()
{
    m_renderTargetView.Reset();
    m_backBuffer.Reset();

    m_context->Flush();

    return S_OK;
}

HRESULT DeviceResources::SetFullscreen(bool fullscreen)
{
    m_swapChain->SetFullscreenState(fullscreen, nullptr);
    ReleaseBackBuffer();

    m_swapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
    ConfigureBackBuffer();

    return S_OK;
}

void DeviceResources::Present()
{
    m_swapChain->Present(1, 0);
}

DeviceResources::~DeviceResources()
= default;

渲染器.cpp:

#include "Renderer.h"
#include <utility>
#include <comdef.h>
#include <vector>


Renderer::Renderer(std::shared_ptr<DeviceResources> resources) : m_resources(std::move(resources)), m_frameCount(0)
{
    m_frameCount = 0;
}

HRESULT Renderer::CreateDeviceDependentResources()
{
    return S_OK;
}

HRESULT Renderer::CreateWindowSizeDependentResources()
{
    return S_OK;
}

void Renderer::Update()
{
    //
}

void Renderer::Render()
{
    cv::Mat mat = cv::imread("C:/Users/Richard/Downloads/orig_cave_L.ppm", cv::IMREAD_ANYCOLOR | cv::IMREAD_ANYDEPTH);
    cv::Mat as4channelMat(mat.size(), CV_MAKE_TYPE(mat.depth(), 4));

    int conversion[] = { 0, 0, 1, 1, 2, 2, -1, 3 };
    cv::mixChannels(&mat, 1, &as4channelMat, 1, conversion, 4);

    D3D11_TEXTURE2D_DESC desc;
    desc.Width = 3840;
    desc.Height = 2160;
    desc.MipLevels = desc.ArraySize = 1;
    desc.Format = DXGI_FORMAT_R16G16B16A16_UNORM;
    desc.SampleDesc.Count = 1;
    desc.SampleDesc.Quality = 0;
    desc.Usage = D3D11_USAGE_DEFAULT;
    desc.BindFlags = 0;
    desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
    desc.MiscFlags = 0;

    ID3D11Texture2D* tex = nullptr;

    auto hr = m_resources->GetDevice()->CreateTexture2D(&desc, nullptr, &tex);

    if FAILED(hr)
    {
        _com_error err(hr);
        auto errMsg = err.ErrorMessage();
    }

    try {
        cv::directx::convertToD3D11Texture2D(as4channelMat, tex);
    } catch (cv::Exception& e)
    {
        std::cerr << "ERROR: " << e.msg << std::endl;
        throw e;
    }

auto hr3 = m_resources->m_device->CreateShaderResourceView(tex.Get(), nullptr, m_texture.GetAddressOf());

    if FAILED(hr3)
    {
        _com_error err(hr3);
        auto errMsg = err.ErrorMessage();
    }

    std::unique_ptr<DirectX::SpriteBatch> m_spriteBatch;
    DirectX::SimpleMath::Vector2 m_screenPos, m_origin;

    m_spriteBatch = std::make_unique<DirectX::SpriteBatch>(m_resources->m_context.Get());

    CD3D11_TEXTURE2D_DESC catDesc;
    tex->GetDesc(&catDesc);

    m_origin.x = float(catDesc.Width / 2);
    m_origin.y = float(catDesc.Height / 2);

    m_screenPos.x = m_resources->m_bbDesc.Width / 2.f;
    m_screenPos.y = m_resources->m_bbDesc.Height / 2.f;

    m_spriteBatch->Begin();

    m_spriteBatch->Draw(
        m_texture.Get(), 
        m_screenPos, 
        nullptr, 
        DirectX::Colors::White, 
        0.0f, 
        m_origin
    );

    m_spriteBatch->End();
}

DXGI_HDR_METADATA_HDR10 Renderer::HDRMetadata()
{
//
}


Renderer::~Renderer()
{

}

据我了解,我必须以某种方式创建一个“四边形”,对其应用纹理,然后显示四边形本身。但是,我不确定如何做到这一点,也找不到任何资源来提供帮助。

编辑:鉴于建议,我尝试使用 DirectXTK,特别是SpriteBatch。我遵循了文档中的相关说明,但Draw似乎没有做/显示任何事情。(在Renderer.cpp

标签: c++windowsgraphicsdirectx

解决方案


推荐阅读