D3D11:如何将GDI文本绘制到GXDI曲面?(没有D2D)

san*_*icz 8 c++ gdi+ gdi directx-11 dxgi

我需要一些帮助,用GDI和D3D11为纹理绘制文本.我尝试使用D2D/DirectWrite,但它只支持D3D10而不支持D3D11.到目前为止,我尝试过的所有内容都失败了......现在我想使用GDI方法在纹理中写入.所以我用这个参数创建了一个纹理:

Usage = D3D11_USAGE_DEFAULT;
Format = DXGI_FORMAT_B8G8R8A8_UNORM;
BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
CPUAccessFlags = 0;
MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE
Run Code Online (Sandbox Code Playgroud)

然后我从这个纹理创建了一个普通的RenderTargetView,就像这里的Microsoft sais:http://msdn.microsoft.com/en-us/library/ff476203%28v=vs.85%29.aspx

下一步:获取DXGI接口:

m_pTexFSText->QueryInterface(__uuidof(IDXGISurface1), (void **)(&m_pDXGISurface));
Run Code Online (Sandbox Code Playgroud)

在Render函数上,我这样做:

m_pDeviceContext->OMSetRenderTargets(1,&m_pTextRenderTarget,NULL);

HDC hDc = NULL;
if(FAILED(m_pDXGISurface->GetDC(TRUE,&hDc)))
    return E_FAIL;

COLORREF bla = SetPixel(hDc,1,1,RGB(255,255,255));
bool hmm = TextOutA(hDc, 10, 10, "LALALA!", 7);

if(FAILED(m_pDXGISurface->ReleaseDC(NULL)))
    return E_FAIL;
Run Code Online (Sandbox Code Playgroud)

问题是,在GDI绘图之后纹理仍然是空的(也用PIX测试).一切正常,没有错误消息.

我希望任何人都能解释它是如何运作的.

谢谢,斯特凡

编辑:尝试它GetDC(FALSE,&hDc)(根据文件):相同的结果 - >没有.

小智 6

我上周在实际上经常讨论这个问题 - 但我已经完成了所有工作!以下是您应该知道/做的事情列表,以使其全部工作:

使用此方法时请记住以下几点:

•必须使用表面的D3D11_RESOURCE_MISC_GDI_COMPATIBLE标志或使用交换链的DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE标志创建曲面,否则此方法将失败.

•在发出任何新的Direct3D命令之前,必须释放设备并调用IDXGISurface1 :: ReleaseDC方法.

•如果此方法已创建未完成的DC,则此方法将失败.

•表面或交换链的格式必须为DXGI_FORMAT_B8G8R8A8_UNORM_SRGB或DXGI_FORMAT_B8G8R8A8_UNORM.

•在GetDC上,Direct3D管道的输出合并中的渲染目标从表面解除绑定.在GDI渲染之后,必须在Direct3D渲染之前在设备上调用ID3D11DeviceContext :: OMSetRenderTargets方法.

•在调整缓冲区大小之前,您必须释放所有未完成的DC.

  • 如果您要在后台缓冲区中使用它,请记得在调用ReleaseDC 重新绑定渲染目标.在调用GetDC之前手动取消绑定RT是不必要的,因为此方法会为您执行此操作.

  • 您不能在GetDC()和ReleaseDC()调用之间使用任何 Direct3D绘图,因为DXGI会为GDI强制锁定表面.但是,只要您在每次需要使用GDI时调用GetDC()/ ReleaseDC(),就可以混合使用GDI和D3D渲染,然后再继续使用D3D.

  • 这最后一点可能听起来很容易,但你会惊讶于有多少开发人员陷入这个问题 - 当你在后台缓冲区上使用GDI绘制时,请记住这是后台缓冲区,而不是帧缓冲区,所以为了实际看到什么你已经绘制了,你必须将RT重新绑定到OM并调用swapChain-> Present()方法,这样后备缓冲区将成为一个帧缓冲区,其内容将显示在屏幕上.


val*_*ldo 3

也许你做的一切都很好,只是文本绘制没有达到你的预期?

COLORREF bla = SetPixel(hDc,1,1,RGB(255,255,255));
bool hmm = TextOutA(hDc, 10, 10, "LALALA!", 7);
Run Code Online (Sandbox Code Playgroud)

我不明白你如何期望它TextOutA会猜测bla应该用作文本颜色。据我所知,新创建/获得的 DC 中使用的默认文本颜色是黑色。不确定背景填充模式,但如果它是TRANSPARENT默认的 - 这充分解释了为什么没有绘制。

我会将您的代码更改为以下内容:

COLORREF bla = SetPixel(hDc,1,1,RGB(255,255,255));
VERIFY(SetTextColor(hDc, bla) != CLR_INVALID);

CREct rc(0, 0, 30, 20); // put relevant coordinates
VERIFY(ExtTextOut(hDc, rc.left, rc.top, ETO_CLIPPED, &rc, "LALALA!", 7));
Run Code Online (Sandbox Code Playgroud)