【问题标题】:DirectX 11 changing the pixel bytesDirectX 11 更改像素字节
【发布时间】:2016-01-27 16:46:44
【问题描述】:

遵循本指南here

我的任务是“通过将像素字节数据设置为 rgb 红色值,使用 map 和 unmap 方法在屏幕上画一条线”。

我有精灵和背景显示,但不知道如何获取数据。

我也试过这样做:

//Create device
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
desc.Width = 500;
desc.Height = 300;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;


m_d3dDevice->CreateTexture2D(&desc, nullptr, &texture);
m_d3dDevice->CreateShaderResourceView(texture, 0, &textureView);

// Render
D3D11_MAPPED_SUBRESOURCE mapped;
m_d3dContext->Map(texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);

data = (BYTE*)mapped.pData;
rows = (BYTE)sizeof(data);

std::cout << "hi" << std::endl;
m_d3dContext->Unmap(texture, 0);

问题是,在这种情况下,数据数组的大小为 0,但有一个指针。这意味着我指向的纹理没有任何数据,或者我没有得到这个?

编辑: 目前我找到了

D3D11_SHADER_RESOURCE_VIEW_DESC desc;
m_background->GetDesc(&desc);
desc.Buffer; // buffer

【问题讨论】:

    标签: visual-c++ directx-11


    【解决方案1】:

    当我搜索如何做到这一点时,我觉得有必要为此创建一个答案。这个问题首先弹出,提供的答案并没有真正为我解决问题,而且也不是我想要的方式......

    在我的程序中,我有一个方法如下。

    void ContentLoader::WritePixelsToShaderIndex(uint32_t *data, int width, int height, int index)
    {
        D3D11_TEXTURE2D_DESC desc = {};
        desc.Width = width;
        desc.Height = height;
        desc.MipLevels = 1;
        desc.ArraySize = 1;
        desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
        desc.SampleDesc.Count = 1;
        desc.SampleDesc.Quality = 0;
        desc.Usage = D3D11_USAGE_DEFAULT;
        desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
        desc.CPUAccessFlags = 0;
        desc.MiscFlags = 0;
    
        D3D11_SUBRESOURCE_DATA initData;
        initData.pSysMem = data;
        initData.SysMemPitch = width * 4;
        initData.SysMemSlicePitch = width * height * 4;
    
        Microsoft::WRL::ComPtr<ID3D11Texture2D> tex;
    
        Engine::device->CreateTexture2D(&desc, &initData, tex.GetAddressOf());
    
        Engine::device->CreateShaderResourceView(tex.Get(), NULL, ContentLoader::GetTextureAddress(index));
    }
    

    然后使用下面的代码,我测试了用白线绘制了一个蓝色正方形。它工作得很好。我遇到的问题是在查看 WICTextureLoader 类后设置 System Mem Slice 和 Mem Pitch,我能够弄清楚数据是如何存储的。所以看起来

    MemPitch = 行的大小(以字节为单位)。 MemSlice = 图像总像素大小(以字节为单位)。

    const int WIDTH = 200;
    const int HEIGHT = 200;
    const uint32_t RED = 255 | (0 << 8) | (0 << 16) | (255 << 24);
    const uint32_t WHITE = 255 | (255 << 8) | (255 << 16) | (255 << 24);
    const uint32_t BLUE = 0 | (0 << 8) | (255 << 16) | (255 << 24);
    uint32_t *buffer = new uint32_t[WIDTH * HEIGHT];
    bool flip = false;
    for (int X = 0; X < WIDTH; ++X)
    {
        for (int Y = 0; Y < HEIGHT; ++Y)
        {
            int pixel = X + Y * WIDTH;
            buffer[pixel] = flip ? BLUE : WHITE;
        }
        flip = true;
    }
    
    WritePixelsToShaderIndex(buffer, WIDTH, HEIGHT, 3);
    delete [] buffer;
    

    【讨论】:

      【解决方案2】:

      首先,这些函数中的大多数都返回您忽略的HRESULT 值。这是不安全的,因为您会错过使剩余代码无效的重要错误。您可以根据需要使用if(FAILED(...)),也可以使用ThrowIfFailed,但不能只忽略正常运行的应用程序中的返回值。

      HRESULT hr = m_d3dDevice->CreateTexture2D(&desc, nullptr, &texture);
      if (FAILED(hr))
          // error!
      hr = m_d3dDevice->CreateShaderResourceView(texture, 0, &textureView);
      if (FAILED(hr))
          // error!
      
      // Render
      D3D11_MAPPED_SUBRESOURCE mapped;
      hr = m_d3dContext->Map(texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
      if (FAILED(hr))
          // error!
      

      其次,您应该启用Debug Device 并查找可能会指出失败原因的诊断输出。

      sizeof(data) 总是 4 或 8,因为数据是 BYTE*,即指针的大小。它与数据数组的大小无关。 mapped.pData 指向的锁定缓冲区的大小将是 mapped.RowPitch * desc.Height 字节。

      您必须将像素数据逐行复制到其中。根据格式和其他因素,mapped.RowPitch 不一定是4 * desc.Width--4 字节/像素,因为您使用的是DXGI_FORMAT_B8G8R8A8_UNORM 格式。它应该至少有那么大,但它可以更大以对齐整体尺寸。

      这是伪代码,不一定是一种有效的方法,但是:

      for(UINT y = 0; y < desc.Height; ++y )
      {
          for(UINT x = 0; x < desc.Width; ++x )
          {
              // Find the memory location of the pixel at (x,y)
              int pixel = y * mapped.RowPitch + (x*4)
              BYTE* blue = data[pixel];
              BYTE* green = data[pixel] + 1;
              BYTE* red = data[pixel] + 2;
              BYTE* alpha = data[pixel] + 3;
      
              *blue = /* value between 0 and 255 */;
              *green = /* value between 0 and 255 */;
              *red = /* value between 0 and 255 */;
              *alpha = /* value between 0 and 255 */;
          }
      }
      

      你应该看看DirectXTex,它做了很多这种逐行处理。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多