3 Replies - 4466 Views - Last Post: 12 September 2014 - 11:51 AM Rate Topic: -----

#1 Kain6622  Icon User is offline

  • D.I.C Regular

Reputation: 19
  • View blog
  • Posts: 268
  • Joined: 18-March 10

Multiple Windows and DirectX 11 rendering Question

Posted 08 September 2014 - 03:08 PM

Hi there,

I've been trying to find resources on how one goes about using DirectX 11 with an application that has multiple windows (Like a level editors or CAD application) but have been no so successful. From what I've looked into most people are suggesting using multiple SwapChains which seems logical but due to lack of samples/tutorials (in DirectX 11) to read through makes it difficult to understand how it would work.

My Question directly is what are the steps required to perform this successfully in DirectX 11? I have a few thoughts but am hoping someone has done this before too...

1: Create multiple Swapchains for each window
2: On initialization of these swapchains, all must have their own desc (as you would expect?)
3: Create multiple Rendertargetviews for each window?

But would you need to create a separate backbuffer for each swapchain or could you use the same one?
and are there any easier approaches to this... Keeping in mind multiple Windows? (not just creating multiple viewports on the same window).

so far my code looks something like this, not creating too much just the swapchains:

// create additional swap chains if wished and possible
	if ((m_nNumhWnd > 0) && m_bWindowed)
	{
		for (UINT i = 0; i < m_nNumhWnd; i++)
		{
			DXGI_SWAP_CHAIN_DESC sd;
			ZeroMemory(&sd, sizeof(sd));
			sd.BufferCount = 1;
			sd.BufferDesc.Width = Windows[1].width;
			sd.BufferDesc.Height = Windows[1].height;
			sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
			sd.BufferDesc.RefreshRate.Numerator = 60;
			sd.BufferDesc.RefreshRate.Denominator = 1;
			sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
			sd.OutputWindow = hWnd3D[i];
			sd.SampleDesc.Count = 8;
			sd.SampleDesc.Quality = 0;
			sd.Windowed = TRUE;

			hr = dxgiFactory->CreateSwapChain(m_pDevice, &sd, &m_pSwapChain[i]);
		}



could you advise on this topic and if possible if you know of any good tutorials on this matter please advise as I'm not having much luck at the moment.

Thank you in advance.
Dave

Is This A Good Question/Topic? 1
  • +

Replies To: Multiple Windows and DirectX 11 rendering Question

#2 BBeck  Icon User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: Multiple Windows and DirectX 11 rendering Question

Posted 09 September 2014 - 06:09 AM

I'm going to take an educated guess here and say you don't want multiple swap chains. I haven't done this in DX11, but I have done it in XNA, which is heavily DX9 based.

The reason I'm guessing you don't need multiple swap chains is that the purpose of the swap chain is to avoid screen tearing when you draw directly to the screen. So, it's there to allow you to not draw directly to the screen. But even with multiple camera views on one screen you only need one back buffer.

So, the way I would approach it if I were going to try this for the first time is to use render targets. Let's say I want the screen split 4 ways so that 4 players playing at the same time get their own quarter of the screen. Each player has a completely different view of the game each from their perspective.

First, I would setup 4 render targets (you might figure out a way to draw one of them directly to the backbuffer without an intermediate render target but this is the easiest way to go). The render targets are just picture buffers like you would store any picture in. They probably need to be the size of 1 quarter of the backbuffer/screen each. They don't need a swap chain because they won't be visible by themselves anyway.

Then I would define 4 view matrices, one for each camera/player. I would "probably" only use one projection matrix unless there was some special effects need that would prevent all 4 from sharing the same perspective.

I would draw the scene to each render target using that render target's view matrix, but otherwise you're drawing the same thing 4 times.

Then I would draw the render targets to the backbuffer as if they were sprites. So, probably draw 4 quads and texture each with the appropriate render target. This probably needs to be done with a 5th camera using an orthographic projection matrix and probably a 5th view matrix.

So, the backbuffer still has a swapchain and it's the only thing the end user will see when the backbuffer presents and becomes the frontbuffer.

And to answer your question, you technically don't have a swapchain without a backbuffer. At a minimum, a swapchain is a frontbuffer and one or more backbuffers. But without two buffers (front and back), it's impossible to swap and therefore there is no swapchain.

I would be interested in seeing the code when you get it working. You could create the first tutorial for it.

P.S. I just went back and reread what you wrote and I think I answered the wrong question. Sounds like you want to draw 4 separate windows. Ouch.

Yep, there you're probably going to need 4 separate swapchains. I would think it would be the same as drawing to 4 separate monitors although I haven't done this in any platform. I would imagine everything has to be duplicated for each window as if it were separate monitors.

For separate monitors you need separate swapchains because there's probably no way to do it without separate backbuffers. With separate swapchains, you shouldn't need render targets at all but you likely may still need separate view matrices. And yes, you would probably need separate backbuffer descriptions unless they are identical descriptions and then you might be able to reuse one. Again, I haven't played with this at all, so I'm just guessing. The description is probably just used for initialization and is probably reusable assuming you never want to change anything... but with separate windows you may have to match it to window size and stuff that may be separate so that may require separate descriptions.

Oh. Another distinction I might make is that a CAD program likely manages its own windows. So those windows are owned by the application and not by the OS. I'm assuming OS windows for what I just said there. If they are app managed windows then you're back to the first solution with render targets and one swapchain. I think that's what made me go for that solution first.

This post has been edited by BBeck: 09 September 2014 - 06:23 AM

Was This Post Helpful? 1
  • +
  • -

#3 Kain6622  Icon User is offline

  • D.I.C Regular

Reputation: 19
  • View blog
  • Posts: 268
  • Joined: 18-March 10

Re: Multiple Windows and DirectX 11 rendering Question

Posted 09 September 2014 - 11:25 AM

Hi BBeck, thanks for your input, There are a lot of changes since DX9 and DX11, The solution is too have a swapchain and rendertargetview of each window your hoping to draw too. I'm my application I've got the main window and two child windows (which are to be drawn too), the swapchain desc requires that you specify the target window that the swapchain is to be bound, hence why we need one for each window.

Through thought and persistence I've managed to successfully achieve what I was wanting through what I said above, I'm not sure how efficient it is but I'll deal which that later unless we use this thread to improve on it...

The Code is as follows, We have a main window contains to child (rendering) windows both render the same triangle but one is solid the other wireframe:

// File: Main.cpp

// Includes
#include <Windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <DirectXColors.h>

using namespace DirectX;

// Libraries
#pragma comment(lib, "D3D11.lib")
#pragma comment(lib, "D3DCompiler.lib")

// Defines
#define MAX_CHILDREN 8

// Forward Declarations
HWND CreateMainhWnd(HINSTANCE hInst, UINT width, UINT height, UINT nCmdShow);
HWND	CreateChildhWnd(HWND Parent, LPCWSTR title, UINT x, UINT y, UINT width, UINT height);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

// DirectX Forward Declarations
HRESULT InitDirect3D();
void	ShutdownDirect3D();
void	CreateNewSwapChain(HWND *TargetWnd);
void	InitScene();
void	Render();

// Direct3D Global Variables
D3D_DRIVER_TYPE         g_driverType = D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVEL       g_featureLevel = D3D_FEATURE_LEVEL_11_0;
ID3D11Device*			g_pD3DDevice = nullptr;
ID3D11DeviceContext*	g_pD3DImmediateContext = nullptr;
IDXGISwapChain*			g_pSwapChain[MAX_CHILDREN] = { nullptr };
ID3D11RenderTargetView*	g_pRenderTargetView[MAX_CHILDREN] = { nullptr };
UINT					g_nSwapchainCount = 0;
ID3D11RasterizerState * g_pRasterStateWire;
ID3D11RasterizerState * g_pRasterStateSolid;

const XMVECTORF32 ClearColor = { 0.75f, 0.75f, 1.0f };

// Sample specific variables
HRESULT CompileShaderFromFile(WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut);

ID3D11VertexShader*     g_pVertexShader = nullptr;
ID3D11PixelShader*      g_pPixelShader = nullptr;
ID3D11InputLayout*      g_pVertexLayout = nullptr;
ID3D11Buffer*           g_pVertexBuffer = nullptr;

struct SimpleVertex
{
	XMFLOAT3 Pos;
};

// Global variables
HINSTANCE	g_iInst;
HWND	g_MainhWnd;
HWND	g_ChildWnd[MAX_CHILDREN];

// Main: Entry point to our application
int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow)
{
	g_iInst = hInstance; // Store instance handle in our global variable

	// Create the main application window
	g_MainhWnd = CreateMainhWnd(g_iInst, 1040, 760, nCmdShow);

	// Create a child window
	g_ChildWnd[0] = CreateChildhWnd(g_MainhWnd, L"Test1", 0, 0, 512, 720);
	g_ChildWnd[1] = CreateChildhWnd(g_MainhWnd, L"Test2", 512, 0, 512, 720);

	if (FAILED(InitDirect3D()))
	{
		MessageBox(nullptr, L"Couldn't Initialize Direct3D.", L"MultiWindow Yay - Error", MB_OK | MB_IConerror);
		return 0;
	}

	CreateNewSwapChain(&g_ChildWnd[0]);
	CreateNewSwapChain(&g_ChildWnd[1]);

	InitScene();

	// Main message loop:
	MSG msg = { 0 };
	while (WM_QUIT != msg.message)
	{
		if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			Render();
		}
	}

	ShutdownDirect3D();

	return (int)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_KEYDOWN:
		if (wParam == VK_ESCAPE)
			PostQuitMessage(0);
	case WM_DESTROY:
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}

	return 0;
}

HWND CreateMainhWnd(HINSTANCE hInst, UINT width, UINT height, UINT nCmdShow)
{
	HWND Wnd;

	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInst;
	wcex.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
	wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = L"Win32Class";
	wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

	if (!RegisterClassEx(&wcex))
	{
		MessageBox(NULL, L"Call to RegisterClassEx failed!", L"MultiWindow Yay", NULL);
		return nullptr;
	}

	Wnd = CreateWindow(L"Win32Class", L"Direct3D Test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height,
		nullptr, nullptr, hInst, nullptr);

	if (!Wnd)
	{
		MessageBox(nullptr, L"Call to CreateWindow failed!", L"MultiWindow Yay", NULL);

		return nullptr;
	}

	// The parameters to ShowWindow explained:
	// hWnd: the value returned from CreateWindow
	// nCmdShow: the fourth parameter from WinMain
	ShowWindow(Wnd, nCmdShow);
	UpdateWindow(Wnd);

	return Wnd;
}

HWND	CreateChildhWnd(HWND Parent, LPCWSTR title, UINT x, UINT y, UINT width, UINT height)
{
	HWND ChildWnd;

	ChildWnd = CreateWindow(L"Win32Class", title, WS_CHILDWINDOW | WS_OVERLAPPEDWINDOW | WS_DLGFRAME, x, y, width, height, Parent, nullptr, g_iInst, nullptr);

	ShowWindow(ChildWnd, SW_SHOW);
	UpdateWindow(ChildWnd);

	return ChildWnd;
}

HRESULT InitDirect3D()
{
	HRESULT hr = S_OK;

	RECT rc;
	GetClientRect(g_MainhWnd, &rc);

	UINT width = rc.right = rc.left;
	UINT height = rc.bottom - rc.top;

	// if we are in debug build mode, set the device flag to include DirectX debugging
	UINT createDeviceFlags = 0;
#ifndef _DEBUG
	createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

	// The Driver types and feature level arrays
	D3D_DRIVER_TYPE driverTypes[] =
	{
		D3D_DRIVER_TYPE_HARDWARE,
		D3D_DRIVER_TYPE_WARP,
		D3D_DRIVER_TYPE_REFERENCE,
	};
	UINT numDriverTypes = ARRAYSIZE(driverTypes);

	D3D_FEATURE_LEVEL featureLevels[] =
	{
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
		D3D_FEATURE_LEVEL_10_0,
	};
	UINT numFeatureLevels = ARRAYSIZE(featureLevels);

	// Create the Direct3D Device
	for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
	{
		g_driverType = driverTypes[driverTypeIndex];

		for (UINT featureIndex = 0; featureIndex < numFeatureLevels; featureIndex++)
		{
			g_featureLevel = featureLevels[featureIndex];
			hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
				D3D11_SDK_VERSION, &g_pD3DDevice, &g_featureLevel, &g_pD3DImmediateContext);

			if (SUCCEEDED(hr))
				break;
		}

		if (SUCCEEDED(hr))
			break;
	}

	if (FAILED(hr))
		return hr;

	return S_OK;
}

void	ShutdownDirect3D()
{
	// Clear the immediate context state
	if (g_pD3DImmediateContext) g_pD3DImmediateContext->ClearState();

	// Release and clear all scene data
	if (g_pRasterStateSolid) g_pRasterStateSolid->Release();
	if (g_pRasterStateWire) g_pRasterStateWire->Release();
	if (g_pVertexBuffer) g_pVertexBuffer->Release();
	if (g_pVertexLayout) g_pVertexLayout->Release();
	if (g_pVertexShader) g_pVertexShader->Release();
	if (g_pPixelShader) g_pPixelShader->Release();

	// Release all D3D Devices, Context and swapchains
	UINT index = 0;
	for (index; index <= g_nSwapchainCount - 1; index++)
	{
		if (g_pRenderTargetView)
			g_pRenderTargetView[index]->Release();

		if (g_pSwapChain[index])
			g_pSwapChain[index]->Release();
	}
	g_nSwapchainCount = 0;

	if (g_pD3DImmediateContext) g_pD3DImmediateContext->Release();
	if (g_pD3DDevice) g_pD3DDevice->Release();
}

void	CreateNewSwapChain(HWND *TargetWnd)
{
	HRESULT hr;

	RECT rc;
	GetClientRect(*TargetWnd, &rc);

	UINT width = rc.right - rc.left;
	UINT height = rc.bottom - rc.top;

	// Obtain DXGI factory from device (since we used nullptr for pAdapter above) 
	IDXGIFactory* dxgiFactory = nullptr;
	{
		IDXGIDevice* dxgiDevice = nullptr;
		hr = g_pD3DDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
		if (SUCCEEDED(hr))
		{
			IDXGIAdapter* adapter = nullptr;
			hr = dxgiDevice->GetAdapter(&adapter);
			if (SUCCEEDED(hr))
			{
				hr = adapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&dxgiFactory));
				adapter->Release();
			}
			dxgiDevice->Release();
		}
	}

	if (FAILED(hr))
		return;

	// Create swap chain 
	// DirectX 11.0 systems 
	DXGI_SWAP_CHAIN_DESC sd;
	ZeroMemory(&sd, sizeof(sd));
	sd.BufferCount = 1;
	sd.BufferDesc.Width = width;
	sd.BufferDesc.Height = height;
	sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	sd.BufferDesc.RefreshRate.Numerator = 60;
	sd.BufferDesc.RefreshRate.Denominator = 1;
	sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	sd.OutputWindow = *TargetWnd;
	sd.SampleDesc.Count = 8;
	sd.SampleDesc.Quality = 0;
	sd.Windowed = TRUE;

	hr = dxgiFactory->CreateSwapChain(g_pD3DDevice, &sd, &g_pSwapChain[g_nSwapchainCount]);

	dxgiFactory->Release();

	if (FAILED(hr))
		return;

	// Create a render target view 
	ID3D11Texture2D* pBackBuffer = nullptr;
	hr = g_pSwapChain[g_nSwapchainCount]->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer));
	if (FAILED(hr))
		return;

	hr = g_pD3DDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView[g_nSwapchainCount]);
	pBackBuffer->Release();
	if (FAILED(hr))
		return;

	g_pD3DImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView[g_nSwapchainCount], nullptr);

	// Setup the viewport 
	D3D11_VIEWPORT vp;
	vp.Width = (FLOAT)width;
	vp.Height = (FLOAT)height;
	vp.MinDepth = 0.0f;
	vp.MaxDepth = 1.0f;
	vp.TopLeftX = 0;
	vp.TopLeftY = 0;
	g_pD3DImmediateContext->RSSetViewports(1, &vp);

	g_nSwapchainCount++;

}

// Helper function
HRESULT CompileShaderFromFile(WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut)
{
	HRESULT hr = S_OK;

	DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG 
	// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders. 
	// Setting this flag improves the shader debugging experience, but still allows  
	// the shaders to be optimized and to run exactly the way they will run in  
	// the release configuration of this program. 
	dwShaderFlags |= D3DCOMPILE_DEBUG;

	// Disable optimizations to further improve shader debugging 
	dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
#endif 

	ID3DBlob* pErrorBlob = nullptr;
	hr = D3DCompileFromFile(szFileName, nullptr, nullptr, szEntryPoint, szShaderModel,
		dwShaderFlags, 0, ppBlobOut, &pErrorBlob);
	if (FAILED(hr))
	{
		if (pErrorBlob)
		{
			OutputDebugStringA(reinterpret_cast<const char*>(pErrorBlob->GetBufferPointer()));
			pErrorBlob->Release();
		}
		return hr;
	}
	if (pErrorBlob) pErrorBlob->Release();

	return S_OK;
}

void	InitScene()
{
	HRESULT hr;

	// Make some rasterizer states
	D3D11_RASTERIZER_DESC rasterizerStateWire;
	rasterizerStateWire.FillMode = D3D11_FILL_WIREFRAME;
	rasterizerStateWire.CullMode = D3D11_CULL_FRONT;
	rasterizerStateWire.FrontCounterClockwise = true;
	rasterizerStateWire.DepthBias = false;
	rasterizerStateWire.DepthBiasClamp = 0;
	rasterizerStateWire.SlopeScaledDepthBias = 0;
	rasterizerStateWire.DepthClipEnable = false;
	rasterizerStateWire.ScissorEnable = false;
	rasterizerStateWire.MultisampleEnable = false;
	rasterizerStateWire.AntialiasedLineEnable = false;
	g_pD3DDevice->CreateRasterizerState(&rasterizerStateWire, &g_pRasterStateWire);

	D3D11_RASTERIZER_DESC rasterizerStateSolid;
	rasterizerStateSolid.FillMode = D3D11_FILL_SOLID;
	rasterizerStateSolid.CullMode = D3D11_CULL_FRONT;
	rasterizerStateSolid.FrontCounterClockwise = true;
	rasterizerStateSolid.DepthBias = false;
	rasterizerStateSolid.DepthBiasClamp = 0;
	rasterizerStateSolid.SlopeScaledDepthBias = 0;
	rasterizerStateSolid.DepthClipEnable = false;
	rasterizerStateSolid.ScissorEnable = false;
	rasterizerStateSolid.MultisampleEnable = false;
	rasterizerStateSolid.AntialiasedLineEnable = false;
	g_pD3DDevice->CreateRasterizerState(&rasterizerStateSolid, &g_pRasterStateSolid);

	// Compile the vertex shader 
	ID3DBlob* pVSBlob = nullptr;
	hr = CompileShaderFromFile(L"Tutorial02.fx", "VS", "vs_4_0", &pVSBlob);
	if (FAILED(hr))
	{
		MessageBox(nullptr,
			L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK);
		return;
	}

	// Create the vertex shader 
	hr = g_pD3DDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader);
	if (FAILED(hr))
	{
		pVSBlob->Release();
		return;
	}

	// Define the input layout 
	D3D11_INPUT_ELEMENT_DESC layout[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};
	UINT numElements = ARRAYSIZE(layout);

	// Create the input layout 
	hr = g_pD3DDevice->CreateInputLayout(layout, numElements, pVSBlob->GetBufferPointer(),
		pVSBlob->GetBufferSize(), &g_pVertexLayout);
	pVSBlob->Release();
	if (FAILED(hr))
		return;

	// Set the input layout 
	g_pD3DImmediateContext->IASetInputLayout(g_pVertexLayout);

	// Compile the pixel shader 
	ID3DBlob* pPSBlob = nullptr;
	hr = CompileShaderFromFile(L"Tutorial02.fx", "PS", "ps_4_0", &pPSBlob);
	if (FAILED(hr))
	{
		MessageBox(nullptr,
			L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK);
		return;
	}

	// Create the pixel shader 
	hr = g_pD3DDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader);
	pPSBlob->Release();
	if (FAILED(hr))
		return;

	// Create vertex buffer 
	SimpleVertex vertices[] =
	{
		XMFLOAT3(0.0f, 0.5f, 0.5f),
		XMFLOAT3(0.5f, -0.5f, 0.5f),
		XMFLOAT3(-0.5f, -0.5f, 0.5f),
	};

	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof(SimpleVertex)* 3;
	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = 0;

	D3D11_SUBRESOURCE_DATA InitData;

	ZeroMemory(&InitData, sizeof(InitData));
	InitData.pSysMem = vertices;

	hr = g_pD3DDevice->CreateBuffer(&bd, &InitData, &g_pVertexBuffer);
	if (FAILED(hr))
		return;

	// Set vertex buffer 
	UINT stride = sizeof(SimpleVertex);
	UINT offset = 0;

	g_pD3DImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);

	// Set primitive topology 
	g_pD3DImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}

void	Render()
{
	// Present the information rendered to the back buffer to the front buffer (the screen) 
	for (UINT index = 0; index <= g_nSwapchainCount - 1; index++)
	{
		g_pD3DImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView[index], nullptr);	// Set the render target

		// Clear the back buffer 
		if (index == 0)
		{
			g_pD3DImmediateContext->ClearRenderTargetView(g_pRenderTargetView[index], ClearColor);
			g_pD3DImmediateContext->RSSetState(g_pRasterStateSolid);
		}
		else
		{
			g_pD3DImmediateContext->ClearRenderTargetView(g_pRenderTargetView[index], Colors::DarkBlue);
			g_pD3DImmediateContext->RSSetState(g_pRasterStateWire);
		}

		// Draw scene know
		// Render a triangle 
		g_pD3DImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0);
		g_pD3DImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0);

		g_pD3DImmediateContext->Draw(3, 0);

		g_pSwapChain[index]->Present(0, 0);
	}
}



the shader is as follows:
//--------------------------------------------------------------------------------------
// File: Tutorial02.fx
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
float4 VS(float4 Pos : POSITION) : SV_POSITION
{
	return Pos;
}


//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS(float4 Pos : SV_POSITION) : SV_Target
{
	return float4(1.0f, 1.0f, 0.0f, 1.0f);    // Yellow, with Alpha = 1
}



Notes on the code: This code is made and compiled in Visual studio 2013 on Windows 7, using the Windows SDK for windows 7/8 for DirectX files and libraries, it wont run if you try to use the DirectX SDK.

Thank you for your input BBeck, helped get my head screwed on properly :)/>.

Edit: Having experimented with the code a bit it is not working 100% to the desired output, but I'll keep working on it till I get it to do what is needed and then update this post.

This post has been edited by Kain6622: 10 September 2014 - 03:07 AM

Was This Post Helpful? 0
  • +
  • -

#4 Kain6622  Icon User is offline

  • D.I.C Regular

Reputation: 19
  • View blog
  • Posts: 268
  • Joined: 18-March 10

Re: Multiple Windows and DirectX 11 rendering Question

Posted 12 September 2014 - 11:51 AM

Ok after some work go a final version using multi windows, still the basics but people can develop on it:

// File: Main.cpp

// Includes
#include "D3DMultiWnd.h"

// Global variables
HINSTANCE	g_hInst;
HWND	g_MainhWnd;

// Main: Entry point to our application
int WINAPI WinMain(HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow)
{
	g_hInst = hInstance; // Store instance handle in our global variable

	// Create the main application window
	CreateMainhWnd(g_hInst, L"MainWnd", WS_OVERLAPPEDWINDOW, 1040, 758, nCmdShow);

	// Create a child window
	CreateChildhWnd(g_hInst, L"Front", WS_CHILD | WS_VISIBLE | WS_BORDER, true, 0, 0, 512, 360);
	CreateChildhWnd(g_hInst, L"Size", WS_CHILD | WS_VISIBLE | WS_BORDER, true, 0, 360, 512, 360);
	CreateChildhWnd(g_hInst, L"Top", WS_CHILD | WS_VISIBLE | WS_BORDER, true, 512, 0, 512, 360);
	CreateChildhWnd(g_hInst, L"Perspective", WS_CHILD | WS_VISIBLE | WS_BORDER, true, 512, 360, 512, 360);
	//CreateChildhWnd(g_hInst, L"Shader Preview", WS_CAPTION, false, 512, 360, 512, 360);

	if (FAILED(CreateD3DDevice()))
	{
		MessageBox(nullptr, L"Couldn't Initialize Direct3D.", L"MultiWindow Yay - Error", MB_OK | MB_IConerror);
		return 0;
	}

	if (FAILED(CreateSwapChainsAndView()))
	{
		MessageBox(nullptr, L"Couldn't Initialize swapchains and stuffs.", L"MultiWindow Yay - Error", MB_OK | MB_IConerror);
		return 0;
	}

	InitScene();

	// Main message loop:
	MSG msg = { 0 };
	while (WM_QUIT != msg.message)
	{
		if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			MultiRender();
		}
	}

	ShutdownDirectX();

	return (int)msg.wParam;
}



// File: Main.h
#ifndef __MAIN_H__
#define __MAIN_H__

// -----------------------
//		Includes
// -----------------------
#include <Windows.h>
#include <vector>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <DirectXColors.h>

using namespace std;
using namespace DirectX;

// -----------------------
//		Libraries
// -----------------------
#pragma comment(lib, "D3D11.lib")
#pragma comment(lib, "DXGUID.lib")
#pragma comment(lib, "D3DCompiler.lib")

// ----------------------
//		Defines
// -----------------------
#define MAX_CHILDREN 8
#define SAFE_RELEASE(x) {if(x){x->Release(); x = nullptr;}}

// Externs
//extern vector<D3DWindowContainer*> WindowsArray;
extern D3D_DRIVER_TYPE         g_driverType;
extern D3D_FEATURE_LEVEL       g_featureLevel;
extern ID3D11Device*			g_pD3DDevice;
extern ID3D11DeviceContext*	g_pD3DImmediateContext;

// Function Declarations
void	CreateMainhWnd(HINSTANCE hInst, LPCWSTR title, DWORD style, UINT width, UINT height, UINT nCmdShow);
void	CreateChildhWnd(HINSTANCE hInst, LPCWSTR title, DWORD style, bool bStatic, UINT x, UINT y, UINT width, UINT height);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

// DirectX Functions
HRESULT	CreateD3DDevice(void);
HRESULT	CreateSwapChainsAndView(void);
HRESULT ShutdownDirectX(void);
void	InitScene(void);
void MultiRender(void);

// Example vars
HRESULT CompileShaderFromFile(WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut);

extern ID3D11VertexShader*     g_pVertexShader;
extern ID3D11PixelShader*      g_pPixelShader;
extern ID3D11InputLayout*      g_pVertexLayout;
extern ID3D11Buffer*           g_pVertexBuffer;

#endif



// File: D3DMultiWnd.cpp

// Includes
#include "D3DMultiWnd.h"

// -----------------------
// Structures and Types
// -----------------------

// Types: D3D_DRIVER_TYPE & D3D_FEATURE_LEVEL
D3D_DRIVER_TYPE driverTypes[] =
{
	D3D_DRIVER_TYPE_HARDWARE,
	D3D_DRIVER_TYPE_WARP,
	D3D_DRIVER_TYPE_REFERENCE,
};

D3D_FEATURE_LEVEL featureLevels[] =
{
	D3D_FEATURE_LEVEL_11_0,
	D3D_FEATURE_LEVEL_10_1,
	D3D_FEATURE_LEVEL_10_0,
};

ID3D11VertexShader*     g_pVertexShader = nullptr;
ID3D11PixelShader*      g_pPixelShader = nullptr;
ID3D11InputLayout*      g_pVertexLayout = nullptr;
ID3D11Buffer*           g_pVertexBuffer = nullptr;

// Struct: D3DWindowContainer
// Description: Contains required Data for all windows to render
//				in DirectX.
struct D3DWindowContainer
{
	//Direct3D 11 stuff per window
	IDXGISwapChain* swapChain;
	ID3D11RenderTargetView* renderTargetView;
	ID3D11DepthStencilView* depthStencilView;
	float					clearColor[4];

	// Window Data
	HWND hWnd;
	int width;
	int height;
};

// Struct: Simple Vertex
// Description: Vertex storing only the position Data
struct SimpleVertex
{
	XMFLOAT3 Pos;
};

// Variables
vector<D3DWindowContainer*> WindowsArray;	// Array to hold our rendering windows

D3D_DRIVER_TYPE         g_driverType = D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVEL       g_featureLevel = D3D_FEATURE_LEVEL_11_0;
ID3D11Device*			g_pD3DDevice = nullptr;
ID3D11DeviceContext*	g_pD3DImmediateContext = nullptr;


// Function Definitions
void	CreateMainhWnd(HINSTANCE hInst, LPCWSTR title, DWORD style, UINT width, UINT height, UINT nCmdShow)
{
	// Create a window contains for this window
	D3DWindowContainer* Window = new D3DWindowContainer;
	ZeroMemory(Window, sizeof(D3DWindowContainer));

	// Create the window class and register it
	WNDCLASSEX wcex;
	ZeroMemory(&wcex, sizeof(WNDCLASSEX));

	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
	wcex.hInstance = hInst;
	wcex.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
	wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = L"MainWndClass";
	wcex.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);

	if (!RegisterClassEx(&wcex))
	{
		MessageBox(NULL, L"Call to RegisterClassEx failed!", L"MultiWindow Yay", NULL);
	}

	// Create the main window
	Window->hWnd = CreateWindow(L"MainWndClass", title, style, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, 0,	hInst, NULL);

	// Show and Update the window
	ShowWindow(Window->hWnd, SW_SHOWDEFAULT);
	UpdateWindow(Window->hWnd);

	// set width and height
	Window->width = width;
	Window->height = height;
	Window->clearColor[0] = 0.75f;
	Window->clearColor[1] = 0.75f;
	Window->clearColor[2] = 1.0f;
	Window->clearColor[3] = 1.0f;

	// shove it in the std::vector
	WindowsArray.push_back(Window);

	//if first window, associate it with DXGI so it can jump in
	// when there is something of interest in the message queue
	// think fullscreen mode switches etc. MSDN for more info.
	/*if (i == 0)
		factory->MakeWindowAssociation(Window->hWnd, 0);*/
}

void	CreateChildhWnd(HINSTANCE hInst, LPCWSTR title, DWORD style, bool bStatic, UINT x, UINT y, UINT width, UINT height)
{
	// Class name var
	LPCWSTR ClassName = L"MainWndClass";
	if (bStatic)
		ClassName = L"STATIC";

	// Create a window contains for this window
	D3DWindowContainer* Window = new D3DWindowContainer;
	ZeroMemory(Window, sizeof(D3DWindowContainer));

	if (WindowsArray[0]->hWnd)
		Window->hWnd = CreateWindow(ClassName, title, style, x, y, width, height, WindowsArray[0]->hWnd, nullptr, hInst, nullptr);
	else
	{
		MessageBox(NULL, L"No Main window present to create child.", L"Error", MB_OK | MB_IConerror);
		return;
	}

	// Show and Update the window
	ShowWindow(Window->hWnd, SW_SHOW);
	UpdateWindow(Window->hWnd);

	// set width and height
	Window->width = width;
	Window->height = height;
	Window->clearColor[0] = 0.75f;
	Window->clearColor[1] = 0.75f;
	Window->clearColor[2] = 1.0f;
	Window->clearColor[3] = 1.0f;

	// shove it in the std::vector
	WindowsArray.push_back(Window);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_KEYDOWN:
		if (wParam == VK_ESCAPE)
			PostQuitMessage(0);
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	case WM_LBUTTONDOWN:
	{
						   // if the left mouse button is clicked
						   // find out which window we are clicking
						   // and return the title or do something useful
						   // ... will be useful in situations of level 
						   // editors and how to respond based on the window in use.
						   HWND wnd;
						   POINT p;
						   p.x = LOWORD(lParam);
						   p.y = HIWORD(lParam);
						   
						   //GetCursorPos(&p);
						   wnd = ChildWindowFromPoint(hWnd, p);
						   TCHAR title[256];
						   TCHAR newtext[256];
						   GetWindowText(wnd, title, 256);
						   swprintf_s(newtext, L"yay - %s was clicked", title);
						   SetWindowText(hWnd, newtext);
	}

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}

	return 0;
}

// DirectX Functions
HRESULT	CreateD3DDevice(void)
{
	HRESULT hr = S_OK;

	// if we are in debug build mode, set the device flag to include DirectX debugging
	UINT createDeviceFlags = 0;
	#ifndef _DEBUG
		createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
	#endif

	// The Driver types and feature level arrays
	UINT numDriverTypes = ARRAYSIZE(driverTypes);
	UINT numFeatureLevels = ARRAYSIZE(featureLevels);

	// Create the Direct3D Device
	for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
	{
		g_driverType = driverTypes[driverTypeIndex];

		for (UINT featureIndex = 0; featureIndex < numFeatureLevels; featureIndex++)
		{
			g_featureLevel = featureLevels[featureIndex];
			hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
				D3D11_SDK_VERSION, &g_pD3DDevice, &g_featureLevel, &g_pD3DImmediateContext);

			if (SUCCEEDED(hr))
				break;
		}

		if (SUCCEEDED(hr))
			break;
	}

	if (FAILED(hr))
		return hr;

	return hr;
}

HRESULT	CreateSwapChainsAndView(void)
{
	HRESULT hr = S_OK;

	// Obtain DXGI factory from device (since we used nullptr for pAdapter above) 
	IDXGIFactory* dxgiFactory = nullptr;
	{
		IDXGIDevice* dxgiDevice = nullptr;
		hr = g_pD3DDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
		if (SUCCEEDED(hr))
		{
			IDXGIAdapter* adapter = nullptr;
			hr = dxgiDevice->GetAdapter(&adapter);
			if (SUCCEEDED(hr))
			{
				hr = adapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&dxgiFactory));
				adapter->Release();
			}
			dxgiDevice->Release();
		}
	}

	if (FAILED(hr))
		return E_FAIL;

	UINT i = 0;

	// Check if child windows are being used
	// if so don't create a swapchain for the main window
	if (WindowsArray.size() > 1)
		i = 1;

	for (i; i < WindowsArray.size(); i++)
	{
		D3DWindowContainer* window = WindowsArray.at(i);

		// get the dxgi device
		IDXGIDevice* DXGIDevice = NULL;
		g_pD3DDevice->QueryInterface(IID_IDXGIDevice, (void**)&DXGIDevice); // COM stuff, hopefully you are familiar

		// Create swap chain 
		// DirectX 11.0 systems 
		DXGI_SWAP_CHAIN_DESC sd;
		ZeroMemory(&sd, sizeof(sd));
		sd.BufferCount = 1;
		sd.BufferDesc.Width = window->width;
		sd.BufferDesc.Height = window->height;
		sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
		sd.BufferDesc.RefreshRate.Numerator = 60;
		sd.BufferDesc.RefreshRate.Denominator = 1;
		sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
		sd.OutputWindow = window->hWnd;
		sd.SampleDesc.Count = 8;
		sd.SampleDesc.Quality = 0;
		sd.Windowed = TRUE;

		hr = dxgiFactory->CreateSwapChain(g_pD3DDevice, &sd, &window->swapChain);
		DXGIDevice->Release();
		DXGIDevice = NULL;

		// Create the backbuffer
		ID3D11Texture2D* pBackBuffer = nullptr;
		hr = window->swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer));
		if (FAILED(hr))
			return E_FAIL;

		// get the backbuffer desc
		D3D11_TEXTURE2D_DESC backBufferDesc;
		pBackBuffer->GetDesc(&backBufferDesc);

		// Create a render target view 
		hr = g_pD3DDevice->CreateRenderTargetView(pBackBuffer, nullptr, &window->renderTargetView);

		SAFE_RELEASE(pBackBuffer);

		if (FAILED(hr))
			return E_FAIL;
	}

	SAFE_RELEASE(dxgiFactory);

	return hr;
}
HRESULT ShutdownDirectX(void)
{
	HRESULT hr = S_OK;

	// Clear the immediate context state
	if (g_pD3DImmediateContext) g_pD3DImmediateContext->ClearState();

	// Release scene data
	if (g_pVertexBuffer) SAFE_RELEASE(g_pVertexBuffer);
	if (g_pVertexLayout) SAFE_RELEASE(g_pVertexLayout);
	if (g_pVertexShader) SAFE_RELEASE(g_pVertexShader);
	if (g_pPixelShader) SAFE_RELEASE(g_pPixelShader);

	// Release all D3D Devices, Context and swapchains
	UINT index = 0;
	for (index; index < WindowsArray.size(); index++)
	{
		if (WindowsArray[index]->renderTargetView)
			SAFE_RELEASE(WindowsArray[index]->renderTargetView);

		if (WindowsArray[index]->depthStencilView)
			SAFE_RELEASE(WindowsArray[index]->depthStencilView);

		if (WindowsArray[index]->swapChain)
			SAFE_RELEASE(WindowsArray[index]->swapChain);
	}

	if (g_pD3DImmediateContext) SAFE_RELEASE(g_pD3DImmediateContext);
	if (g_pD3DDevice) SAFE_RELEASE(g_pD3DDevice);

	return hr;
}

void MultiRender(void)
{
	// Clear them all
	UINT i = 0;
	if (WindowsArray.size() > 1)
		i = 1;

	for ( i; i < WindowsArray.size(); i++)
	{
		D3DWindowContainer* window = WindowsArray.at(i);

		// There is the answer to your second question:
		g_pD3DImmediateContext->OMSetRenderTargets(1, &window->renderTargetView, nullptr);

		// Don't forget to adjust the viewport, in fullscreen it's not important...
		D3D11_VIEWPORT Viewport;
		Viewport.TopLeftX = 0;
		Viewport.TopLeftY = 0;
		Viewport.Width = (FLOAT)window->width;
		Viewport.Height = (FLOAT)window->height;
		Viewport.MinDepth = 0.0f;
		Viewport.MaxDepth = 1.0f;
		g_pD3DImmediateContext->RSSetViewports(1, &Viewport);

		g_pD3DImmediateContext->ClearRenderTargetView(window->renderTargetView, window->clearColor);

		// TO DO: AMAZING STUFF PER WINDOW
		g_pD3DImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0);
		g_pD3DImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0);

		g_pD3DImmediateContext->Draw(3, 0);

		// Present to screen
		window->swapChain->Present(0, 0);
	}
}

// Helper function
HRESULT CompileShaderFromFile(WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut)
{
	HRESULT hr = S_OK;

	DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG 
	// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders. 
	// Setting this flag improves the shader debugging experience, but still allows  
	// the shaders to be optimized and to run exactly the way they will run in  
	// the release configuration of this program. 
	dwShaderFlags |= D3DCOMPILE_DEBUG;

	// Disable optimizations to further improve shader debugging 
	dwShaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
#endif 

	ID3DBlob* pErrorBlob = nullptr;
	hr = D3DCompileFromFile(szFileName, nullptr, nullptr, szEntryPoint, szShaderModel,
		dwShaderFlags, 0, ppBlobOut, &pErrorBlob);
	if (FAILED(hr))
	{
		if (pErrorBlob)
		{
			OutputDebugStringA(reinterpret_cast<const char*>(pErrorBlob->GetBufferPointer()));
			pErrorBlob->Release();
		}
		return hr;
	}
	if (pErrorBlob) pErrorBlob->Release();

	return S_OK;
}

void	InitScene()
{
	HRESULT hr;

	// Compile the vertex shader 
	ID3DBlob* pVSBlob = nullptr;
	hr = CompileShaderFromFile(L"Tutorial02.fx", "VS", "vs_4_0", &pVSBlob);
	if (FAILED(hr))
	{
		MessageBox(nullptr,
			L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK);
		return;
	}

	// Create the vertex shader 
	hr = g_pD3DDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader);
	if (FAILED(hr))
	{
		pVSBlob->Release();
		return;
	}

	// Define the input layout 
	D3D11_INPUT_ELEMENT_DESC layout[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};
	UINT numElements = ARRAYSIZE(layout);

	// Create the input layout 
	hr = g_pD3DDevice->CreateInputLayout(layout, numElements, pVSBlob->GetBufferPointer(),
		pVSBlob->GetBufferSize(), &g_pVertexLayout);
	pVSBlob->Release();
	if (FAILED(hr))
		return;

	// Set the input layout 
	g_pD3DImmediateContext->IASetInputLayout(g_pVertexLayout);

	// Compile the pixel shader 
	ID3DBlob* pPSBlob = nullptr;
	hr = CompileShaderFromFile(L"Tutorial02.fx", "PS", "ps_4_0", &pPSBlob);
	if (FAILED(hr))
	{
		MessageBox(nullptr,
			L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK);
		return;
	}

	// Create the pixel shader 
	hr = g_pD3DDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader);
	pPSBlob->Release();
	if (FAILED(hr))
		return;

	// Create vertex buffer 
	SimpleVertex vertices[] =
	{
		XMFLOAT3(0.0f, 0.5f, 0.5f),
		XMFLOAT3(0.5f, -0.5f, 0.5f),
		XMFLOAT3(-0.5f, -0.5f, 0.5f),
	};

	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));
	bd.Usage = D3D11_USAGE_DEFAULT;
	bd.ByteWidth = sizeof(SimpleVertex)* 3;
	bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	bd.CPUAccessFlags = 0;

	D3D11_SUBRESOURCE_DATA InitData;

	ZeroMemory(&InitData, sizeof(InitData));
	InitData.pSysMem = vertices;

	hr = g_pD3DDevice->CreateBuffer(&bd, &InitData, &g_pVertexBuffer);
	if (FAILED(hr))
		return;

	// Set vertex buffer 
	UINT stride = sizeof(SimpleVertex);
	UINT offset = 0;

	g_pD3DImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);

	// Set primitive topology 
	g_pD3DImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}



The same applies to the version above, it uses the windows SDK not the DirectX SDK for the DX includes and libraries. Hope people have fun with this.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1