填充texture3d切片明智

时间:2016-10-25 12:19:38

标签: c++ directx-11

我尝试用2d图像填充texture3D切片。 我的结果只能让我回到6张图片中的第一张,就像你在这张照片中看到的那样:

3D cube with the texture3D texture

要确保它不是像错误的uvw坐标那样的渲染问题我还会给你uvw坐标的图片:

uvw coordinates of the 3d cube

这里是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 使用另一个命令,或者至少以某种方式更改参数。 我也没有在互联网上找到一些例子。 先谢谢你了

1 个答案:

答案 0 :(得分:2)

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

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

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

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

D3D11_MAPPED_SUBRESOURCE.RowPitch

切片中的每个图像在子资源中一个接一个地布置D3D11_MAPPED_SUBRESOURCE.DepthPitch的间距,切片的总大小(以字节为单位)为 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; } }

例如,这里有一些来自DirectXTex的代码,因为它更容易阅读。它从捕获的3D体积纹理中读取数据,但填充纹理时逻辑相同。

findViewById