如何使用 UpdateSubResource 更新 Direct3d 中的纹理

How to use UpdateSubresource to update the texture in Direct3d

本文关键字:纹理 Direct3d 更新 何使用 UpdateSubResource      更新时间:2023-10-16

我的CreateDeviceResources方法中有以下代码:(该方法在初始调用一次)。

我需要做什么来创建更改纹理的方法?void SetTexture(...纹理输入...

每次需要更改纹理时,我是否需要运行下面的代码? 或者我可以以某种方式更改内存中的一些数据吗?

我发现我想使用 ID3D11DeviceContext::UpdateSubresource,但找不到如何使用它的示例。

  auto textureData = reader->ReadData("SIn.Win8\texturedata.bin");
        D3D11_SUBRESOURCE_DATA textureSubresourceData = {0};
        textureSubresourceData.pSysMem = textureData->Data;
        // Specify the size of a row in bytes, known a priori about the texture data.
        textureSubresourceData.SysMemPitch = 1024;
        // As this is not a texture array or 3D texture, this parameter is ignored.
        textureSubresourceData.SysMemSlicePitch = 0;
        // Create a texture description from information known a priori about the data.
        // Generalized texture loading code can be found in the Resource Loading sample.
        D3D11_TEXTURE2D_DESC textureDesc = {0};
        textureDesc.Width = 256;
        textureDesc.Height = 256;
        textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
        textureDesc.Usage = D3D11_USAGE_DEFAULT;
        textureDesc.CPUAccessFlags = 0;
        textureDesc.MiscFlags = 0;
        // Most textures contain more than one MIP level.  For simplicity, this sample uses only one.
        textureDesc.MipLevels = 1;
        // As this will not be a texture array, this parameter is ignored.
        textureDesc.ArraySize = 1;
        // Don't use multi-sampling.
        textureDesc.SampleDesc.Count = 1;
        textureDesc.SampleDesc.Quality = 0;
        // Allow the texture to be bound as a shader resource.
        textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
        ComPtr<ID3D11Texture2D> texture;
        DX::ThrowIfFailed(
            m_d3dDevice->CreateTexture2D(
                &textureDesc,
                &textureSubresourceData,
                &texture
                )
            );
        // Once the texture is created, we must create a shader resource view of it
        // so that shaders may use it.  In general, the view description will match
        // the texture description.
        D3D11_SHADER_RESOURCE_VIEW_DESC textureViewDesc;
        ZeroMemory(&textureViewDesc, sizeof(textureViewDesc));
        textureViewDesc.Format = textureDesc.Format;
        textureViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
        textureViewDesc.Texture2D.MipLevels = textureDesc.MipLevels;
        textureViewDesc.Texture2D.MostDetailedMip = 0;
        ComPtr<ID3D11ShaderResourceView> textureView;
        DX::ThrowIfFailed(
            m_d3dDevice->CreateShaderResourceView(
                texture.Get(),
                &textureViewDesc,
                &textureView
                )
            );
        // Once the texture view is created, create a sampler.  This defines how the color
        // for a particular texture coordinate is determined using the relevant texture data.
        D3D11_SAMPLER_DESC samplerDesc;
        ZeroMemory(&samplerDesc, sizeof(samplerDesc));
        samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
        // The sampler does not use anisotropic filtering, so this parameter is ignored.
        samplerDesc.MaxAnisotropy = 0;
        // Specify how texture coordinates outside of the range 0..1 are resolved.
        samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
        samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
        samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
        // Use no special MIP clamping or bias.
        samplerDesc.MipLODBias = 0.0f;
        samplerDesc.MinLOD = 0;
        samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
        // Don't use a comparison function.
        samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
        // Border address mode is not used, so this parameter is ignored.
        samplerDesc.BorderColor[0] = 0.0f;
        samplerDesc.BorderColor[1] = 0.0f;
        samplerDesc.BorderColor[2] = 0.0f;
        samplerDesc.BorderColor[3] = 0.0f;
        ComPtr<ID3D11SamplerState> sampler;
        DX::ThrowIfFailed(
            m_d3dDevice->CreateSamplerState(
                &samplerDesc,
                &sampler
                )
            );

如果要在运行时更新相同的纹理,则需要使用 Map

地图类型需要D3D11_MAP_WRITE_DISCARD

此外,您的纹理需要使用动态标志而不是默认标志创建,并且需要将 cpu 访问标志设置为 D3D11_CPU_ACCESS_WRITE

如果允许您访问D3D11_MAPPED_SUBRESOURCE,并且您可以使用 pData 设置新数据

根据

具体情况,重新创建纹理可能会更好,这是根据具体情况进行的(如果纹理经常更改,动态很好)