1 / 66

C++ and DirectX for Metro style games

C++ and DirectX for Metro style games. Chas Boyd, Matt Sandy Windows Graphics Microsoft Corporation. Why Write a Metro-Style Game?. Metro-style apps have features games need Store makes monetization simple New customers: Windows tablet users

stevie
Download Presentation

C++ and DirectX for Metro style games

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C++ and DirectX for Metro style games Chas Boyd, Matt Sandy Windows Graphics Microsoft Corporation

  2. Why Write a Metro-Style Game? Metro-style apps have features games need Store makes monetization simple New customers: Windows tablet users Single API set spans tablet PCs and conventional PCs Streamlined API surface is quick to learn Key game APIs are already familiar New platform means opportunity for visibility

  3. Windows 8 PC Spectrum

  4. Agenda Quick summary of the platform Step through the developing a C++/DirectX App such as a real-time animated game: App Initialization Opening a Window Rendering Graphics Loading and Saving Adding Input Controls Adding Sound Effects

  5. Platform Overview

  6. Windows 8 Metro style apps Desktop apps View XAML DX Model Controller HTML JavaScript C# VB HTML / CSS C C++ JavaScript C C++ C# VB System Services WinRT APIs Application Model Devices & Printing Communication & Data Graphics & Media Windows Kernel Services Kernel .NET SL Internet Explorer Win32

  7. App Structure Options C++ App JS/HTML App C++ or C# App WWA Host XAML Framework Your App Framework CoreWindow Kernel: Input and DirectX

  8. FrameworkViewand CoreWindow • IFrameworkView • Effectively the new App Object class you implement • Enables OS to initialize app, deliver core OS resources • CoreWindow • Replacement for Win32 hWnd • Manages screen layout • Provides app input • Using event handler model

  9. App Activation

  10. App Model – Activation • refclassMyApp : publicIFrameworkView • { • public: • MyApp(); • // IFrameworkView Methods • virtualvoid Initialize(CoreApplicationView^ applicationView); • virtualvoidSetWindow(CoreWindow^ window); • virtualvoid Load(String^ entryPoint); • virtualvoid Run(); • virtualvoidUninitialize();

  11. App Activation Timeline Splash Screen Loading Screen Menu Screen Gameplay - OS Loads your App App Loads Loading Screen App is running Load() Run()

  12. CoreWindow

  13. Games Need Real-Time Animation • voidMyApp::Run() • { • auto dispatcher = CoreWindow::GetForCurrentThread()->Dispatcher; • while (!m_windowClosed) • { • dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); • m_renderer->Update(); • m_renderer->Render(); • m_renderer->Present(); • } • }

  14. ViewStates

  15. ViewStates: OnWindowSizeChanged • voidMyApp::SetWindow(CoreWindow^ window) • { • window->SizeChanged+= • refnewTypedEventHandler<CoreWindow^,WindowSizeChangedEventArgs^>( • this, &MyApp::OnWindowSizeChanged); • }

  16. Resize Handler • voidDirectXApp::OnWindowSizeChanged( • _In_CoreWindow^ sender, • _In_WindowSizeChangedEventArgs^ args • ) • { • if (m_window->Bounds.Width != m_windowBounds.Width || • m_window->Bounds.Height != m_windowBounds.Height) • { • m_d2dContext->SetTarget(nullptr); • m_d2dTargetBitmap = nullptr; • m_renderTargetView = nullptr; • m_depthStencilView = nullptr; • CreateWindowSizeDependentResources(); • } • }

  17. Rotation Preferences • { • DisplayOrientations::None; // Enable rotation by OS/Accelerometer • DisplayOrientations::Landscape; // Lock rotation by OS/Accelerometer • DisplayOrientations::LandscapeFlipped; // and enable this orientation • DisplayOrientations::Portrait; • DisplayOrientations::PortraitFlipped; • } • usingnamespace Windows::Graphics::Display; • DisplayProperties::AutoRotationPreferences = DisplayOrientations::Landscape • | DisplayOrientations::LandscapeFlipped;

  18. Rotation Best Practices: Support All Orientations Event-based games Solitaire, Mahjong Full-real time games For example, Arcade games Pause gameplay during animation Restart via 3 – 2 – 1 countdown When game is paused E.g. at a menu Non-game apps Accelerometer/gyro games For example, Marble Maze Augmented Reality Apps Lock Rotation

  19. Window Activation – Focus Changed • voidMyApp::OnWindowActivationChanged( • CoreWindow^ sender, • WindowActivatedEventArgs^ args) • { • auto state = args->WindowActivationState; • if(state == CoreWindowActivationState::Deactivated) • OutputDebugString("Focus Lost"); • if(state == CoreWindowActivationState::CodeActivated|| • state == CoreWindowActivationState::PointerActivated) • OutputDebugString("Focus Regained"); • }

  20. Windows 8 Game Platform Technologies Your Killer Game Graphics Movies & Cut Scenes Game Input Audio Local Services Connected Services Tools Visual Studio Direct3D DirectX Video Pointer Point Windows Live WASAPI PLM Sensor API Windows Store Direct2D Asset Viewers Media Foundation AppData XAudio2 XInput Xbox LIVE Contracts Asset Processors HTML XAML

  21. Rendering Graphics

  22. Direct3D is the Core Graphics API for Metro Style Apps • C++/DirectX is a very common game technology • Direct3D 11 is the API version for metro-style apps: • Existing Direct3D11 code should ‘just work’ • Direct3D10 code is very close to D3D11 syntax • Direct3D9 code is more work to port to D3D11, but relatively simple if you still have your DX9/10 shaders

  23. DirectX Versions • The only DirectX API version supported is DirectX11 • But the DirectX11 API operates in different “modes” called FeatureLevels • These correspond to DirectX9 and Direct10 graphics hardware generations • In each mode, the API restricts features to those supported on that class of hardware

  24. DirectX 11 Hardware Feature Level Geometry shaders Stream out 128 Textures per shader 8 Render Targets Integers in shaders Vertex textures Shader sampling Constant buffers Alpha-to-coverage Basic DirectCompute Async resource creation Full DirectCompute Random access writes Tessellation shaders New compression formats Shader linkage • Vertex shaders • Pixel shaders • 8 Textures • 4 Render Targets • Cube maps • Volume textures • Anisotropic filtering • Antialiasing • HDR rendering • Texture compression

  25. DirectX 10 Hardware Feature Level • Vertex shaders • Pixel shaders • 8 Textures • 4 Render Targets • Cube maps • Volume textures • Anisotropic filtering • Antialiasing • HDR rendering • Texture compression Geometry shaders Stream out 128 Textures per shader 8 Render Targets Integers in shaders Vertex textures Shader sampling Constant buffers Alpha-to-coverage Basic DirectCompute Async resource creation

  26. DirectX9 Hardware Feature Level • Vertex shaders • Pixel shaders • 8 Textures • 4 Render Targets • Cube maps • Volume textures • Anisotropic filtering • Antialiasing • HDR rendering • Texture compression

  27. Select Feature Levels to Support D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_1 }; UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;

  28. Create the Device and Context ComPtr<ID3D11Device> device; ComPtr<ID3D11DeviceContext> context; D3D11CreateDevice( nullptr, // use the default adapter D3D_DRIVER_TYPE_HARDWARE, 0, // use 0 unless a software device creationFlags, // defined above featureLevels, // what app will support ARRAYSIZE(featureLevels), D3D11_SDK_VERSION, // should always be D3D11_SDK_VERSION &device, // created device &m_featureLevel, // feature level of the device &context // corresponding immediate context );

  29. DirectX Control Panel

  30. Creating a swap chain • Windows::UI::Core::CoreWindow^ coreWindow; // app’s core window • Microsoft::WRL::ComPtr<ID3D11Device1> d3dDevice;// renderer • Microsoft::WRL::ComPtr<IDXGISwapChain1> dxgiSwapChain;// front/back buffers of RT • // Obtain the final swap chain for this window from the DXGI factory. • dxgiFactory->CreateSwapChainForCoreWindow( • d3dDevice.Get(), // the Direct3D device that will render to it • DX::GetIUnknown(coreWindow), // IUnknown interface on our core window • &swapChainDesc, // double or triple buffered, stereo, etc. • nullptr, // allow on all displays • &dxgiSwapChain// the resulting swap chain object • );

  31. voidmyApp::Render() • { • m_d3dContext->OMSetRenderTargets( // rebind every frame! • 1, • m_renderTargetView.GetAddressOf(), • m_depthStencilView.Get() ); • if(!m_loadingComplete) // only draw the cube once it's loaded • return; //(this is async) • m_d3dContext->IASetVertexBuffers( • 0, 1, • m_vertexBuffer.GetAddressOf(), • &stride, • &offset ); • m_d3dContext->IASetIndexBuffer( • m_indexBuffer.Get(), • DXGI_FORMAT_R16_UINT, 0 );

  32. m_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); • m_d3dContext->IASetInputLayout(m_inputLayout.Get()); • m_d3dContext->VSSetConstantBuffers( • 0, 1, • m_constantBuffer.GetAddressOf() ); • m_d3dContext->VSSetShader( m_vertexShader.Get(), • nullptr, 0 ); • m_d3dContext->PSSetShader( m_pixelShader.Get(), • nullptr, 0 ); • m_d3dContext->DrawIndexed( m_indexCount, 0, 0 ); • }

  33. Graphics Optimization Techniques • Tune Anisotropic filter quality • Simple scalar value • MultiSamplingAntiAliasing (MSAA) • Reduce sample count to maintain frame rate • Render to a lower resolution and scale up for final image • For best image quality, do not scale 2D text • Geometry • Feature_Level_11 – use tessellation for more polygon count control • Consider lower-resolution (lower vertex count) meshes

  34. Texture Quality Control • Balance visual quality with performance • Scale back on size via mipmap levels • Use block-compressed • texture formats • Loader code skips mip levels 1024 x 1024 512 x 512 256 x 256

  35. Differentiation • Increase Visual Quality • Higher resolution textures • Use bump maps

  36. Minimum PrecisionHLSL Code Sample static constfloat brightThreshold = 0.5f; Texture2DsourceTexture : register(t0); float4 DownScale3x3BrightPass(QuadVertexShaderOutput input) : SV_TARGET { float3 brightColor = 0; // Gather 16 adjacent pixels (each bilinear sample reads a 2x2 region) brightColor = sourceTexture.Sample(linearSampler, input.tex, int2(-1,-1)).rgb; brightColor += sourceTexture.Sample(linearSampler, input.tex, int2( 1,-1)).rgb; brightColor += sourceTexture.Sample(linearSampler, input.tex, int2(-1, 1)).rgb; brightColor += sourceTexture.Sample(linearSampler, input.tex, int2( 1, 1)).rgb; brightColor /= 4.0f; // Brightness thresholding brightColor = max(0, brightColor - brightThreshold); return float4(brightColor, 1.0f); }

  37. Minimum Precision OptimizationHLSL Code Sample static const min16float brightThreshold = (min16float)0.5; Texture2D<min16float4> sourceTexture : register(t0); float4 DownScale3x3BrightPass(QuadVertexShaderOutput input) : SV_TARGET { min16float3 brightColor = 0; // Gather 16 adjacent pixels (each bilinear sample reads a 2x2 region) brightColor = sourceTexture.Sample(linearSampler, input.tex, int2(-1,-1)).rgb; brightColor += sourceTexture.Sample(linearSampler, input.tex, int2( 1,-1)).rgb; brightColor += sourceTexture.Sample(linearSampler, input.tex, int2(-1, 1)).rgb; brightColor += sourceTexture.Sample(linearSampler, input.tex, int2( 1, 1)).rgb; brightColor /= (min16float)4.0; // Brightness thresholding brightColor = max(0, brightColor - brightThreshold); return float4(brightColor, 1.0f); }

  38. Development Strategy • Develop on DirectX 11 hardware • Target Feature_Level_9 and scale up • Include calibration code in game to adjust performance for current hardware • Adjust to maintain performance • Be aware of Feature Level differences • Test by restricting Feature Level or via WARP • Test on multiple PCs

  39. Saving Game State

  40. Process Lifetime Management • Suspend/Resume Apps are not notified before they are terminated App gets 5 seconds to work after suspend message suspending Running App Suspended App Terminated App User Launches App Low Memory resuming Apps are notified when they have been resumed

  41. Best Practice for Games • Save (parts of) state as often as possible • End of level, • Mid-level checkpoints, • When user pauses, • On Suspend event • Incremental data possibly every frame • If resuming mid-level, use a countdown

  42. Game Input

  43. Mouse and Touch Input • win->PointerPressed += refnewTypedEventHandler<CoreWindow^,PointerEventArgs^> • (this, &LonLatController::OnPointerPressed); • voidLonLatController::OnPointerPressed( • _In_CoreWindow^ sender, • _In_PointerEventArgs^ args • ) • { • float2position = float2( // position of contact • args->CurrentPoint->Position.X, • args->CurrentPoint->Position.Y • ); • m_lonLatLastPoint= position; // save for use in controller • m_lonLatPointerID= args->CurrentPoint->PointerId; • }

  44. Polling for Keyboard Input • // Arrow keys or WASD example • auto upKeyState = window->GetKeyAsyncState(VirtualKey::Up); • auto wKeyState = window->GetAsyncKeyState(VirtualKey::W); • if (upKeyState & CoreVirtualKeyStates::Down || • wKeyState & CoreVirtualKeyStates::Down) • { • m_playerPosition.y += 1.0f; • }

  45. Sensor fusion inputs and outputs Accelerometer 3D Accelerometer Pass-Through 3D Gyro Gyro 3D Magnetometer Sensor Fusion Compass Inclinometer Device Orientation

  46. Reading orientation sensor data • using Windows::Devices::Sensors; • // Get current reading from sensor • OrientationSensorReading^ orientationReading = m_orientationsensor->GetCurrentReading(); • SensorQuaternion^ quat = orientationReading->Quaternion; • // Transform quaternion from device orientation space to world space • // Orientation space is Z-up, right-handed coordinate system • // World space is Y-up, left-handed coordinate system • XMVECTOR orientationQuat = XMVectorSet(-quat->X, quat->Z, quat->Y, -quat->W); • // Create a rotation matrix from the quaternion • // This matrix can be used to rotate an object inside the scene to match • // the rotation of the device • XMMATRIX rotXMMatrix = XMMatrixRotationQuaternion(orientationQuat);

  47. Game Controller Input • Windows 8 supports Xbox360 -compatible controllers • Check out new ControllerSketch sample • Demonstrates game controller usage from JavaScript app

  48. Game Controller D-pad Input • SHORT thumbLeftX = inputState.Gamepad.sThumbLX; • if (abs(thumbLeftX) < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) • thumbLeftX = 0; • SHORT thumbLeftY = inputState.Gamepad.sThumbLY; • if (abs(thumbLeftY) < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) • thumbLeftY = 0; • combinedTiltX += (float)thumbLeftX / 32768.0f; • combinedTiltY += (float)thumbLeftY / 32768.0f;

  49. Game Audio

  50. Sound Effects // Create the XAudio2 engine and mastering voice on the default audio device XAudio2Create(&m_audioEngine); m_audioEngine->CreateMasteringVoice(&m_masteringVoice);// Load all audio data for the sound effect into a single in-memory buffer MediaLoadersoundFile(ref new Platform::String(SOUND_FILE));m_soundEffectBuffer = soundFile.ReadAll();// Create a single source voice for a sound effect m_audioEngine->CreateSourceVoice(&m_sourceVoice, &(soundFile.GetOutputWaveFormatEx())); // Trigger sound effect: queue in-memory buffer for playback and start the voiceXAUDIO2_BUFFER buf = {0};buf.AudioBytes = m_soundEffectBuffer.size();buf.pAudioData = &m_soundEffectBuffer[0];buf.Flags = XAUDIO2_END_OF_STREAM;m_sourceVoice->SubmitSourceBuffer(&buf);m_sourceVoice->Start();

More Related