// This sample uses DirectX SDK, specifically it depends on DirectX 11 // Please install DirectX SDK June 2010 to compile this sample #include #include #include #include #include #include "AnselSDK.h" using namespace DirectX; struct SimpleVertex { XMFLOAT3 Pos; XMFLOAT3 Normal; }; struct ConstantBuffer { XMMATRIX mWorld; XMMATRIX mView; XMMATRIX mProjection; XMFLOAT4 vLightDir; XMFLOAT4 vLightColor; XMFLOAT4 vOutputColor; float vTime; }; // Globals HINSTANCE g_hInst = nullptr; HWND g_hWnd = nullptr; 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_pImmediateContext = nullptr; IDXGISwapChain* g_pSwapChain = nullptr; ID3D11RenderTargetView* g_pRenderTargetView = nullptr; ID3D11Texture2D* g_pDepthStencil = nullptr; ID3D11DepthStencilView* g_pDepthStencilView = nullptr; ID3D11VertexShader* g_pVertexShader = nullptr; ID3D11PixelShader* g_pPixelShader = nullptr; ID3D11VertexShader* g_pHudVertexShader = nullptr; ID3D11PixelShader* g_pHudPixelShader = nullptr; ID3D11InputLayout* g_pVertexLayout = nullptr; ID3D11DepthStencilState *g_pDepthStencilStateDepthDisable = nullptr; ID3D11Buffer* g_pVertexBuffer = nullptr; ID3D11Buffer* g_pIndexBuffer = nullptr; ID3D11Buffer* g_pHudVertexBuffer = nullptr; ID3D11Buffer* g_pHudIndexBuffer = nullptr; ID3D11Buffer* g_pConstantBuffer = nullptr; XMMATRIX g_World; XMMATRIX g_View, g_ViewBackup; XMMATRIX g_Projection; bool g_Pause = false; bool g_AnselSessionIsActive = false; float g_Fov = XM_PIDIV4; uint32_t g_FrameWidth = 0u, g_FrameHeight = 0u; float g_ProjectionOffsetX = 0.0f, g_ProjectionOffsetY = 0.0f; float g_LightIntensity = 1.0f; // Forward declarations HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow); HRESULT InitDevice(); void CleanupDevice(); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void Render(); void updateProjectionMatrix() { // Before Ansel SDK integration: g_Projection = XMMatrixPerspectiveFovLH(g_Fov, g_FrameWidth / FLOAT(g_FrameHeight), 0.01f, 100.0f); // Ansel SDK integration requires projection offsetting for super resolution captures: g_Projection.r[2].m128_f32[0] = -g_ProjectionOffsetX; g_Projection.r[2].m128_f32[1] = -g_ProjectionOffsetY; } // Entry point int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); if (FAILED(InitWindow(hInstance, nCmdShow))) return 0; if (FAILED(InitDevice())) { CleanupDevice(); return 0; } // 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(); } CleanupDevice(); return int(msg.wParam); } // Register class and create window HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow) { // Register class WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_APPLICATION); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = nullptr; wcex.lpszClassName = L"SampleWindowClass"; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_APPLICATION); if (!RegisterClassEx(&wcex)) return E_FAIL; // Create window g_hInst = hInstance; RECT rc = { 0, 0, 800, 600 }; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); g_hWnd = CreateWindow(L"SampleWindowClass", L"Sample Ansel SDK Integration", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance, nullptr); if (!g_hWnd) return E_FAIL; ShowWindow(g_hWnd, nCmdShow); return S_OK; } HRESULT CompileShaderFromFile(WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut) { HRESULT hr = S_OK; ID3DBlob* pErrorBlob = nullptr; hr = D3DCompileFromFile(szFileName, nullptr, nullptr, szEntryPoint, szShaderModel, D3DCOMPILE_ENABLE_STRICTNESS, 0, ppBlobOut, &pErrorBlob); if (FAILED(hr)) { if (pErrorBlob) { OutputDebugStringA(reinterpret_cast(pErrorBlob->GetBufferPointer())); pErrorBlob->Release(); } return hr; } if (pErrorBlob) pErrorBlob->Release(); return S_OK; } // Create Direct3D device and swap chain HRESULT InitDevice() { HRESULT hr = S_OK; RECT rc; GetClientRect(g_hWnd, &rc); g_FrameWidth = rc.right - rc.left; g_FrameHeight = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_DRIVER_TYPE driverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE, }; const UINT numDriverTypes = ARRAYSIZE(driverTypes); D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, }; const UINT numFeatureLevels = ARRAYSIZE(featureLevels); for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) { g_driverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext); if (hr == E_INVALIDARG) { // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext); } if (SUCCEEDED(hr)) break; } if (FAILED(hr)) return hr; // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; { IDXGIDevice* dxgiDevice = nullptr; hr = g_pd3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&dxgiDevice)); if (SUCCEEDED(hr)) { IDXGIAdapter* adapter = nullptr; hr = dxgiDevice->GetAdapter(&adapter); if (SUCCEEDED(hr)) { hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast(&dxgiFactory)); adapter->Release(); } dxgiDevice->Release(); } } if (FAILED(hr)) return hr; // Create swap chain DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = g_FrameWidth; sd.BufferDesc.Height = g_FrameHeight; 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 = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; sd.OutputWindow = g_hWnd; hr = dxgiFactory->CreateSwapChain(g_pd3dDevice, &sd, &g_pSwapChain); if (FAILED(hr)) return hr; dxgiFactory->Release(); // Create a render target view ID3D11Texture2D* pBackBuffer = nullptr; hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast(&pBackBuffer)); if (FAILED(hr)) return hr; hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView); pBackBuffer->Release(); if (FAILED(hr)) return hr; // Create depth stencil texture D3D11_TEXTURE2D_DESC descDepth; ZeroMemory(&descDepth, sizeof(descDepth)); descDepth.Width = g_FrameWidth; descDepth.Height = g_FrameHeight; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; descDepth.SampleDesc.Count = 1; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D11_USAGE_DEFAULT; descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = 0; descDepth.MiscFlags = 0; hr = g_pd3dDevice->CreateTexture2D(&descDepth, nullptr, &g_pDepthStencil); if (FAILED(hr)) return hr; // Create the depth stencil view D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; ZeroMemory(&descDSV, sizeof(descDSV)); descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; hr = g_pd3dDevice->CreateDepthStencilView(g_pDepthStencil, &descDSV, &g_pDepthStencilView); if (FAILED(hr)) return hr; g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView); // Setup the viewport D3D11_VIEWPORT vp; vp.Width = (FLOAT)g_FrameWidth; vp.Height = (FLOAT)g_FrameHeight; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; g_pImmediateContext->RSSetViewports(1, &vp); // Compile the vertex shader ID3DBlob* pVSBlob = nullptr; hr = CompileShaderFromFile(L"Shaders.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 hr; } // Create the vertex shader hr = g_pd3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader); if (FAILED(hr)) { pVSBlob->Release(); return hr; } hr = CompileShaderFromFile(L"Shaders.fx", "VS_Hud", "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 hr; } // Create the vertex shader hr = g_pd3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pHudVertexShader); if (FAILED(hr)) { pVSBlob->Release(); return hr; } // Define the input layout D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; const 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 hr; // Set the input layout g_pImmediateContext->IASetInputLayout(g_pVertexLayout); // Compile the pixel shader ID3DBlob* pPSBlob = nullptr; hr = CompileShaderFromFile(L"Shaders.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 hr; } // Create the pixel shader hr = g_pd3dDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader); pPSBlob->Release(); if (FAILED(hr)) return hr; hr = CompileShaderFromFile(L"Shaders.fx", "PS_Hud", "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 hr; } // Create the pixel shader hr = g_pd3dDevice->CreatePixelShader(pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pHudPixelShader); pPSBlob->Release(); if (FAILED(hr)) return hr; // Create vertex buffer const SimpleVertex vertices[] = { { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, -1.0f, 0.0f) }, { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(-1.0f, 0.0f, 0.0f) }, { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, { XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, { XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, { XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, { XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, -1.0f) }, { XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, { XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, { XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, { XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, }; const SimpleVertex hud[] = { { XMFLOAT3(0.1f, -0.92f, 0.0f), XMFLOAT3(0.0f, 0.0f, 0.0f) }, { XMFLOAT3(0.9f, -0.92f, 0.0f), XMFLOAT3(2.0f, 0.0f, 0.0f) }, { XMFLOAT3(0.1f, -0.95f, 0.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, { XMFLOAT3(0.9f, -0.95f, 0.0f), XMFLOAT3(3.0f, 0.0f, 0.0f) }, }; D3D11_BUFFER_DESC bd; ZeroMemory(&bd, sizeof(bd)); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof(SimpleVertex) * 24; 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 hr; bd.ByteWidth = sizeof(SimpleVertex) * 4; InitData.pSysMem = hud; hr = g_pd3dDevice->CreateBuffer(&bd, &InitData, &g_pHudVertexBuffer); if (FAILED(hr)) return hr; // Set vertex buffer UINT stride = sizeof(SimpleVertex); UINT offset = 0; g_pImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset); // Create index buffer const WORD indices[] = { 3,1,0, 2,1,3, 6,4,5, 7,4,6, 11,9,8, 10,9,11, 14,12,13, 15,12,14, 19,17,16, 18,17,19, 22,20,21, 23,20,22 }; const WORD hud_indices[] = { 0,1,2,2,1,3 }; bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof(WORD) * 36; bd.BindFlags = D3D11_BIND_INDEX_BUFFER; bd.CPUAccessFlags = 0; InitData.pSysMem = indices; hr = g_pd3dDevice->CreateBuffer(&bd, &InitData, &g_pIndexBuffer); if (FAILED(hr)) return hr; bd.ByteWidth = sizeof(WORD) * 6; InitData.pSysMem = hud_indices; hr = g_pd3dDevice->CreateBuffer(&bd, &InitData, &g_pHudIndexBuffer); if (FAILED(hr)) return hr; // Set index buffer g_pImmediateContext->IASetIndexBuffer(g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0); // Set primitive topology g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // Create the constant buffer bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof(ConstantBuffer); bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = 0; hr = g_pd3dDevice->CreateBuffer(&bd, nullptr, &g_pConstantBuffer); if (FAILED(hr)) return hr; D3D11_DEPTH_STENCIL_DESC depthStencilDesc; depthStencilDesc.DepthEnable = FALSE; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; depthStencilDesc.StencilEnable = FALSE; depthStencilDesc.StencilReadMask = 0xFF; depthStencilDesc.StencilWriteMask = 0xFF; hr = g_pd3dDevice->CreateDepthStencilState(&depthStencilDesc, &g_pDepthStencilStateDepthDisable); if (FAILED(hr)) return hr; // Initialize the world matrices g_World = XMMatrixIdentity(); // Initialize the view matrix g_View = XMMatrixLookAtLH(XMVectorSet(0.0f, 4.0f, -10.0f, 0.0f), XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f), XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f)); // Initialize the projection matrix updateProjectionMatrix(); // Configure the Ansel SDK ansel::Configuration config; config.rotationalSpeedInDegreesPerSecond = 220.0f; config.translationalSpeedInWorldUnitsPerSecond = 50.0f; config.right = { 1.0f, 0.0f, 0.0f }; config.up = { 0.0f, 1.0f, 0.0f }; config.forward = { 0.0f, 0.0f, 1.0f }; config.captureLatency = 0; config.captureSettleLatency = 0; config.metersInWorldUnit = 2.0f; config.fovType = ansel::kVerticalFov; config.startSessionCallback = [](ansel::SessionConfiguration& conf, void* userPointer) { UNREFERENCED_PARAMETER(userPointer); UNREFERENCED_PARAMETER(conf); g_Pause = true; g_AnselSessionIsActive = true; g_ViewBackup = g_View; return ansel::kAllowed; }; config.stopSessionCallback = [](void* userPointer) { UNREFERENCED_PARAMETER(userPointer); g_Pause = false; g_AnselSessionIsActive = false; g_View = g_ViewBackup; }; config.startCaptureCallback = [](const ansel::CaptureConfiguration&, void*) { // turn non-uniform full screen effects like vignette off here }; config.stopCaptureCallback = [](void*) { // turn disabled effects back on here }; config.isCameraFovSupported = true; config.isCameraOffcenteredProjectionSupported = true; config.isCameraRotationSupported = true; config.isCameraTranslationSupported = true; config.userPointer = nullptr; config.isFilterOutsideSessionAllowed = false; config.gameWindowHandle = g_hWnd; config.titleNameUtf8 = "AnselSDKIntegration"; ansel::setConfiguration(config); // Expose light intensity setting as user control in the Ansel UI { ansel::UserControlDesc ui_position_slider; ui_position_slider.labelUtf8 = "Light intensity"; ui_position_slider.info.userControlId = 1; ui_position_slider.info.userControlType = ansel::kUserControlSlider; ui_position_slider.info.value = &g_LightIntensity; ui_position_slider.callback = [](const ansel::UserControlInfo& info) { g_LightIntensity = *reinterpret_cast(info.value); }; ansel::addUserControl(ui_position_slider); } return S_OK; } // Clean up the objects we've created void CleanupDevice() { if (g_pImmediateContext) g_pImmediateContext->ClearState(); if (g_pConstantBuffer) g_pConstantBuffer->Release(); if (g_pVertexBuffer) g_pVertexBuffer->Release(); if (g_pIndexBuffer) g_pIndexBuffer->Release(); if (g_pHudVertexBuffer) g_pVertexBuffer->Release(); if (g_pHudIndexBuffer) g_pIndexBuffer->Release(); if (g_pVertexLayout) g_pVertexLayout->Release(); if (g_pVertexShader) g_pVertexShader->Release(); if (g_pPixelShader) g_pPixelShader->Release(); if (g_pHudVertexShader) g_pVertexShader->Release(); if (g_pHudPixelShader) g_pPixelShader->Release(); if (g_pDepthStencil) g_pDepthStencil->Release(); if (g_pDepthStencilView) g_pDepthStencilView->Release(); if (g_pRenderTargetView) g_pRenderTargetView->Release(); if (g_pDepthStencilStateDepthDisable) g_pDepthStencilStateDepthDisable->Release(); if (g_pSwapChain) g_pSwapChain->Release(); if (g_pImmediateContext) g_pImmediateContext->Release(); if (g_pd3dDevice) g_pd3dDevice->Release(); } // Called every time the application receives a message LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Render a frame void Render() { // Simple solution, but not the best one: we would like to run at 100 hz Sleep(10); // Update our time static float t = 0.0f; if (!g_Pause) { static ULONGLONG timeStart = 0; ULONGLONG timeCur = GetTickCount64(); if (timeStart == 0) timeStart = timeCur; t = (timeCur - timeStart) / 1000.0f; } // Before Ansel SDK integration: // Rotate cube around the origin // g_World = XMMatrixRotationY(t); // After Ansel SDK integration: if (g_AnselSessionIsActive) { ansel::Camera cam; // set up ansel::Camera object with the current camera parameters cam.fov = (g_Fov / XM_PI) * 180.0f; cam.projectionOffsetX = g_ProjectionOffsetX; cam.projectionOffsetY = g_ProjectionOffsetY; // convert view matrix (XMMATRIX) into a pair of a position and a quaternion XMMATRIX invView = XMMatrixInverse(nullptr, g_View); const nv::Vec3 right = { invView.r[0].m128_f32[0], invView.r[0].m128_f32[1], invView.r[0].m128_f32[2] }; const nv::Vec3 up = { invView.r[1].m128_f32[0], invView.r[1].m128_f32[1], invView.r[1].m128_f32[2] }; const nv::Vec3 forward = { invView.r[2].m128_f32[0], invView.r[2].m128_f32[1], invView.r[2].m128_f32[2] }; ansel::rotationMatrixVectorsToQuaternion(right, up, forward, cam.rotation); cam.position = { invView.r[3].m128_f32[0], invView.r[3].m128_f32[1], invView.r[3].m128_f32[2] }; ansel::updateCamera(cam); // convert position and quaternion returned in ansel::updateCamera call and update camera parameters invView = DirectX::XMMatrixAffineTransformation(DirectX::XMVectorSet(1.0f, 1.0f, 1.0f, 1.0f), DirectX::XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f), DirectX::XMLoadFloat4(reinterpret_cast(&cam.rotation)), DirectX::XMLoadFloat3(reinterpret_cast(&cam.position))); g_View = XMMatrixInverse(nullptr, invView); g_Fov = (cam.fov / 180.0f) * XM_PI; g_ProjectionOffsetX = cam.projectionOffsetX; g_ProjectionOffsetY = cam.projectionOffsetY; updateProjectionMatrix(); } else g_World = XMMatrixRotationY(t); // Rotate cube around the origin // Clear the back buffer g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, Colors::MidnightBlue); // Clear the depth buffer to 1.0 (max depth) g_pImmediateContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0); // Update matrix variables and lighting variables ConstantBuffer cb1; cb1.mWorld = XMMatrixTranspose(g_World); cb1.mView = XMMatrixTranspose(g_View); cb1.mProjection = XMMatrixTranspose(g_Projection); cb1.vLightDir = XMFLOAT4(-0.577f, 0.577f, -0.577f, 1.0f); cb1.vLightColor = XMFLOAT4(0.453f * g_LightIntensity, 0.714f * g_LightIntensity, 0.105f * g_LightIntensity, 1.0f); cb1.vOutputColor = XMFLOAT4(0, 0, 0, 0); cb1.vTime = t; g_pImmediateContext->UpdateSubresource(g_pConstantBuffer, 0, nullptr, &cb1, 0, 0); // Render the cube UINT stride = sizeof(SimpleVertex); UINT offset = 0; g_pImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset); g_pImmediateContext->IASetIndexBuffer(g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0); g_pImmediateContext->VSSetShader(g_pVertexShader, nullptr, 0); g_pImmediateContext->VSSetConstantBuffers(0, 1, &g_pConstantBuffer); g_pImmediateContext->PSSetShader(g_pPixelShader, nullptr, 0); g_pImmediateContext->PSSetConstantBuffers(0, 1, &g_pConstantBuffer); g_pImmediateContext->DrawIndexed(36, 0, 0); // Render the HUD only if Ansel session is not active if (!g_AnselSessionIsActive) { g_pImmediateContext->OMSetDepthStencilState(g_pDepthStencilStateDepthDisable, 0); g_pImmediateContext->IASetVertexBuffers(0, 1, &g_pHudVertexBuffer, &stride, &offset); g_pImmediateContext->IASetIndexBuffer(g_pHudIndexBuffer, DXGI_FORMAT_R16_UINT, 0); g_pImmediateContext->VSSetShader(g_pHudVertexShader, nullptr, 0); g_pImmediateContext->PSSetShader(g_pHudPixelShader, nullptr, 0); g_pImmediateContext->DrawIndexed(6, 0, 0); } // Present our back buffer to our front buffer g_pSwapChain->Present(0, 0); }