我尝试用2d图像明智地填充texture3D切片。
我的结果只给了我6张图片中的第一张,就像这张图片所示:

c++ - 明智地填充texture3d切片-LMLPHP

为确保它不是像错误的uvw坐标之类的渲染问题,我还给您提供了uvw坐标的图片:

c++ - 明智地填充texture3d切片-LMLPHP

这是创建texture3d的代码:

if (ETextureType::Texture3D == TextureType)
{
    ID3D11Texture3D* pTexture3D = nullptr;
    D3D11_TEXTURE3D_DESC TextureDesc;
    ZeroMemory(&TextureDesc, sizeof(TextureDesc));
    TextureDesc.Width = nWidth;
    TextureDesc.Height = nHeight;
    TextureDesc.MipLevels = nMipMaps;
    TextureDesc.Depth = nDepth;
    TextureDesc.Usage = D3D11_USAGE_DEFAULT;
    TextureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;

    switch (TextureFormat)
    {
        case ETextureFormat::R8G8B8A8:
        {
            TextureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
        }
        break;

        case ETextureFormat::R32FG32FB32FA32F:
        {
            TextureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
        }
        break;

        default:
        DebugAssertOnce(UNKNOWN_TEXTURE_FORMAT);
    }

    HRESULT hr = m_pD3D11Device->CreateTexture3D(&TextureDesc, nullptr, &pTexture3D);

    if (FAILED(hr))
    {
        DebugAssertOnce(UNABLE_TO_CREATE_TEXTURE);
        return false;
    }

    if (bCreateShaderResourceView)
    {
        D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
        ZeroMemory(&SRVDesc, sizeof(SRVDesc));

        SRVDesc.Format = TextureDesc.Format;
        SRVDesc.Texture3D.MipLevels = TextureDesc.MipLevels;
        SRVDesc.Texture3D.MostDetailedMip = 0;
        SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
        hr = m_pD3D11Device->CreateShaderResourceView(pTexture3D, &SRVDesc, &pShaderResourceView);

        if (FAILED(hr))
        {
            pTexture3D->Release();

            DebugAssertOnce(UNABLE_TO_CREATE_SHADER_RESOURCE_VIEW);
            return false;
        }
    }

    else if (bCreateRenderTargetView)
    {
        ID3D11RenderTargetView* pRenderTargetView = nullptr;

        hr = m_pD3D11Device->CreateRenderTargetView(pTexture3D, nullptr, &pRenderTargetView);

        if (FAILED(hr))
        {
            pShaderResourceView->Release();
            pTexture3D->Release();

            DebugAssertOnce(UNABLE_TO_CREATE_RENDERTARGET_VIEW);
            return false;
        }

        pView = pRenderTargetView;
    }
    *ppTexture = new CTextureDX11(TextureType, pTexture3D, pShaderResourceView, pView);
    return true;
}


以及填充部分:

bool CGraphicsDriverDX11::CreateTexture3DFromImageBuffers(CTexture** ppTexture, const std::vector<CImageBuffer*>* pvecImageBuffers)
{
    uint32_t nWidth = pvecImageBuffers->front()->GetWidth();
    uint32_t nHeight = pvecImageBuffers->front()->GetHeight();

    uint32_t nMipMapLevels = 1;

    bool bRet = CreateTexture(ppTexture, nWidth, nHeight, ETextureType::Texture3D, ETextureFormat::R8G8B8A8, nMipMapLevels, false, true, false, static_cast<UINT>(pvecImageBuffers->size()));

    if (bRet)
    {
        ID3D11Texture3D* pD3DTexture = static_cast<ID3D11Texture3D*>((*ppTexture)->GetTexture());

        for (size_t nImageBuffer = 0; nImageBuffer < pvecImageBuffers->size(); ++nImageBuffer)
        {
            uint32_t nIndex = D3D11CalcSubresource(static_cast<UINT>(nImageBuffer), 0, 1);

            m_pD3D11DeviceContext->UpdateSubresource(pD3DTexture, nIndex, nullptr, pvecImageBuffers->at(nImageBuffer)->GetData(), nWidth * 4, 0);

        }
    }

    return bRet;
}


我尝试了很多……例如,我将此代码更改为texture2DArray,并且运行良好。所以错误不是我的CImageBuffer类。而且nDepth变量具有正确的值...我想我必须对UpdateSubresource使用另一个命令,或者至少以某种方式更改参数。
我也没有在互联网上找到一些例子。
谢谢高级

最佳答案

切片中的所有深度纹理在单个子资源中并排放置。您还需要针对给定的miplevel计算切片中存在多少个深度图像。

这为您提供了包含整个切片的子资源索引:

D3D11CalcSubresource(level, 0, mipLevels);


对于给定的miplevel,这将为您提供切片中的图像数量:

std::max(depth >> level, 1);


切片中的每个图像的节距D3D11_MAPPED_SUBRESOURCE.RowPitch都在子资源中一个接一个地排列,切片的总字节大小为D3D11_MAPPED_SUBRESOURCE.DepthPitch

例如,以下是DirectXTex中的一些代码,经过精简后使其更易于阅读。它正在从捕获的3D体积纹理中读取数据,但填充纹理时的逻辑是相同的。

    if (metadata.IsVolumemap())
    {
        assert(metadata.arraySize == 1);

        size_t height = metadata.height;
        size_t depth = metadata.depth;

        for (size_t level = 0; level < metadata.mipLevels; ++level)
        {
            UINT dindex = D3D11CalcSubresource(level, 0, metadata.mipLevels);

            D3D11_MAPPED_SUBRESOURCE mapped;
            HRESULT hr = pContext->Map(pSource, dindex, D3D11_MAP_READ, 0, &mapped);
            if (FAILED(hr))
                // error

            auto pslice = reinterpret_cast<const uint8_t*>(mapped.pData);

            size_t lines = ComputeScanlines(metadata.format, height);
            // For uncompressed images, lines == height

            for (size_t slice = 0; slice < depth; ++slice)
            {
                const Image* img = result.GetImage(level, 0, slice);

                const uint8_t* sptr = pslice;
                uint8_t* dptr = img->pixels;
                for (size_t h = 0; h < lines; ++h)
                {
                    size_t msize = std::min<size_t>(img->rowPitch, mapped.RowPitch);
                    memcpy_s(dptr, img->rowPitch, sptr, msize);
                    sptr += mapped.RowPitch;
                    dptr += img->rowPitch;
                }

                pslice += mapped.DepthPitch;
            }

            pContext->Unmap(pSource, dindex);

            if (height > 1)
                height >>= 1;
            if (depth > 1)
                depth >>= 1;
        }
    }

关于c++ - 明智地填充texture3d切片,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40239814/

10-15 06:55