Introduction to DirectX 11

Post on 14-Jan-2015

539 views 5 download

Tags:

description

A short introduction to WinAPI and DirectX 11 that I created for Game Designers' Students Club on Poznań University of Technology. It isn't finished, but still I hope I can help someone with it :) //edit: I've just found out that some text in the source code is cropped, here you can find the online version of the presentation (in which you can scroll the code): http://jotunheim.kmarciniak.com/prezentacje/directx/online/#/

Transcript of Introduction to DirectX 11

INTRODUCTION TO

Note: this was supposed to be in Polish, but Quicksanddoesn't have latin-ext subset. Sorry!

ABOUT ME on Twitter, on the Web

3rd year student of Computer Science at the PoznańUniversity of TechnologyC++ user for... quite a lot of time (since before high school)my bachelor's thesis will be about implementing realtimeglobal illumination algorithms, the example will be a gameon DirectX 11 in C++

@hun7err kmarciniak.com

WHAT IS DIRECTX?multimedia application API

2D/3D graphics (DirectDraw, Direct2D/Direct3D [D3D])sound/music (DirectSound, DirectMusic)handling input (DirectInput)

OpenGL alternative (or the other way around)

HISTORY

Source: http://www.technama.com/wp-content/uploads/2010/11/Directx-Timeline.jpg

DirectX 11.1 was released on 1st August 2012, DirectX 12 isstill to be released.

WHY DIRECTX?

GAMES USING DIRECTXBattlefield 4Call of Duty: GhostsCrysis 3The Witcher (1-3)Metro 2033...

Generally speaking AAA games on CryEngine, FrostbiteEngine, REDengine, ... (but not only AAA, small indie projects

as well)

HARDWARE VENDORSUPPORT

EXPERIENCE

SUPPORTED LANGUAGESC#C++Visual Basic (wait, what?)

DIRECTX VERSUS OPENGLRenderTargetViews and Framebuffers (no default rendertarget in DX)swapChain in DXshaders: HLSL and GLSL

INTRODUCED IN DIRECTX 11hardware tessellation supportnew RenderTarget formats like R11B11G10 (see PhilipHammer's talk on rendering in 'Lords of the Fallen' fromDigitalDragons 2014)... (to-do)

DRAWBACKSDirectX is not cross-platformDirectX API changes constantly (trust me, I've experiencedthat)WinAPI is pure evil

LET'S GO!

WINMAINheader: Windows.h

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

hInstance - handle to current instancehPrevInstance - handle to previous instancelpCmdLine - cmd line argumentsnCmdShow - how should the window appear whencreated

WNDCLASSEX - struct that holds window class information

WINDOW CREATION (1/2)

WNDCLASSEX wc;ZeroMemory(&wc, sizeof(WNDCLASSEX)); // eq. of memset(&wc, 0, sizeof(WNDCLASSEX))

wc.cbSize = sizeof(WNDCLASSEX); // size (no ****, Sherlock)wc.style = CS_HREDRAW | CS_VREDRAW; // window style: redraw after horizontal and vertical movementwc.lpfnWndProc = WindowProc; // what function shall we use to handle messages from Windows?wc.hInstance = hInstance; // application instancewc.hCursor = LoadCursor(NULL, IDC_ARROW); // guess ;-)wc.hbrBackground = (HBRUSH)COLOR_WINDOW; // ̂--wc.lpszClassName = L"MyWindowClass"; // name of the window class

RegisterClassEx(&wc); // register the window class

HWND - i ow andle

WINDOW CREATION (2/2)Wnd h

HWND CreateWindowEx(DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,// handle to application instance (again?) // spoiler: it's not the last time (noooooo-) LPVOID lpParam); // usually NULL

BOOL ShowWindow(HWND hWnd, int nCmdShow);

MESSAGE PROCESSING (1/4)

LRESULT CALLBACK WindowProc(HWND hWnd, // remember? UINT message, // message identifier WPARAM wParam, // more message information LPARAM lParam // more information about more message information);

What happens when an event occurs? Well, *we* have to:

MESSAGE PROCESSING (2/4)

use an appropriate function that gets message from thequeuecall TranslateMessage() that is used to... well, it doessomethingcall DispatchMessage() to execute the appropriateWindowProc function

Blocking calls? ain't nobody got time for that!

Passing (0,0) in (wMsgFilterMin, wMsgFilterMax) means wedon't care what we get

MESSAGE PROCESSING (3/4)

BOOL GetMessage(LPMSG lpMsg, // pointer to message struct HWND hWnd, UINT wMsgFilterMin, // lowest msg id value UINT wMsgFilterMax // highest msg id value);// ̂-- blocking, evilBOOL PeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg); // PM_REMOVE/PM_NOREMOVE

Complete main loop:

MESSAGE PROCESSING(4/4)

MSG msg = {0};while(TRUE){ if(PeekMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg);

DispatchMessage(&msg);

if(msg.message == WM_QUIT) break; } else { // rendering and other stuff (physics, AI etc.) }}

THAT'S ALL, FOLKS!

Just kidding. You thought that was all, didn't you?WindowProc function implementation:

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lparam){ switch(message) { case WM_DESTROY: { PostQuitMessage( 0); return 0; } break; } return DefWindowProc(hWnd, message, wParam, lParam);}

THE FUN PART: DIRECTX

DIRECTX(INFRA)STRUCTURE

Source: http://msdn.microsoft.com/en-us/library/windows/desktop/bb205075(v=vs.85).aspx

DXGI = Microsoft DirectX Graphics Infrastructure

returns true if HRESULT represents a failed status

DEVICE, DEVICE CONTEXTdevice - "represents the video adapter"device context - manages the gpu (important!)

BOOL FAILED( HRESULT hr);

COM = Component Object Model

call Release() on every COM object and see the world aroundyou becoming a better place.

COM OBJECTS ANDCLEANING

SwapChain is a thing that is used for setting up bufferswapping.

IDXGISwapChain interface is used for that, descriptionstored in DXGI_SWAP_CHAIN_DESC

SWAPCHAIN (1/3)

SWAPCHAIN (2/3)

typedef struct DXGI_SWAP_CHAIN_DESC { DXGI_MODE_DESC BufferDesc; DXGI_SAMPLE_DESC SampleDesc; DXGI_USAGE BufferUsage; UINT BufferCount; HWND OutputWindow; BOOL Windowed; DXGI_SWAP_EFFECT SwapEffect; UINT Flags;} DXGI_SWAP_CHAIN_DESC;

SWAPCHAIN (3/3)

typedef struct DXGI_MODE_DESC { UINT Width; UINT Height; DXGI_RATIONAL RefreshRate; DXGI_FORMAT Format; DXGI_MODE_SCANLINE_ORDER ScanlineOrdering; DXGI_MODE_SCALING Scaling;} DXGI_MODE_DESC;

typedef enum DXGI_FORMAT { DXGI_FORMAT_UNKNOWN = 0, ..., DXGI_FORMAT_R8G8B8A8_UNORM = 28, ..., DXGI_FORMAT_B4G4R4A4_UNORM = 115, DXGI_FORMAT_FORCE_UINT = 0xffffffffUL} DXGI_FORMAT;

HRESULT D3D11CreateDeviceAndSwapChain( _In_ IDXGIAdapter *pAdapter, // if NULL, uses the default adapter _In_ D3D_DRIVER_TYPE DriverType, // D3D_DRIVER_TYPE_HARDWARE/_SOFTWARE/_REFERENCE/_UNKNOWN _In_ HMODULE Software, // a handle to a DLL that implements software rasterizer if DriverType == SOFTWARE _In_ UINT Flags, _In_ const D3D_FEATURE_LEVEL *pFeatureLevels, // array of features _In_ UINT FeatureLevels, // size of pFeatureLevels _In_ UINT SDKVersion, // D3D11_SDK_VERSION _In_ const DXGI_SWAP_CHAIN_DESC *pSwapChainDesc, _Out_ IDXGISwapChain **ppSwapChain, _Out_ ID3D11Device **ppDevice, _Out_ D3D_FEATURE_LEVEL *pFeatureLevel, _Out_ ID3D11DeviceContext **ppImmediateContext);

INITIALIZATION

IDXGISwapChain *swapchain;ID3D11Device *dev;ID3D11DeviceContext *devcon;DXGI_SWAP_CHAIN_DESC scd;

ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));

scd.BufferCount = 1;scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;scd.OutputWindow = hWnd;scd.SampleDesc.Count = 4;scd.Windowed = TRUE;

D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &scd, &swapchain, &dev, NULL, &devcon);

RENDER TARGETS

__uuidof operator returns GUID

SETTING RENDER TARGET

ID3D11RenderTargetView *backbuffer;

ID3D11Texture2D *pBackBuffer;swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);// ̂-- __uuidof -> here returns const IID, LPVOID = void* (we all love void*)

dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);pBackBuffer->Release();

devcon->OMSetRenderTargets(1, &backbuffer, NULL);// The "OM" prefix in this method's name comes from the new, simplified graphics pipeline model, where subsequent stages are called: Input Assembler (IA), Vertex Shader (VS), Hull Shader (HS), Tesselator Stage, Domain Shader (DS), Geometry Shader (GS), Stream Output (SO), Rasterizer Stage (RS), Pixel Shader (PS), Output Merger (OM) and separate Compute Shader (CS)

MSDN HAS SPOKENA GUID is a 128-bit value consisting of onegroup of 8 hexadecimal digits, followed bythree groups of 4 hexadecimal digits each,followed by one group of 12 hexadecimal

digits. The following example GUID shows thegroupings of hexadecimal digits in a GUID:

6B29FC40-CA47-1067-B31D-00DD010662DA

used to translate window coordinates to normalized <-1,1>

VIEWPORTS

D3D11_VIEWPORT viewport;ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

viewport.TopLeftX = 0;viewport.TopLeftY = 0;viewport.Width = 800;viewport.Height = 600;

devcon->RSSetviewports(1, &viewport);

fullscreen: scd.Flags =DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH,

swapchain->SetFullscreenState()

PRESENTING RESULTS

HRESULT Present( [in] UINT SyncInterval, // 0 -> no synchronisation [in] UINT Flags);

HRESULT SetFullscreenState( [in] BOOL Fullscreen, [in] IDXGIOutput *pTarget);

Shaders and effects (.fx)

SHADERS, SHADERS

HRESULT WINAPI D3DCompileFromFile( in LPCWSTR pFileName, // shader file name in_opt const D3D_SHADER_MACRO *pDefines,// an array of D3D_SHADER_MACRO structures describing shader macros (I don't know what it is either) in_opt ID3DInclude *pInclude, // pointer to an ID3DInclude interface [...] // ̂-- D3D_COMPILE_STANDARD_FILE_INCLUDE is recommended instead of NULL in LPCSTR pEntrypoint, // entry point in LPCSTR pTarget, // a string specifying set of shader features (like shader model) // ̂-- vs_4_0, ps_4_0, gs_4_0, ... in UINT Flags1, // shader compile options for HLSL in UINT Flags2, // like above, but for effects out ID3DBlob **ppCode, // pointer to a blob object for compiled shader code out_opt ID3DBlob **ppErrorMsgs // );

SHADER USAGE

ID3D10Blob *pVertexShaderBlob, *pPixelShaderBlob; // that's not a mistakeID3D11VertexShader *pVertexShader, *pPixelShader; // remember to use Release(), save pandas!

D3DCompileFromFile((LPCWSTR)m_VertexShaderName.c_str(), 0, 0, m_VertexShaderEntryPointName, D3DCompileFromFile((LPCWSTR)m_PixelShaderName.c_str(), 0, 0, m_PixelShaderEntryPointName,

dev->CreateVertexShader(pVertexShaderBlob->GetBufferPointer(), pVertexShaderBlob->GetBufferSize(), NULL, &pVertexShader);dev->CreatePixelShader(...);

devcon->VSSetShader(pVertexShader);devcon->PSSetShader(pPixelShader);

HLSL CODE EXAMPLE

struct VOut{ float4 position : SV_POSITION; float4 color : COLOR;};

VOut VShader(float4 position : POSITION, float4 color : COLOR){ VOut output;

output.position = position; output.color = color;

return output;}

float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET{ return color;}

UNDER CONSTRUCTION :(

QUESTIONS?

THANK YOU FOR YOUR ATTENTION

Sources:

Microsoft Developer Network

directxtutorial.com

Raster Tek