【发布时间】:2017-08-23 22:41:57
【问题描述】:
我对directx不熟悉,但在一个小项目中遇到了一个问题,其中一部分涉及到捕获directx数据。我希望,下面我有点道理。
一般问题:
我想知道是什么因素决定了后缓冲区中纹理的 DXGI_FORMAT(硬件?操作系统?应用程序?directx 版本?)。更重要的是,当从后台缓冲区捕获纹理时,是否可以通过提供格式作为参数来接收所需格式的纹理,并在必要时自动转换格式。
关于我的问题的细节:
我使用 Open Broadcaster Software (OBS) 从游戏中捕获屏幕,并在流式传输之前使用特定库 (OpenCV) 对其进行处理。我注意到,在更新 Windows 和 OBS 之后,我得到 'DXGI_FORMAT_R10G10B10A2_UNORM' 作为 DXGI_FORMAT。这对我来说是个问题,因为据我所知,当颜色为 10 位时,OpenCV 不提供构建 OpenCV 对象的便捷方法。以下是修改后的 OBS 源文件中的一些相关行。
d3d11_copy_texture(data.texture, backbuffer);
...
hlog(toStr(data.format)); // prints 24 = DXGI_FORMAT_R10G10B10A2_UNORM
...
ID3D11Texture2D* tex;
bool success = create_d3d11_stage_surface(&tex);
if (success) {
...
HRESULT hr = data.context->Map(tex, subresource, D3D11_MAP_READ, 0, &mappedTex);
...
Mat frame(data.cy, data.cx, CV_8UC4, mappedTex.pData, (int)mappedTex.RowPitch); //This creates an OpenCV Mat object.
//No support for 10-bit coors. Expects 8-bit colors (CV_8UC4 argument).
//When the resulting Mat is viewed, colours are jumbled (Probably because 10-bits did not fit into 8-bits).
在更新之前(一年前我正在处理这个问题时),我可能收到 DXGI_FORMAT = DXGI_FORMAT_B8G8R8A8_UNORM,因为上面的代码曾经可以工作。
现在我想知道发生了什么变化,是否可以修改 OBS 的源代码以接收具有所需 DXGI_FORMAT 的数据。
上面调用的'create_d3d11_stage_surface'方法设置DXGI_FORMAT,但我不确定它是否意味着'给我这个DXGI_FORMAT的数据'或'我知道你使用这种格式,给我你有什么'。
static bool create_d3d11_stage_surface(ID3D11Texture2D **tex)
{
HRESULT hr;
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = data.cx;
desc.Height = data.cy;
desc.Format = data.format;
...
我希望,用 DXGI_FORMAT_B8G8R8A8_UNORM 覆盖 desc.Format 会导致该格式在上面的 ID3D11DeviceContext::Map 调用中作为参数传递,并且我会得到具有指定格式的数据。但这不起作用。
【问题讨论】:
-
纹理的DXGI_FORMAT在纹理创建期间指定。您可能需要将 r10g10b10a2 数据“转换”为 b8r8g8a8 到 CPU 中,然后将其提供给 OpenCV 进行处理。
-
我检查了 directxtex,但我认为在我的情况下,从 OBS 中的另一个地方获取图像会更容易。
标签: directx directx-11