Как преобразовать массив 2D RGB в файл dds с помощью C ++? - PullRequest
0 голосов
/ 27 мая 2020

У меня есть 2D-массив значений RGB, которые представляют нарисованные вершины плоскости. Я хотел бы сохранить окончательные цвета вершин плоскости в файле .dds, чтобы позже можно было загрузить файл .dds как текстуру.

Как я могу подойти к этому?

1 Ответ

1 голос
/ 28 мая 2020

Спасибо Чаку в комментариях, я обнаружил, что это решение работает для меня. Вероятно, будут внесены улучшения. Подход можно разбить на несколько шагов.

Первый шаг - это захват контекста устройства и устройства D3D, используемого для рендеринга, и установка правильного описания текстуры, которое будет использоваться при создании текстуры, которая будет захвачена с помощью SaveDDSTextureToFile ( ScreenGrab ). Приведенное ниже описание работает, когда каждое число с плавающей запятой содержит четыре байтовых значения для каждого цвета и для значения альфа.

void DisplayChunk::SaveVertexColours(std::shared_ptr<DX::DeviceResources> DevResources)
{
    // Setup D3DDeviceContext and D3DDevice
    auto devicecontext = DevResources->GetD3DDeviceContext();
    auto device = DevResources->GetD3DDevice();
    // Create Texture2D and Texture2D Description
    ID3D11Texture2D* terrain_texture;
    D3D11_TEXTURE2D_DESC texture_desc;
    // Set up a texture description 
    texture_desc.Width = TERRAINRESOLUTION;
    texture_desc.Height = TERRAINRESOLUTION;
    texture_desc.MipLevels = texture_desc.ArraySize = 1;
    texture_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
    texture_desc.SampleDesc.Count = 1;
    texture_desc.SampleDesc.Quality = 0;
    texture_desc.Usage = D3D11_USAGE_DYNAMIC;
    texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    texture_desc.MiscFlags = 0;

Шаг второй - создать вектор поплавков и заполнить его соответствующими значениями RGBA. Причина, по которой я использовал вектор, заключалась в том, что для удобства вставлял отдельные значения с плавающей запятой для R, G, B и A на каждой итерации. Таким образом, в каждой позиции вершины вы можете sh вернуть необходимые шестнадцать байтовых значений (по четыре из каждого числа с плавающей запятой, как описано выше).

    // Create vertex colour vector
    std::vector<float> colour_vector;
    for (int i = 0; i < TERRAINRESOLUTION; i++) {
        for (int j = 0; j < TERRAINRESOLUTION; j++) {
            colour_vector.push_back((float)m_terrainGeometry[i][j].color.x);
            colour_vector.push_back((float)m_terrainGeometry[i][j].color.y);
            colour_vector.push_back((float)m_terrainGeometry[i][j].color.z);
            colour_vector.push_back((float)m_terrainGeometry[i][j].color.w);
        }
    }

Шаг третий - заполнить буфер значениями вершинного RGBA. Размер буфера должен быть равен общему количеству байтов, необходимых для хранения, что составляет четыре байта на число с плавающей запятой, четыре с плавающей точкой на вершину и вершины TERRAINTRESOLUTION * TERRAINTRESOLUTION. Пример ландшафта 10 x 10: 4 (байта) x 4 (числа с плавающей точкой) x 10 (ширина) x 10 (высота) = 1600 байт для хранения RGBA каждой вершины.

    // Initialise buffer parameters
    const int components = 4;
    const int length = components * TERRAINRESOLUTION * TERRAINRESOLUTION;
    // Fill buffer with vertex colours
    float* buffer = new float[length * sizeof(float)];
    for (int i = 0; i < length; i++)
        buffer[i] = colour_vector[i];

Последний шаг - создание данных текстуры с использованием содержимого буфера, созданного выше. Для pSysMem требуется указатель на буфер, используемый в качестве данных инициализации. SysMemPitch должен быть установлен равным размеру одной строки. Используя CreateTexture2D, можно создать новую текстуру, используя сохраненные байтовые значения. SaveDDSTextureToFile позволяет сохранить ресурс текстуры во внешний файл .dds. Не забудьте удалить буфер после использования.

    // Set the texture data using the buffer contents
    D3D11_SUBRESOURCE_DATA texture_data;
    texture_data.pSysMem = (void*)buffer;
    texture_data.SysMemPitch = TERRAINRESOLUTION * components * sizeof(float);
    // Create the texture using the terrain colour data
    device->CreateTexture2D(&texture_desc, &texture_data, &terrain_texture);
    // Save the texture to a .dds file
    HRESULT hr = SaveDDSTextureToFile(devicecontext, terrain_texture, L"terrain_output.dds");
    // Delete the buffer
    delete[] buffer;
}

Некоторые ресурсы, которые я использовал при внедрении:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...