diff options
Diffstat (limited to 'samples/AnselSDKIntegration/AnselSDKIntegration.cpp')
| -rw-r--r-- | samples/AnselSDKIntegration/AnselSDKIntegration.cpp | 731 |
1 files changed, 731 insertions, 0 deletions
diff --git a/samples/AnselSDKIntegration/AnselSDKIntegration.cpp b/samples/AnselSDKIntegration/AnselSDKIntegration.cpp new file mode 100644 index 0000000..95074f2 --- /dev/null +++ b/samples/AnselSDKIntegration/AnselSDKIntegration.cpp @@ -0,0 +1,731 @@ +// This sample uses DirectX SDK, specifically it depends on DirectX 11 +// Please install DirectX SDK June 2010 to compile this sample + +#include <windows.h> +#include <d3d11.h> +#include <d3dcompiler.h> +#include <directxmath.h> +#include <directxcolors.h> + +#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<const char*>(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<void**>(&dxgiDevice)); + if (SUCCEEDED(hr)) + { + IDXGIAdapter* adapter = nullptr; + hr = dxgiDevice->GetAdapter(&adapter); + if (SUCCEEDED(hr)) + { + hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&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<void**>(&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<const float*>(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<const XMFLOAT4*>(&cam.rotation)), + DirectX::XMLoadFloat3(reinterpret_cast<const XMFLOAT3*>(&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); +} |