• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
BlackJoker

D2D + D3D11 help me to make them work together

20 posts in this topic

Hello to all!


I have a problem with connecting D2D to D3D11. I read a lot of forum articles on that theme, but this interop a little bit hard to understand and more harder to use on practice. I tried to implement it as was saying in this article http://www.braynzarsoft.net/index.php?p=D3D11FONT#still but problem in that in the sample all the code is in 1 file and there is no OOP at all, and I make my engine from the rasterteck framework.

I think during implementation of interop D2D and D3D11 I missed something, but I can`t find the problem because program work without errors, but just no text on the screen.



I uploaded my project here, so if you wish to help me, you can look into code and say where i have a mistake because I am completely confused with this problem.

 

Could someone build up this project and find out why text is not rendered?

I am trying to find a solution already a week, but unsuccessfully.


P.S. I chose to implement D2D + D3D11 because the way to cut texture into pieces seems no so good way to make text output for me, besides it hard to make localization in that way.

 



Please, help me.

0

Share this post


Link to post
Share on other sites

I don't have a good resource available to explain this, but I just thought I'd let you know that Microsoft released a platform update on 2/26/2013 that makes a lot of the things in that article unnecessary. It's now possible to use D3D11 and D2D together directly, without having to create a D3D10.1 device and worry about synchronizing the resources.

 

If you've installed the update, you should be able to just create a D3D11 texture, get an IDXGISurface1 pointer from it, and then pass that to CreateDxgiSurfaceRenderTarget to create a D2D render target.

Edited by jrh2365
2

Share this post


Link to post
Share on other sites

I didn`t hear about this update. Is it for DirectX11 or for DirectX 11.1? Where I can read about it more detail?

Edited by BlackJoker
0

Share this post


Link to post
Share on other sites

Actually, if you are on Windows 8 it was possible before the update. The update (http://support.microsoft.com/kb/2670838) was only for allowing it to work on Windows 7 as well.

 

Here is a sample for D3D-D2D interop on Windows 8. I didn't get a chance to look at it, but it might be useful.

http://code.msdn.microsoft.com/windowsapps/Direct2D-Direct3D-Interop-ee641e46

 

Also, here's a quick example I threw together, using D2D to draw text to the backbuffer. It should also be possible to create a texture in D3D11, and then write to it with D2D. (I think you would use QueryInterface to get the IDXGISurface1 pointer from the texture, and then pass that to CreateDxgiSurfaceRenderTarget, but I'm not sure)

 

#include <Windows.h>
#include <d3d11.h>
#include <d2d1_1.h>
#include <dwrite_1.h>

#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dwrite.lib")

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	if (msg == WM_CLOSE)
	{
		PostQuitMessage(0);
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	// create the window

	WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = sizeof(LONG_PTR);
	wcex.hInstance = hInstance;
	wcex.hbrBackground = NULL;
	wcex.lpszMenuName  = NULL;
	wcex.hCursor  = LoadCursor(NULL, IDI_APPLICATION);
	wcex.lpszClassName = "Vector";
	ATOM a = RegisterClassEx(&wcex);

	RECT r = {0, 0, 800, 600};
	AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, false);

	HWND hWnd = CreateWindow(
		(LPCSTR)a,
		"Vector",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		r.right - r.left,
		r.bottom - r.top,
		NULL,
		NULL,
		hInstance,
		NULL);

	// create the D3D device and swap chain

	D3D_FEATURE_LEVEL level = D3D_FEATURE_LEVEL_11_0;

	DXGI_SWAP_CHAIN_DESC swapChainDesc = { };
	swapChainDesc.BufferCount = 1;
	swapChainDesc.BufferDesc.Width = 800;
	swapChainDesc.BufferDesc.Height = 600;
	swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
	swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	swapChainDesc.OutputWindow = hWnd;
	swapChainDesc.SampleDesc.Count = 1;
	swapChainDesc.SampleDesc.Quality = 0;
	swapChainDesc.Windowed = true;

	IDXGISwapChain *swapChain;
	ID3D11Device *device;
	ID3D11DeviceContext *context;

	HRESULT hr = D3D11CreateDeviceAndSwapChain(
		NULL,
		D3D_DRIVER_TYPE_HARDWARE,
		NULL,
		D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_BGRA_SUPPORT,
		&level,
		1,
		D3D11_SDK_VERSION,
		&swapChainDesc,
		&swapChain,
		&device,
		NULL,
		&context);

	// set up the D3D render target view to the back buffer

	ID3D11Texture2D *backBuffer;
	ID3D11RenderTargetView *backBufferView;
	swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer));
	device->CreateRenderTargetView(backBuffer, NULL, &backBufferView);
	context->OMSetRenderTargets(1, &backBufferView, NULL);

	// create the D2D factory

	ID2D1Factory *factory;
	D2D1_FACTORY_OPTIONS options;
	options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
	D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, options, &factory);

	// set up the D2D render target using the back buffer

	IDXGISurface *dxgiBackbuffer;
	swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackbuffer));
	ID2D1RenderTarget *d2dRenderTarget;
	D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
		D2D1_RENDER_TARGET_TYPE_DEFAULT,
		D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
	factory->CreateDxgiSurfaceRenderTarget(dxgiBackbuffer, props, &d2dRenderTarget);
	dxgiBackbuffer->Release();

	// create the DWrite factory

	IDWriteFactory1 *writeFactory;
	DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(writeFactory), (IUnknown**)(&writeFactory));

	// create the DRwite text format

	IDWriteTextFormat *textFormat;
	writeFactory->CreateTextFormat(
		L"Arial",
		NULL,
		DWRITE_FONT_WEIGHT_NORMAL,
		DWRITE_FONT_STYLE_NORMAL,
		DWRITE_FONT_STRETCH_NORMAL,
		50,
		L"",
		&textFormat);

	// create a brush

	ID2D1SolidColorBrush *whiteBrush;
	d2dRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &whiteBrush);

	// draw the text
	
	d2dRenderTarget->BeginDraw();
	const WCHAR *text = L"Hello World";
	d2dRenderTarget->DrawTextA(text, wcslen(text), textFormat, D2D1::RectF(0, 0, 800, 600), whiteBrush);
	d2dRenderTarget->EndDraw();

	ShowWindow(hWnd, true);

	MSG msg = {0};
	while (WM_QUIT != msg.message)
	{
		if (PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
		else
		{
			swapChain->Present(0, 0);
		}
	}
}
2

Share this post


Link to post
Share on other sites

I didn`t know that D2D1_1 I can use with D3D11 on Win8. Thanks for that.

 

hm, it seems that i cannot build that MS sample because my VS 2012 says that this project is incompatible with my version of VS. I have Ultimate version.

Does someone know how to build that project?

0

Share this post


Link to post
Share on other sites

And another one thing - now I must use Windows 8 SDK to use new D2D, but here is no D3DX.h, so I must find new analogs for old functions such as D3DXMatrixPerspectiveFovLH and D3DXCreateTextureFromFile

 

Does someone now which functions I can replace these?

 

By the way. I have tested you code and it work great after few small corrections regarding CreateWindow function. Thanks a lot for this, but I still don`t know whixh functions to use instead of D3DX functions. Could you please help me with that question?

Edited by BlackJoker
0

Share this post


Link to post
Share on other sites

And another one question: how to get last position of drawn symbol in D2D? For example I want to draw text after previous, but for thi I need to now where the rivious text ended on the screen. Could I get this information somehow?

0

Share this post


Link to post
Share on other sites

And another one thing - now I must use Windows 8 SDK to use new D2D, but here is no D3DX.h, so I must find new analogs for old functions such as D3DXMatrixPerspectiveFovLH and D3DXCreateTextureFromFile

 

Does someone now which functions I can replace these?

 

By the way. I have tested you code and it work great after few small corrections regarding CreateWindow function. Thanks a lot for this, but I still don`t know whixh functions to use instead of D3DX functions. Could you please help me with that question?

 

Since D3DX is retired you (must) can use DirectX Tool kit, DirectX Tex and DirectXMath respectively for graphics, texture and math function ad structures.

 

http://directxtk.codeplex.com/

http://directxtex.codeplex.com/

http://msdn.microsoft.com/en-us/library/windows/desktop/ee418730.aspx

 

If you still want to use D3DX you must install the June 2010 DXSDK and manually configure the vs project: http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275.aspx

Edited by Alessio1989
1

Share this post


Link to post
Share on other sites

As far as rendering the text to a texture, you use QueryInterface<T> as mentioned above to get an IDXGISurface1 pointer, and then pass that to ID2D1Factory::CreateDxgiSurfaceRenderTarget. Then you can just use that render target like the render target in my example above.

Example of render target creation:

// create the D3D11 texture

D3D11_TEXTURE2D_DESC texDesc = {};
texDesc.ArraySize = 1;
texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
texDesc.Usage = D3D11_USAGE_DEFAULT;
texDesc.Width = 512;
texDesc.Height = 512;
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
texDesc.SampleDesc.Count = 1;
texDesc.MipLevels = 1;
ID3D11Texture2D *texture;
device->CreateTexture2D(&texDesc, NULL, &texture);

// create D2D render target using texture

ID2D1RenderTarget *renderTarget;
IDXGISurface1* dxgiSurface;
texture->QueryInterface<IDXGISurface1>(&dxgiSurface);
D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
	D2D1_RENDER_TARGET_TYPE_DEFAULT,
	D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
factory->CreateDxgiSurfaceRenderTarget(dxgiSurface, &props, &renderTarget);
dxgiSurface->Release();

 

 

For determining where the previous text ended on the screen...I think IDWriteFactory::CreateTextLayout and IDWriteTextLayout::GetMetrics might help. It looks like it can take care of wrapping text for you as well.

Edited by jrh2365
1

Share this post


Link to post
Share on other sites

Are you drawing text directly to the backbuffer with D2D? If so, its not using the depth buffer. You could try drawing the text last, or drawing the text to a texture first, and then drawing a quad using that texture.

1

Share this post


Link to post
Share on other sites

Are you drawing text directly to the backbuffer with D2D? If so, its not using the depth buffer. You could try drawing the text last, or drawing the text to a texture first, and then drawing a quad using that texture.

Yes, I am drawing directly to backbuffer. If I will draw to a texture will this texture be always on top of D3D scene independently of when I am drawing it?

0

Share this post


Link to post
Share on other sites

And one more question. Rendered text displaying not clear enough. I use antialiasing like this:



d2dRenderTarget->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE);
	D2D1_ANTIALIAS_MODE anti;
	anti = D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
	d2dRenderTarget->SetAntialiasMode(anti);

 

but text look like diffused (see attachment).

 

How to fix this and make text clear?

0

Share this post


Link to post
Share on other sites

Yes, I am drawing directly to backbuffer. If I will draw to a texture will this texture be always on top of D3D scene independently of when I am drawing it?

 

Here's a better explanation:

If you're just overlaying text on a scene, easiest would be to just draw it last. If for some reason you can't/don't want to draw all the text last, you could draw the text to a texture, and then draw a quad with that texture. You'll still need to draw that quad last, though, and you'd probably want to disable depth testing for that. (Note that this is also a bit less efficient because of the additional memory used by the texture, and overdraw.)

 

How to fix this and make text clear?

 

Not sure. If I have time, I'll see how it looks on my system later. Could you post the code you used to create the font?

0

Share this post


Link to post
Share on other sites

Not sure. If I have time, I'll see how it looks on my system later. Could you post the code you used to create the font?

Yes, here is my coe for that - it is just copy from yours

 





swapChain->GetBuffer(0, IID_PPV_ARGS(&BackBuffer11));

	d3d11_Device->CreateRenderTargetView(BackBuffer11, NULL, &d3d11_RenderTargetView);
	d3d11_DeviceContext->OMSetRenderTargets(1, &d3d11_RenderTargetView, NULL);

	options.debugLevel = D2D1_DEBUG_LEVEL_ERROR;
	D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, options, &d2dfactory);

	swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackbuffer));
	D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
		D2D1_RENDER_TARGET_TYPE_DEFAULT,
		D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
	d2dfactory->CreateDxgiSurfaceRenderTarget(dxgiBackbuffer, props, &d2dRenderTarget);
	dxgiBackbuffer->Release();

	DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(DWriteFactory), (IUnknown**)(&DWriteFactory));

	DWriteFactory->CreateTextFormat(
		L"Cambria",
		NULL,
		DWRITE_FONT_WEIGHT_NORMAL,
		DWRITE_FONT_STYLE_NORMAL,
		DWRITE_FONT_STRETCH_NORMAL,
		14,
		L"",
		&textFormat);

	d2dRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &Brush);

 

and then I DrawText with this fuction:

In this code I don`t use antialiasing, but there is no difference between using and not using it.





void D3D11::RenderText(WCHAR* text)
{
	d2dRenderTarget->BeginDraw();
	DWriteFactory->CreateTextLayout(text, wcslen(text), textFormat, 1000, 10, &textLayout);

	D2D1_POINT_2F origin;
	origin.x = 0;
	origin.y = 0;
	D2D1_DRAW_TEXT_OPTIONS op= D2D1_DRAW_TEXT_OPTIONS_NONE;
	d2dRenderTarget->DrawTextLayout(origin,textLayout,Brush, op);
	DWRITE_TEXT_METRICS textMetrix;
	//???????? ?????????? ? ???????????? ??????
	textLayout->GetMetrics(&textMetrix);
	//d2dRenderTarget->DrawText(text, wcslen(text), textFormat, D2D1::RectF(0, 0, 800, 600), Brush);
	d2dRenderTarget->EndDraw();
	textLayout->Release();
	textLayout = NULL;
}
Edited by BlackJoker
0

Share this post


Link to post
Share on other sites

Ok, so two things:

 

First, it looks like you are using a font that you don't have. Cambria is a serif font, but the font in your screenshot is sans-serif, so I think it is failing to find the font you specified and uses a fallback instead.

 

 

Second, everything looks correct when I draw text with my code (see attachment). How are you sizing your window and backbuffer? If you're passing the same dimensions to CreateWindow and D3D11CreateDeviceAndSwapChain, that could be the problem because CreateWindow includes the size of the border in the dimensions. So then you end up with a window that is smaller than your backbuffer, and everything gets scaled and looks horrible.

 

You should use AdjustWindowRect to take the size of the border into account, passing the same style used to create the window (ex. WS_OVERLAPPEDWINDOW). Then when calling CreateWindow, you should pass rect.right - rect.left as the width, and rect.bottom - rect.top as the height, because AdjustWindowRect might make the left and top values negative. Relevant snippet from my code above:

 

RECT r = {0, 0, 800, 600};
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, false);

HWND hWnd = CreateWindow(
	(LPCSTR)a,
	"Vector",
	WS_OVERLAPPEDWINDOW,
	CW_USEDEFAULT,
	CW_USEDEFAULT,
	r.right - r.left,
	r.bottom - r.top,
	NULL,
	NULL,
	hInstance,
	NULL);

 

 

AdjustWindowRect

1

Share this post


Link to post
Share on other sites

jrh2365, your advice helped. Thanks a lot, but 1 question left (I hope  one).

I setup patch fro Win7 you wrote to fix interop D2D with D3D and now it works, but when I exit application, it crashes in "crt0dat.c" in



void __cdecl __crtExitProcess (
        int status
        )
{
        __crtCorExitProcess(status);

        /*
         * Either mscoree.dll isn't loaded,
         * or CorExitProcess isn't exported from mscoree.dll,
         * or CorExitProcess returned (should never happen).
         * Just call ExitProcess.
         */

        ExitProcess(status);
}

here in the last line - ExitProcess(status)

 

If I comment the code for initialization of D2D, then no crashes occured. On Win 8 no crashes at all. Do you know how to fix that?

Edited by BlackJoker
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0