Я пытаюсь преобразовать каждый кадр моей программы DirectX в YUV (для кодирования видео). Поэтому для каждого кадра сначала нужны значения RGB (A) каждого пикселя. Мне нужно получить их от буфера.DirectX запись данных буфера данных в файл
Поскольку нет glReadPixels в DirectX, я следующее:
- Получить указатель на renderTargetView в BackBuffer и получайте BackBuffer ресурсу
- Cast этот ресурс
ID3D10Texture2D
- Сделайте промежуточную структуру и
CopyResource
texture2D с предыдущего шага.
В этот момент я могу использовать D3DX10SaveTextureToFile
, и эта промежуточная текстура правильно сохранит буферный буфер как изображение.
Однако, я не хочу использовать диск в качестве объезда, я хочу, чтобы получить данные RGB сразу же, так что я сделать следующее:
- Карта постановочной ресурс
- Читать pData отображаемой текстуры для получения значений RGB (A)
Проблема: значения RGB являются мусором. Это пример для пикселя (1,1)
(1, 1) = (-170141183460469230000000000000000000000.000000, -170141183460469230000000000000000000000,000000, -170141183460469230000000000000000000000,000000)
Это особенно странно, потому что используют один и тот же код для сопоставления другой промежуточной текстуры (из другой целевой экранной рендеринга), и этот код прекрасно работает.
Это мой код:
// Get resource pointer to backbuffer
ID3D10Resource *backbufferRes;
m_D3D->GetRenderTargetView()->GetResource(&backbufferRes);
// Cast backbuffer resource to texture2D
ID3D10Texture2D* tempTexture = 0;
backbufferRes->QueryInterface(__uuidof(ID3D10Texture2D),(LPVOID*) &tempTexture);
backbufferRes->Release();
// Get the descriptor of this texture2D
D3D10_TEXTURE2D_DESC descDefault;
tempTexture->GetDesc(&descDefault);
// Create a staging texture desc based on the texture of the backbuffer
D3D10_TEXTURE2D_DESC descStaging;
descStaging = descDefault;
descStaging.Usage = D3D10_USAGE_STAGING;
descStaging.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
descStaging.BindFlags = 0;
// Create the new empty staging texture
ID3D10Texture2D *texture = 0;
m_D3D->GetDevice()->CreateTexture2D(&descStaging, NULL, &texture);
// Copy the backbuffer texture data (tempTexture) to the staging texture (texture)
m_D3D->GetDevice()->CopyResource(texture, tempTexture);
// This call works perfectly, image is correct!
// D3DX10SaveTextureToFile(texture, D3DX10_IFF_BMP, L"D:\\img.bmp");
// We want to avoid disk access, so instead let's map the texture and read its RGB data
D3D10_MAPPED_TEXTURE2D mappedTexture;
hr = texture->Map(D3D10CalcSubresource(0, 0, 1), D3D10_MAP_READ, 0, &mappedTexture);
FLOAT* m_pBits = (FLOAT*) malloc(4 * descStaging.Width * descStaging.Height * sizeof(FLOAT));
if(!FAILED(hr)) {
memcpy(m_pBits, mappedTexture.pData, 4 * descStaging.Width * descStaging.Height);
texture->Unmap(D3D10CalcSubresource(0, 0, 1));
}
texture->Release();
tempTexture->Release();
fp = fopen("D:\\output.txt", "a");
for(UINT row = 0; row < descStaging.Height; row++)
{
UINT rowStart = row * mappedTexture.RowPitch/4;
for(UINT col = 0; col < descStaging.Width; col++)
{
r = m_pBits[rowStart + col*4 + 0]; // Red (X)
g = m_pBits[rowStart + col*4 + 1]; // Green (Y)
b = m_pBits[rowStart + col*4 + 2]; // Blue (Z)
a = m_pBits[rowStart + col*4 + 3]; // Alpha (W)
// Save pixel values to disk
fprintf(fp, "%d %d - %f %f %f\n", col + 1, row + 1, r, g, b);
}
}
fclose(fp);
Кто-нибудь есть идеи о том, что проблема может быть? Вся помощь действительно оценена.
Как насчет рендеринга кадра в текстуру как RenderTarget и постобработки его с RGB в YUV шейдер? Это было бы намного быстрее, чем ручное преобразование из-за параллельных возможностей gpu. – Gnietschow
Спасибо! На самом деле это отличная идея, я попробую. Рендеринг текстуры был альтернативой, которую я имел в виду (она исправляет проблему за счет другого прохода визуализации), но мне все еще интересно, почему я получаю эти результаты. – Glenn
Он работал как шарм. Еще раз спасибо! – Glenn