【问题标题】:C++ : DirectX Texture is Misaligned/ShiftedC++:DirectX 纹理未对齐/移位
【发布时间】:2016-10-08 07:44:40
【问题描述】:

我正在尝试用纹理渲染一个正方形。有谁知道为什么这个纹理会出现偏移或未对齐?

这是它的外观:http://imgur.com/siCQXXT

问题如下:http://imgur.com/rj6tHcX

auto createVSTask = loadVSTask.then([this](const std::vector<byte>& fileData) {
    DX::ThrowIfFailed(
        m_deviceResources->GetD3DDevice()->CreateVertexShader(
            &fileData[0],
            fileData.size(),
            nullptr,
            &m_vertexShader
        )
    );

    static const D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };

    DX::ThrowIfFailed(
        m_deviceResources->GetD3DDevice()->CreateInputLayout(
            vertexDesc,
            ARRAYSIZE(vertexDesc),
            &fileData[0],
            fileData.size(),
            &m_inputLayout
        )
    );
});

auto createPSTask = loadPSTask.then([this](const std::vector<byte>& fileData) {
    DX::ThrowIfFailed(
        m_deviceResources->GetD3DDevice()->CreatePixelShader(
            &fileData[0],
            fileData.size(),
            nullptr,
            &m_pixelShader
        )
    );

    CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ModelViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER);
    DX::ThrowIfFailed(
        m_deviceResources->GetD3DDevice()->CreateBuffer(
            &constantBufferDesc,
            nullptr,
            &m_constantBuffer
        )
    );
});

auto createPrimitiveTask = (createPSTask && createVSTask).then([this]() {

    const VertexPositionColor cubeVertices[] =
    {
        { DirectX::XMFLOAT3(-1.0f, -1.0f, 0.0f),  DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 0.0f) },
        { DirectX::XMFLOAT3(1.0f, -1.0f, 0.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 0.0f) },
        { DirectX::XMFLOAT3(1.0f, 1.0f, 0.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 1.0f) },
        { DirectX::XMFLOAT3(-1.0f, 1.0f, 0.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 1.0f) },
    };

    static const unsigned short cubeIndices[] =
    {
        0, 1, 2,
        0, 2, 3
    };

    m_indexCount = ARRAYSIZE(cubeIndices);

    D3D11_SUBRESOURCE_DATA vertexBufferData = { 0 };
    vertexBufferData.pSysMem = cubeVertices;
    vertexBufferData.SysMemPitch = 0;
    vertexBufferData.SysMemSlicePitch = 0;
    CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(cubeVertices), D3D11_BIND_VERTEX_BUFFER);
    DX::ThrowIfFailed(
        m_deviceResources->GetD3DDevice()->CreateBuffer(
            &vertexBufferDesc,
            &vertexBufferData,
            &m_vertexBuffer
        )
    );

    D3D11_SUBRESOURCE_DATA indexBufferData = { 0 };
    indexBufferData.pSysMem = cubeIndices;
    indexBufferData.SysMemPitch = 0;
    indexBufferData.SysMemSlicePitch = 0;
    CD3D11_BUFFER_DESC indexBufferDesc(sizeof(cubeIndices), D3D11_BIND_INDEX_BUFFER);
    DX::ThrowIfFailed(
        m_deviceResources->GetD3DDevice()->CreateBuffer(
            &indexBufferDesc,
            &indexBufferData,
            &m_indexBuffer
        )
    );
});

auto loadTDTask = DX::ReadDataAsync(m_textureFile);

auto createSubresourceTask = loadTDTask.then([=](std::vector<byte>& textureData) {

    D3D11_SUBRESOURCE_DATA textureSubresourceData = { 0 };
    textureSubresourceData.pSysMem = &textureData[0];
    textureSubresourceData.SysMemPitch = 1024;
    textureSubresourceData.SysMemSlicePitch = 0;

    D3D11_TEXTURE2D_DESC textureDesc = { 0 };
    textureDesc.Width = 256;
    textureDesc.Height = 256;
    textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    textureDesc.Usage = D3D11_USAGE_DEFAULT;
    textureDesc.CPUAccessFlags = 0;
    textureDesc.ArraySize = 1;
    textureDesc.SampleDesc.Count = 1;
    textureDesc.SampleDesc.Quality = 0;
    textureDesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
    textureDesc.MipLevels = 0;
    textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;

    DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D(
        &textureDesc,
        nullptr,
        &m_texture
    );

    if (m_texture != NULL)
    {
        D3D11_SHADER_RESOURCE_VIEW_DESC textureViewDesc;
        ZeroMemory(&textureViewDesc, sizeof(textureViewDesc));
        textureViewDesc.Format = textureDesc.Format;
        textureViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
        textureViewDesc.Texture2D.MipLevels = -1;
        textureViewDesc.Texture2D.MostDetailedMip = 0;

        DX::ThrowIfFailed(
            m_d3dDevice->CreateShaderResourceView(
            m_texture.Get(),
            &textureViewDesc,
            &m_textureView
            )
        );

        context->UpdateSubresource(m_texture.Get(), 0, nullptr, &textureData[0], textureSubresourceData.SysMemPitch, textureDesc.Width);
        context->GenerateMips(m_textureView.Get());
    }
}

D3D11_SAMPLER_DESC samplerDesc;
ZeroMemory(&samplerDesc, sizeof(samplerDesc));
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.MaxAnisotropy = 0;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
samplerDesc.BorderColor[0] = 0.0f;
samplerDesc.BorderColor[1] = 0.0f;
samplerDesc.BorderColor[2] = 0.0f;
samplerDesc.BorderColor[3] = 0.0f;

DX::ThrowIfFailed(
    m_d3dDevice->CreateSamplerState(
    &samplerDesc,
    &m_sampler
    )
);

【问题讨论】:

  • 你能告诉我们顶点/索引缓冲区吗?谢谢!
  • 好的,我更新了帖子里的源代码。
  • 你可以尝试使用clamp纹理寻址来判断是uv问题,还是纹理更新问题。另外,UpdateSubresource 中的最后一个参数应该是 0,而不是宽度,因为它是一个深度间距,而你这里没有。
  • 如果我指定D3D11_TEXTURE_ADDRESS_CLAMP,那么默认渲染的图像没有变化。如果我将 UV 坐标的长度/宽度增加到 1.5 并指定 D3D11_TEXTURE_ADDRESS_BORDER,那么它看起来像 this。如果我将 UV 坐标的长度/宽度增加到 1.5 并指定 D3D11_TEXTURE_ADDRESS_CLAMP,那么它看起来像 this
  • @436c75656c657373Programmer 意思是你的贴图上传错了。因为纹理看起来大部分是正确的,所以音高是正确的,但是您可能忘记从 textureData 中删除文件头?在任何情况下,在你的代码中使用常量,比如 256 或 1024 假设传入的数据是兼容的是一种不好的做法,你应该转发值以防止任何不匹配。

标签: c++ directx directx-11


【解决方案1】:

首先,您确认钳位实验没有状态或几何问题,其次,您说您使用的是 DDS 图像,这是关键。

根据您的代码,图像是 256 宽 RGBA8,因为石头是其中的 1/8,这意味着它们覆盖 32*4 = 128 字节。足够接近,DDS header 是 124 字节,当你没有 dx10 块时,它解释了为什么图像是这样偏移的。

您所要做的就是跳过标题并仅将图像数据传递给UpdateSubResource。我邀请您查看DDS reference 以了解文件的布局,以便您可以阅读大小、格式、正确跳到数据的开头,还可以利用 DDS 存储压缩格式,并包含mip 预先映射不使用 GenerateMips 这是不好的做法。

【讨论】:

  • 要跳过 DDS 标头,在读入 DDS 文件中的二进制数据时是否应该跳过前 128 个字节?
  • 我知道效率不高但我的目标是创建一个可以自动生成mipmap的测试应用,所以需要GenerateMips。
  • DDS header 有一个已知的大小,并且可能还包含可选的 dx10 额外块,要知道跳过多少,您需要阅读 header 并测试里面的格式标签。这里没有一个始终有效的魔法常数。
  • 此外,即使您的目标是在运行时生成 mipmap,GenerateMips 仍然是个坏主意,首先,您无法控制该过程,如果您想要对法线贴图进行锐化或重新归一化怎么办,其次,您不能使用压缩格式,最后,您必须使用 rendertarget 绑定,这会降低纹理读取效率,如果您想自己生成 mips,则需要使用 RT 或 UAV 的临时缓冲区,编写计算或像素着色器生成它们,然后使用 CopyResource 初始化具有只读绑定的正确纹理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-02
  • 1970-01-01
  • 1970-01-01
  • 2013-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多