我需要一些帮助,用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
然后我从这个纹理创建了一个普通的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));
在渲染功能上,我这样做:
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;
问题是,在GDI绘图之后纹理仍然是空的(也用PIX测试)。 一切正常,没有错误信息。
我希望任何人都可以解释它是如何运作的。
谢谢,Stefan
编辑:尝试使用GetDC(FALSE,&hDc)
(根据文档):相同的结果 - >什么都没有。
答案 0 :(得分:5)
上周我实际上经常讨论这个问题 - 但我已经完成了所有工作!以下列出了您应该知道/做的事情,以使其全部工作:
使用此方法时请记住以下几点:
•您必须使用表面的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()方法,这样后备缓冲区将成为一个帧缓冲区,它的内容将被显示在屏幕上。
答案 1 :(得分:3)
也许你做的一切都很好,只是文字图纸不符合你的期望?
COLORREF bla = SetPixel(hDc,1,1,RGB(255,255,255));
bool hmm = TextOutA(hDc, 10, 10, "LALALA!", 7);
我不明白这一点你怎么认为TextOutA
会猜测bla
应该用作文字颜色。 AFAIK在新创建/获得的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));
答案 2 :(得分:0)
我将在后台缓冲区中使用它。我不确定是否做得正确。我看不到图纸。它显示为黑色。
HDC GetSurfaceDC()
{
m_pSurface1 = nullptr;
HDC hdc{};
//Setup the swapchain surface
IF_FAILED_THROW_HR(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&m_pSurface1)));
// Obtain the back buffer for this window which will be the final 3D render target.
ID3D11Texture2DPtr backBuffer;
IF_FAILED_THROW_HR(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)));
// Create a descriptor for the RenderTargetView.
CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2DARRAY, DXGI_FORMAT_B8G8R8A8_UNORM, 0, 0, 1);
ID3D11RenderTargetViewPtr renderTargetView;
// Create a view interface on the render target to use on bind for mono or left eye view.
IF_FAILED_THROW_HR(m_device->CreateRenderTargetView(backBuffer, &renderTargetViewDesc, &renderTargetView));
m_context->OMSetRenderTargets(1, &renderTargetView.GetInterfacePtr(), nullptr);
IF_FAILED_THROW_HR(m_pSurface1->GetDC(FALSE, &hdc));
return hdc;
}
void ReleaseSurfaceDC()
{
if (m_pSurface1 == nullptr)
return;
//When finish drawing release the DC
m_pSurface1->ReleaseDC(nullptr);
m_context->OMSetRenderTargets(1, &m_renderTargetView.GetInterfacePtr(), m_depthStencilView);
}
我用过交换链desc:
DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;