├── 10bpc_demo ├── My10bpcdemo.rc ├── res │ ├── 10bpc_demo.ico │ └── My10bpcdemo.rc2 ├── pch.cpp ├── targetver.h ├── Popupwindow.h ├── pch.h ├── 10bpc_demo.h ├── resource.h ├── 10bpc_demoDlg.h ├── GrayscaleEffect.hlsl ├── Game.h ├── 10bpc_demo.vcxproj.filters ├── 10bpc_demo.cpp ├── GrayscaleEffect.h ├── 10bpc_demoDlg.cpp ├── framework.h ├── DeviceResources.h ├── Popupwindow.cpp ├── StepTimer.h ├── GrayscaleEffect.cpp ├── Game.cpp ├── 10bpc_demo.vcxproj ├── DeviceResources.cpp └── BasicMath.h ├── 10bpc demo application release note.docx ├── 10bpc Feature Enabling In Win10 SDR Mode user guide.docx ├── README.md ├── LICENSE └── 10bpc_demo.sln /10bpc_demo/My10bpcdemo.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/10-bit-per-color-demo/main/10bpc_demo/My10bpcdemo.rc -------------------------------------------------------------------------------- /10bpc_demo/res/10bpc_demo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/10-bit-per-color-demo/main/10bpc_demo/res/10bpc_demo.ico -------------------------------------------------------------------------------- /10bpc_demo/res/My10bpcdemo.rc2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/10-bit-per-color-demo/main/10bpc_demo/res/My10bpcdemo.rc2 -------------------------------------------------------------------------------- /10bpc demo application release note.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/10-bit-per-color-demo/main/10bpc demo application release note.docx -------------------------------------------------------------------------------- /10bpc Feature Enabling In Win10 SDR Mode user guide.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intel/10-bit-per-color-demo/main/10bpc Feature Enabling In Win10 SDR Mode user guide.docx -------------------------------------------------------------------------------- /10bpc_demo/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /10bpc_demo/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /10bpc_demo/Popupwindow.h: -------------------------------------------------------------------------------- 1 | class PopupWindow 2 | { 3 | public: 4 | 5 | PopupWindow(); 6 | ~PopupWindow(); 7 | 8 | 9 | HRESULT CreatePopupWindow(bool isPattern, LPWSTR mediaFileName); 10 | 11 | private: 12 | 13 | HINSTANCE m_hInstance = nullptr; 14 | HWND m_hWindow = nullptr; 15 | 16 | LPWSTR m_FileName = nullptr; 17 | bool m_isPattern=true; 18 | 19 | static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 20 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DISCONTINUATION OF PROJECT 2 | 3 | This project will no longer be maintained by Intel. 4 | 5 | Intel has ceased development and contributions including, but not limited to, maintenance, bug fixes, new releases, or updates, to this project. 6 | 7 | Intel no longer accepts patches to this project. 8 | 9 | If you have an ongoing need to use this project, are interested in independently developing it, or would like to maintain patches for the open source software community, please create your own fork of this project. 10 | 11 | Contact: webadmin@linux.intel.com 12 | # 10bpc_demo -------------------------------------------------------------------------------- /10bpc_demo/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // add headers that you want to pre-compile here 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /10bpc_demo/10bpc_demo.h: -------------------------------------------------------------------------------- 1 | 2 | // 10bpc_demo.h : main header file for the PROJECT_NAME application 3 | // 4 | 5 | #pragma once 6 | 7 | #ifndef __AFXWIN_H__ 8 | #error "include 'pch.h' before including this file for PCH" 9 | #endif 10 | 11 | #include "resource.h" // main symbols 12 | 13 | 14 | // C10bpcdemoApp: 15 | // See 10bpc_demo.cpp for the implementation of this class 16 | // 17 | 18 | class C10bpcdemoApp : public CWinApp 19 | { 20 | public: 21 | C10bpcdemoApp(); 22 | 23 | // Overrides 24 | public: 25 | virtual BOOL InitInstance(); 26 | 27 | // Implementation 28 | 29 | DECLARE_MESSAGE_MAP() 30 | }; 31 | 32 | extern C10bpcdemoApp theApp; 33 | -------------------------------------------------------------------------------- /10bpc_demo/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by My10bpcdemo.rc 4 | // 5 | #define IDOK2 3 6 | #define IDCREATEPATTERN 3 7 | #define IDD_MY10BPC_DEMO_DIALOG 102 8 | #define IDR_MAINFRAME 128 9 | #define IDOPENFILE 1000 10 | 11 | // Next default values for new objects 12 | // 13 | #ifdef APSTUDIO_INVOKED 14 | #ifndef APSTUDIO_READONLY_SYMBOLS 15 | #define _APS_NEXT_RESOURCE_VALUE 130 16 | #define _APS_NEXT_COMMAND_VALUE 32771 17 | #define _APS_NEXT_CONTROL_VALUE 1001 18 | #define _APS_NEXT_SYMED_VALUE 101 19 | #endif 20 | #endif 21 | -------------------------------------------------------------------------------- /10bpc_demo/10bpc_demoDlg.h: -------------------------------------------------------------------------------- 1 | 2 | // 10bpc_demoDlg.h : header file 3 | // 4 | 5 | #pragma once 6 | 7 | 8 | // C10bpcdemoDlg dialog 9 | class C10bpcdemoDlg : public CDialogEx 10 | { 11 | // Construction 12 | public: 13 | C10bpcdemoDlg(CWnd* pParent = nullptr); // standard constructor 14 | 15 | // Dialog Data 16 | #ifdef AFX_DESIGN_TIME 17 | enum { IDD = IDD_MY10BPC_DEMO_DIALOG }; 18 | #endif 19 | 20 | protected: 21 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 22 | 23 | 24 | // Implementation 25 | protected: 26 | HICON m_hIcon; 27 | 28 | // Generated message map functions 29 | virtual BOOL OnInitDialog(); 30 | afx_msg void OnPaint(); 31 | afx_msg HCURSOR OnQueryDragIcon(); 32 | DECLARE_MESSAGE_MAP() 33 | public: 34 | BOOL mFirstTime; 35 | CString mMediaFilePath; 36 | 37 | 38 | void DisplayImage(); 39 | void DisplayPattern(); 40 | afx_msg void OnBnClickedOpenfile(); 41 | afx_msg void OnBnClickedCreatepattern(); 42 | }; 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Intel Sandbox 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /10bpc_demo.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31911.196 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "10bpc_demo", "10bpc_demo\10bpc_demo.vcxproj", "{40334E22-DA0D-4F55-9830-04F888C4FFC3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {40334E22-DA0D-4F55-9830-04F888C4FFC3}.Debug|x64.ActiveCfg = Debug|x64 17 | {40334E22-DA0D-4F55-9830-04F888C4FFC3}.Debug|x64.Build.0 = Debug|x64 18 | {40334E22-DA0D-4F55-9830-04F888C4FFC3}.Debug|x86.ActiveCfg = Debug|Win32 19 | {40334E22-DA0D-4F55-9830-04F888C4FFC3}.Debug|x86.Build.0 = Debug|Win32 20 | {40334E22-DA0D-4F55-9830-04F888C4FFC3}.Release|x64.ActiveCfg = Release|x64 21 | {40334E22-DA0D-4F55-9830-04F888C4FFC3}.Release|x64.Build.0 = Release|x64 22 | {40334E22-DA0D-4F55-9830-04F888C4FFC3}.Release|x86.ActiveCfg = Release|Win32 23 | {40334E22-DA0D-4F55-9830-04F888C4FFC3}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {38AE49F2-DCB1-4645-A325-154415355875} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /10bpc_demo/GrayscaleEffect.hlsl: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | // Custom effects using pixel shaders should use HLSL helper functions defined in 13 | // d2d1effecthelpers.hlsli to make use of effect shader linking. 14 | #define D2D_INPUT_COUNT 0 // The pixel shader is a source and does not take inputs. 15 | #define D2D_REQUIRES_SCENE_POSITION // The pixel shader requires the SCENE_POSITION input. 16 | 17 | // Note that the custom build step must provide the correct path to find d2d1effecthelpers.hlsli when calling fxc.exe. 18 | #include "d2d1effecthelpers.hlsli" 19 | 20 | cbuffer constants : register(b0) 21 | { 22 | float dpi : packoffset(c0.x); 23 | float2 outputSize : packoffset(c0.y); 24 | }; 25 | 26 | D2D_PS_ENTRY(main) 27 | { 28 | float2 posScene = D2DGetScenePosition().xy; 29 | float2 pos = float2(posScene.x / outputSize.x, posScene.y / outputSize.y); 30 | 31 | float c = pos.x; 32 | c = pow(c,0.45454); 33 | c = c*0.5; 34 | 35 | if (pos.y < 0.25f) 36 | { 37 | c = trunc(c * 256.0f) / 256.0f; //8 bit per color 38 | } 39 | else if (pos.y > 0.25 && pos.y < 0.5f) 40 | { 41 | c = trunc(c * 256.0f) / 256.0f; //8 bit per color //c = trunc(c * 1024.0f) / 1024.0f; // 10 bit per color 42 | } 43 | else if (pos.y > 0.5f && pos.y < 0.75f) 44 | { 45 | c = trunc(c * 1024.0f) / 1024.0f; // 10 bit per color /c = trunc(c * 256.0f) / 256.0f; //8 bit per color 46 | } 47 | else if (pos.y > 0.75f) 48 | { 49 | c = trunc(c * 1024.0f) / 1024.0f; // 10 bit per color 50 | } 51 | 52 | c = pow(c,2.2f); 53 | 54 | float4 color_temp = { c, c, c, 1.0f }; 55 | //color_temp = { c, c, c, 1.0f }; 56 | /*if (pos.y < 0.5f) { 57 | float4 color_temp = { 0, c, 0, 1.0f }; 58 | } 59 | else { 60 | float4 color_temp = { c, c, c, 1.0f }; 61 | }*/ 62 | 63 | float4 color = color_temp; 64 | return color; 65 | } -------------------------------------------------------------------------------- /10bpc_demo/Game.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #pragma once 13 | 14 | #include "DeviceResources.h" 15 | #include "StepTimer.h" 16 | #include "Basicmath.h" 17 | #include 18 | 19 | // A basic game implementation that creates a D3D11 device and 20 | // provides a game loop. 21 | class Game : public DX::IDeviceNotify 22 | { 23 | private: 24 | 25 | HINSTANCE m_hInstance = nullptr; 26 | HWND m_hWindow = nullptr; 27 | Microsoft::WRL::ComPtr m_wicSource; // Generated from WIC. 28 | Microsoft::WRL::ComPtr m_d2dSource; // Generated from D2D. 29 | Microsoft::WRL::ComPtr m_d2dEffect; // Generated from D2D. 30 | std::wstring m_effectShaderFilename; // Empty means no shader t. 31 | GUID m_effectClsid; 32 | bool m_imageIsValid; 33 | bool m_effectIsValid; // false means effect file is missing or invalid. 34 | 35 | public: 36 | 37 | Game(PWSTR appTitle); 38 | ~Game(); 39 | // Initialization and management 40 | void Initialize(HWND window, int width, int height, LPWSTR mediaFileName); 41 | 42 | // Basic game loop 43 | void Tick(); 44 | 45 | // IDeviceNotify 46 | virtual void OnDeviceLost() override; 47 | virtual void OnDeviceRestored() override; 48 | 49 | // Messages 50 | void OnActivated(); 51 | void OnDeactivated(); 52 | void OnSuspending(); 53 | void OnResuming(); 54 | void OnWindowSizeChanged(int width, int height); 55 | 56 | 57 | // Properties 58 | void GetDefaultSize(int& width, int& height) const; 59 | 60 | 61 | void SetPattern(bool ispattern) { m_isPattern = ispattern; } 62 | private: 63 | 64 | void ConstructorInternal(); 65 | void Update(DX::StepTimer const& timer); 66 | void UpdateDxgiColorimetryInfo(); 67 | 68 | void Render(); 69 | void DrawPattern(ID2D1DeviceContext2* ctx); 70 | void DrawImageCommon(ID2D1DeviceContext2* ctx); 71 | 72 | // Common rendering subroutines. 73 | void Clear(); 74 | void CreateDeviceIndependentResources(); 75 | void CreateDeviceDependentResources(); 76 | void LoadImageResources(); 77 | void LoadEffectResources(); 78 | 79 | 80 | static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); 81 | // Device resources. 82 | std::unique_ptr m_deviceResources; 83 | 84 | DXGI_OUTPUT_DESC1 m_outputDesc; 85 | 86 | // Rendering loop timer. 87 | DX::StepTimer m_timer; 88 | float m_totalTime; 89 | 90 | PWSTR m_appTitle; 91 | LPWSTR m_FileName = nullptr; 92 | bool m_isPattern; 93 | }; -------------------------------------------------------------------------------- /10bpc_demo/10bpc_demo.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | 70 | 71 | Resource Files 72 | 73 | 74 | 75 | 76 | Resource Files 77 | 78 | 79 | 80 | 81 | Resource Files 82 | 83 | 84 | 85 | 86 | Source Files 87 | 88 | 89 | -------------------------------------------------------------------------------- /10bpc_demo/10bpc_demo.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Intel. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | // 10bpc_demo.cpp : Defines the class behaviors for the application. 12 | // 13 | 14 | #include "pch.h" 15 | #include "framework.h" 16 | #include "10bpc_demo.h" 17 | #include "10bpc_demoDlg.h" 18 | 19 | #ifdef _DEBUG 20 | #define new DEBUG_NEW 21 | #endif 22 | 23 | 24 | // C10bpcdemoApp 25 | 26 | BEGIN_MESSAGE_MAP(C10bpcdemoApp, CWinApp) 27 | ON_COMMAND(ID_HELP, &CWinApp::OnHelp) 28 | END_MESSAGE_MAP() 29 | 30 | 31 | // C10bpcdemoApp construction 32 | 33 | C10bpcdemoApp::C10bpcdemoApp() 34 | { 35 | // support Restart Manager 36 | m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART; 37 | 38 | // TODO: add construction code here, 39 | // Place all significant initialization in InitInstance 40 | } 41 | 42 | 43 | // The one and only C10bpcdemoApp object 44 | 45 | C10bpcdemoApp theApp; 46 | 47 | 48 | // C10bpcdemoApp initialization 49 | 50 | BOOL C10bpcdemoApp::InitInstance() 51 | { 52 | // InitCommonControlsEx() is required on Windows XP if an application 53 | // manifest specifies use of ComCtl32.dll version 6 or later to enable 54 | // visual styles. Otherwise, any window creation will fail. 55 | INITCOMMONCONTROLSEX InitCtrls; 56 | InitCtrls.dwSize = sizeof(InitCtrls); 57 | // Set this to include all the common control classes you want to use 58 | // in your application. 59 | InitCtrls.dwICC = ICC_WIN95_CLASSES; 60 | InitCommonControlsEx(&InitCtrls); 61 | 62 | CWinApp::InitInstance(); 63 | 64 | 65 | AfxEnableControlContainer(); 66 | 67 | // Create the shell manager, in case the dialog contains 68 | // any shell tree view or shell list view controls. 69 | CShellManager *pShellManager = new CShellManager; 70 | 71 | // Activate "Windows Native" visual manager for enabling themes in MFC controls 72 | CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows)); 73 | 74 | // Standard initialization 75 | // If you are not using these features and wish to reduce the size 76 | // of your final executable, you should remove from the following 77 | // the specific initialization routines you do not need 78 | // Change the registry key under which our settings are stored 79 | // TODO: You should modify this string to be something appropriate 80 | // such as the name of your company or organization 81 | SetRegistryKey(_T("Local AppWizard-Generated Applications")); 82 | 83 | C10bpcdemoDlg dlg; 84 | m_pMainWnd = &dlg; 85 | INT_PTR nResponse = dlg.DoModal(); 86 | if (nResponse == IDOK) 87 | { 88 | // TODO: Place code here to handle when the dialog is 89 | // dismissed with OK 90 | } 91 | else if (nResponse == IDCANCEL) 92 | { 93 | // TODO: Place code here to handle when the dialog is 94 | // dismissed with Cancel 95 | } 96 | else if (nResponse == -1) 97 | { 98 | TRACE(traceAppMsg, 0, "Warning: dialog creation failed, so application is terminating unexpectedly.\n"); 99 | TRACE(traceAppMsg, 0, "Warning: if you are using MFC controls on the dialog, you cannot #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS.\n"); 100 | } 101 | 102 | // Delete the shell manager created above. 103 | if (pShellManager != nullptr) 104 | { 105 | delete pShellManager; 106 | } 107 | 108 | #if !defined(_AFXDLL) && !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS) 109 | ControlBarCleanUp(); 110 | #endif 111 | 112 | // Since the dialog has been closed, return FALSE so that we exit the 113 | // application, rather than start the application's message pump. 114 | return FALSE; 115 | } 116 | 117 | -------------------------------------------------------------------------------- /10bpc_demo/GrayscaleEffect.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | DEFINE_GUID(GUID_GrayscaleEffectPixelShader, 0xfddf597e, 0x98d4, 0x4aac, 0x83, 0x49, 0x6f, 0xb8, 0x36, 0x36, 0x36, 0x36); 13 | DEFINE_GUID(CLSID_CustomGrayscaleEffect, 0x376c22b8, 0xe6c3, 0x41e7, 0xb1, 0xc1, 0xfb, 0x48, 0x48, 0x48, 0x48, 0x48); 14 | 15 | // Our effect contains one transform, which is simply a wrapper around a pixel shader. As such, 16 | // we can simply make the effect itself act as the transform. 17 | class GrayscaleEffect : public ID2D1EffectImpl, public ID2D1DrawTransform 18 | { 19 | public: 20 | // Declare effect registration methods. 21 | static HRESULT Register(_In_ ID2D1Factory1* pFactory); 22 | 23 | static HRESULT __stdcall CreateGrayscaleEffectImpl(_Outptr_ IUnknown** ppEffectImpl); 24 | 25 | // Declare ID2D1EffectImpl implementation methods. 26 | IFACEMETHODIMP Initialize( 27 | _In_ ID2D1EffectContext* pContextInternal, 28 | _In_ ID2D1TransformGraph* pTransformGraph 29 | ); 30 | 31 | IFACEMETHODIMP PrepareForRender(D2D1_CHANGE_TYPE changeType); 32 | 33 | IFACEMETHODIMP SetGraph(_In_ ID2D1TransformGraph* pGraph); 34 | 35 | // Declare ID2D1DrawTransform implementation methods. 36 | IFACEMETHODIMP SetDrawInfo(_In_ ID2D1DrawInfo* pRenderInfo); 37 | 38 | // Declare ID2D1Transform implementation methods. 39 | IFACEMETHODIMP MapOutputRectToInputRects( 40 | _In_ const D2D1_RECT_L* pOutputRect, 41 | _Out_writes_(inputRectCount) D2D1_RECT_L* pInputRects, 42 | UINT32 inputRectCount 43 | ) const; 44 | 45 | IFACEMETHODIMP MapInputRectsToOutputRect( 46 | _In_reads_(inputRectCount) CONST D2D1_RECT_L* pInputRects, 47 | _In_reads_(inputRectCount) CONST D2D1_RECT_L* pInputOpaqueSubRects, 48 | UINT32 inputRectCount, 49 | _Out_ D2D1_RECT_L* pOutputRect, 50 | _Out_ D2D1_RECT_L* pOutputOpaqueSubRect 51 | ); 52 | 53 | IFACEMETHODIMP MapInvalidRect( 54 | UINT32 inputIndex, 55 | D2D1_RECT_L invalidInputRect, 56 | _Out_ D2D1_RECT_L* pInvalidOutputRect 57 | ) const; 58 | 59 | // Declare ID2D1TransformNode implementation methods. 60 | IFACEMETHODIMP_(UINT32) GetInputCount() const; 61 | 62 | // Declare IUnknown implementation methods. 63 | IFACEMETHODIMP_(ULONG) AddRef(); 64 | IFACEMETHODIMP_(ULONG) Release(); 65 | IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _Outptr_ void** ppOutput); 66 | 67 | // Declare property getter/setter methods. 68 | HRESULT SetOutputSize(D2D1_POINT_2F size); 69 | D2D1_POINT_2F GetOutputSize() const; 70 | 71 | private: 72 | GrayscaleEffect(); 73 | ~GrayscaleEffect(); 74 | HRESULT UpdateConstants(); 75 | 76 | inline static float Clamp(float v, float low, float high) 77 | { 78 | return (v < low) ? low : (v > high) ? high : v; 79 | } 80 | 81 | inline static float Round(float v) 82 | { 83 | return floor(v + 0.5f); 84 | } 85 | 86 | // Prevents over/underflows when adding longs. 87 | inline static long SafeAdd(long base, long valueToAdd) 88 | { 89 | if (valueToAdd >= 0) 90 | { 91 | return ((base + valueToAdd) >= base) ? (base + valueToAdd) : LONG_MAX; 92 | } 93 | else 94 | { 95 | return ((base + valueToAdd) <= base) ? (base + valueToAdd) : LONG_MIN; 96 | } 97 | } 98 | 99 | // This struct defines the constant buffer of our pixel shader. 100 | struct 101 | { 102 | float dpi; 103 | D2D1_POINT_2F outputSize; 104 | } m_constants; 105 | 106 | Microsoft::WRL::ComPtr m_drawInfo; 107 | Microsoft::WRL::ComPtr m_effectContext; 108 | LONG m_refCount; 109 | D2D1_RECT_L m_inputRect; 110 | float m_dpi; 111 | byte* m_shaderdata; 112 | }; 113 | -------------------------------------------------------------------------------- /10bpc_demo/10bpc_demoDlg.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Intel. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | // 10bpc_demoDlg.cpp : implementation file 12 | // 13 | 14 | #include "pch.h" 15 | #include "framework.h" 16 | #include "10bpc_demo.h" 17 | #include "10bpc_demoDlg.h" 18 | #include "afxdialogex.h" 19 | #include "PopupWindow.h" 20 | 21 | // C10bpcdemoDlg dialog 22 | const PWSTR g_appTitle = L"10bpc demo"; 23 | #if 1 24 | namespace 25 | { 26 | std::unique_ptr g_popupwindow; 27 | }; 28 | #endif 29 | 30 | C10bpcdemoDlg::C10bpcdemoDlg(CWnd* pParent /*=nullptr*/) 31 | : CDialogEx(IDD_MY10BPC_DEMO_DIALOG, pParent) 32 | { 33 | m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 34 | } 35 | 36 | void C10bpcdemoDlg::DoDataExchange(CDataExchange* pDX) 37 | { 38 | CDialogEx::DoDataExchange(pDX); 39 | } 40 | 41 | BEGIN_MESSAGE_MAP(C10bpcdemoDlg, CDialogEx) 42 | ON_WM_PAINT() 43 | ON_WM_QUERYDRAGICON() 44 | ON_BN_CLICKED(IDOPENFILE, &C10bpcdemoDlg::OnBnClickedOpenfile) 45 | ON_BN_CLICKED(IDCREATEPATTERN, &C10bpcdemoDlg::OnBnClickedCreatepattern) 46 | END_MESSAGE_MAP() 47 | 48 | 49 | // C10bpcdemoDlg message handlers 50 | 51 | BOOL C10bpcdemoDlg::OnInitDialog() 52 | { 53 | CDialogEx::OnInitDialog(); 54 | 55 | // Set the icon for this dialog. The framework does this automatically 56 | // when the application's main window is not a dialog 57 | SetIcon(m_hIcon, TRUE); // Set big icon 58 | SetIcon(m_hIcon, FALSE); // Set small icon 59 | 60 | // TODO: Add extra initialization here 61 | 62 | return TRUE; // return TRUE unless you set the focus to a control 63 | } 64 | 65 | // If you add a minimize button to your dialog, you will need the code below 66 | // to draw the icon. For MFC applications using the document/view model, 67 | // this is automatically done for you by the framework. 68 | 69 | void C10bpcdemoDlg::OnPaint() 70 | { 71 | if (IsIconic()) 72 | { 73 | CPaintDC dc(this); // device context for painting 74 | 75 | SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0); 76 | 77 | // Center icon in client rectangle 78 | int cxIcon = GetSystemMetrics(SM_CXICON); 79 | int cyIcon = GetSystemMetrics(SM_CYICON); 80 | CRect rect; 81 | GetClientRect(&rect); 82 | int x = (rect.Width() - cxIcon + 1) / 2; 83 | int y = (rect.Height() - cyIcon + 1) / 2; 84 | 85 | // Draw the icon 86 | dc.DrawIcon(x, y, m_hIcon); 87 | } 88 | else 89 | { 90 | CDialogEx::OnPaint(); 91 | } 92 | 93 | if (wcslen(mMediaFilePath) > 3 && mFirstTime) 94 | { 95 | DisplayImage(); 96 | mFirstTime = FALSE; 97 | } 98 | } 99 | 100 | // The system calls this function to obtain the cursor to display while the user drags 101 | // the minimized window. 102 | HCURSOR C10bpcdemoDlg::OnQueryDragIcon() 103 | { 104 | return static_cast(m_hIcon); 105 | } 106 | 107 | 108 | 109 | void C10bpcdemoDlg::OnBnClickedOpenfile() 110 | { 111 | HRESULT hr = S_OK; 112 | 113 | CString fileName; 114 | wchar_t* p = fileName.GetBuffer(MAX_PATH + 1); 115 | CFileDialog dlgFile(TRUE); 116 | 117 | OPENFILENAME& ofn = dlgFile.GetOFN(); 118 | ofn.Flags |= OFN_ALLOWMULTISELECT; 119 | ofn.lpstrFile = p; 120 | ofn.nMaxFile = MAX_PATH + 1; 121 | 122 | ofn.lpstrFilter = L"Image Files(*.bmp, *.png, *.jpg, *.tif)\0*.bmp;*.png;*.jpg;*.tif;\0"; 123 | 124 | dlgFile.DoModal(); 125 | 126 | if (5 > fileName.GetLength()) 127 | { 128 | mMediaFilePath = fileName; 129 | LPWSTR pExtn = PathFindExtension(mMediaFilePath); 130 | 131 | DisplayImage(); 132 | 133 | } 134 | } 135 | 136 | void C10bpcdemoDlg::DisplayPattern() 137 | { 138 | g_popupwindow = std::make_unique(); 139 | 140 | HRESULT ret = g_popupwindow->CreatePopupWindow(true, NULL); 141 | g_popupwindow.reset(); 142 | } 143 | void C10bpcdemoDlg::DisplayImage() 144 | { 145 | g_popupwindow = std::make_unique(); 146 | 147 | HRESULT ret= g_popupwindow->CreatePopupWindow(false, (LPWSTR)mMediaFilePath.GetString()); 148 | g_popupwindow.reset(); 149 | } 150 | void C10bpcdemoDlg::OnBnClickedCreatepattern() 151 | { 152 | 153 | DisplayPattern(); 154 | } 155 | -------------------------------------------------------------------------------- /10bpc_demo/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef VC_EXTRALEAN 4 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers 5 | #endif 6 | 7 | #include "targetver.h" 8 | 9 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit 10 | 11 | // turns off MFC's hiding of some common and often safely ignored warning messages 12 | #define _AFX_ALL_WARNINGS 13 | 14 | #include // MFC core and standard components 15 | #include // MFC extensions 16 | 17 | 18 | #include // MFC Automation classes 19 | 20 | 21 | 22 | #ifndef _AFX_NO_OLE_SUPPORT 23 | #include // MFC support for Internet Explorer 4 Common Controls 24 | #endif 25 | #ifndef _AFX_NO_AFXCMN_SUPPORT 26 | #include // MFC support for Windows Common Controls 27 | #endif // _AFX_NO_AFXCMN_SUPPORT 28 | 29 | #include // MFC support for ribbons and control bars 30 | 31 | // Target latest OS/SDK 32 | #include 33 | 34 | // Use the C++ standard templated min/max 35 | #define NOMINMAX 36 | 37 | // Include if you need this 38 | #define NOMCX 39 | 40 | // Include if you need this 41 | #define NOSERVICE 42 | 43 | // WinHelp is deprecated 44 | #define NOHELP 45 | 46 | #define WIN32_LEAN_AND_MEAN 47 | #include 48 | #include 49 | #include 50 | 51 | #include 52 | #include 53 | 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | 63 | #include 64 | #include 65 | #include 66 | 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | #include 75 | 76 | #include 77 | 78 | namespace DX 79 | { 80 | // Helper class for COM exceptions 81 | class com_exception : public std::exception 82 | { 83 | public: 84 | com_exception(HRESULT hr) : result(hr) {} 85 | 86 | virtual const char* what() const override 87 | { 88 | static char s_str[64] = { 0 }; 89 | sprintf_s(s_str, "Failure with HRESULT of %08X", result); 90 | return s_str; 91 | } 92 | 93 | private: 94 | HRESULT result; 95 | }; 96 | 97 | // Helper utility converts D3D API failures into exceptions. 98 | inline void ThrowIfFailed(HRESULT hr) 99 | { 100 | if (FAILED(hr)) 101 | { 102 | throw com_exception(hr); 103 | } 104 | } 105 | #if 1 106 | // Formats numbers with fixed precision. 107 | template 108 | std::wstring to_string_with_precision(const T a_value, const int n = 4) 109 | { 110 | std::wstringstream out; 111 | out << std::setprecision(n) << a_value; 112 | return out.str(); 113 | } 114 | 115 | // In some environments (e.g. MSIX/desktop bridge), we have to force the absolute file path 116 | // for APIs such as WIC - even though the working directory appears to be correct. 117 | // Note this breaks file loading for cases where the working directory is not where the executable is, 118 | // for example during Visual Studio debugging. 119 | inline std::wstring GetAbsolutePath(_In_ std::wstring filename) 120 | { 121 | WCHAR wd[MAX_PATH]; 122 | DWORD length = GetModuleFileName(NULL, wd, ARRAYSIZE(wd)); 123 | PathCchRemoveFileSpec(wd, ARRAYSIZE(wd)); 124 | 125 | std::wstringstream abspath; 126 | abspath << wd << L"\\" << filename; 127 | 128 | //MessageBox(nullptr, abspath.str().c_str(), L"Full path", MB_OK); 129 | return abspath.str(); 130 | } 131 | 132 | inline HRESULT ReadDataFromFile(LPCWSTR filename, byte** data, UINT* size) 133 | { 134 | using namespace Microsoft::WRL; 135 | 136 | CREATEFILE2_EXTENDED_PARAMETERS extendedParams = {}; 137 | extendedParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); 138 | extendedParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; 139 | extendedParams.dwFileFlags = FILE_FLAG_SEQUENTIAL_SCAN; 140 | extendedParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; 141 | extendedParams.lpSecurityAttributes = nullptr; 142 | extendedParams.hTemplateFile = nullptr; 143 | 144 | Wrappers::FileHandle file(CreateFile2(filename, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &extendedParams)); 145 | if (file.Get() == INVALID_HANDLE_VALUE) 146 | { 147 | throw std::exception(); 148 | } 149 | 150 | FILE_STANDARD_INFO fileInfo = {}; 151 | if (!GetFileInformationByHandleEx(file.Get(), FileStandardInfo, &fileInfo, sizeof(fileInfo))) 152 | { 153 | throw std::exception(); 154 | } 155 | 156 | if (fileInfo.EndOfFile.HighPart != 0) 157 | { 158 | throw std::exception(); 159 | } 160 | 161 | *data = reinterpret_cast(malloc(fileInfo.EndOfFile.LowPart)); 162 | *size = fileInfo.EndOfFile.LowPart; 163 | 164 | if (!ReadFile(file.Get(), *data, fileInfo.EndOfFile.LowPart, nullptr, nullptr)) 165 | { 166 | throw std::exception(); 167 | } 168 | 169 | return S_OK; 170 | } 171 | #endif 172 | } 173 | 174 | -------------------------------------------------------------------------------- /10bpc_demo/DeviceResources.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #pragma once 13 | 14 | namespace DX 15 | { 16 | // Provides an interface for an application that owns DeviceResources to be notified of the device being lost or created. 17 | interface IDeviceNotify 18 | { 19 | virtual void OnDeviceLost() = 0; 20 | virtual void OnDeviceRestored() = 0; 21 | }; 22 | 23 | // Controls all the DirectX device resources. 24 | class DeviceResources 25 | { 26 | public: 27 | DeviceResources(DXGI_FORMAT backBufferFormat = DXGI_FORMAT_R16G16B16A16_FLOAT, 28 | DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D24_UNORM_S8_UINT, 29 | UINT backBufferCount = 2, 30 | D3D_FEATURE_LEVEL minFeatureLevel = D3D_FEATURE_LEVEL_11_0); 31 | 32 | void CreateDeviceIndependentResources(); 33 | void CreateDeviceResources(); 34 | void CreateWindowSizeDependentResources(); 35 | void SetWindow(HWND window, int width, int height); 36 | bool WindowSizeChanged(int width, int height); 37 | void SetDpi(float dpi); 38 | void HandleDeviceLost(); 39 | void RegisterDeviceNotify(IDeviceNotify* deviceNotify) { m_deviceNotify = deviceNotify; } 40 | void Present(); 41 | 42 | // The size of the render target, in pixels. 43 | RECT GetOutputSize() const { return m_outputSize; } 44 | // The size of the render target, in dips. 45 | D2D1_RECT_F GetLogicalSize() const { return m_logicalSize; } 46 | float GetDpi() const { return m_dpi; } 47 | 48 | // Direct3D Accessors. 49 | ID3D11Device3* GetD3DDevice() const { return m_d3dDevice.Get(); } 50 | ID3D11DeviceContext3* GetD3DDeviceContext() const { return m_d3dContext.Get(); } 51 | IDXGISwapChain4* GetSwapChain() const { return m_swapChain.Get(); } 52 | D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; } 53 | ID3D11Texture2D* GetRenderTarget() const { return m_renderTarget.Get(); } 54 | ID3D11Texture2D* GetDepthStencil() const { return m_depthStencil.Get(); } 55 | ID3D11RenderTargetView* GetRenderTargetView() const { return m_d3dRenderTargetView.Get(); } 56 | ID3D11DepthStencilView* GetDepthStencilView() const { return m_d3dDepthStencilView.Get(); } 57 | DXGI_FORMAT GetBackBufferFormat() const { return m_backBufferFormat; } 58 | DXGI_FORMAT GetDepthBufferFormat() const { return m_depthBufferFormat; } 59 | D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; } 60 | UINT GetBackBufferCount() const { return m_backBufferCount; } 61 | 62 | // D2D Accessors. 63 | ID2D1Factory3* GetD2DFactory() const { return m_d2dFactory.Get(); } 64 | ID2D1Device2* GetD2DDevice() const { return m_d2dDevice.Get(); } 65 | ID2D1DeviceContext2* GetD2DDeviceContext() const { return m_d2dContext.Get(); } 66 | ID2D1Bitmap1* GetD2DTargetBitmap() const { return m_d2dTargetBitmap.Get(); } 67 | IDWriteFactory3* GetDWriteFactory() const { return m_dwriteFactory.Get(); } 68 | IWICImagingFactory2* GetWicImagingFactory() const { return m_wicFactory.Get(); } 69 | 70 | // Performance events 71 | void PIXBeginEvent(_In_z_ const wchar_t* name) 72 | { 73 | if (m_d3dAnnotation) 74 | { 75 | m_d3dAnnotation->BeginEvent(name); 76 | } 77 | } 78 | 79 | void PIXEndEvent() 80 | { 81 | if (m_d3dAnnotation) 82 | { 83 | m_d3dAnnotation->EndEvent(); 84 | } 85 | } 86 | 87 | void PIXSetMarker(_In_z_ const wchar_t* name) 88 | { 89 | if (m_d3dAnnotation) 90 | { 91 | m_d3dAnnotation->SetMarker(name); 92 | } 93 | } 94 | 95 | private: 96 | void GetHardwareAdapter(IDXGIAdapter1** ppAdapter); 97 | void UpdateLogicalSize(RECT outputSize, float dpi); 98 | 99 | // Direct3D objects. 100 | Microsoft::WRL::ComPtr m_d3dDevice; 101 | Microsoft::WRL::ComPtr m_d3dContext; 102 | Microsoft::WRL::ComPtr m_swapChain; 103 | Microsoft::WRL::ComPtr m_d3dAnnotation; 104 | 105 | // Direct3D rendering objects. Required for 3D. 106 | Microsoft::WRL::ComPtr m_renderTarget; 107 | Microsoft::WRL::ComPtr m_depthStencil; 108 | Microsoft::WRL::ComPtr m_d3dRenderTargetView; 109 | Microsoft::WRL::ComPtr m_d3dDepthStencilView; 110 | D3D11_VIEWPORT m_screenViewport; 111 | 112 | // Direct2D drawing components. 113 | Microsoft::WRL::ComPtr m_d2dFactory; 114 | Microsoft::WRL::ComPtr m_d2dDevice; 115 | Microsoft::WRL::ComPtr m_d2dContext; 116 | Microsoft::WRL::ComPtr m_d2dTargetBitmap; 117 | 118 | // DirectWrite drawing components. 119 | Microsoft::WRL::ComPtr m_dwriteFactory; 120 | Microsoft::WRL::ComPtr m_wicFactory; 121 | 122 | // Direct3D properties. 123 | DXGI_FORMAT m_backBufferFormat; 124 | DXGI_FORMAT m_depthBufferFormat; 125 | UINT m_backBufferCount; 126 | 127 | // Cached device properties. 128 | HWND m_window; 129 | D3D_FEATURE_LEVEL m_d3dFeatureLevel; 130 | RECT m_outputSize; 131 | D2D1_RECT_F m_logicalSize; 132 | float m_dpi; 133 | 134 | // The IDeviceNotify can be held directly as it owns the DeviceResources. 135 | IDeviceNotify* m_deviceNotify; 136 | }; 137 | } -------------------------------------------------------------------------------- /10bpc_demo/Popupwindow.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Intel. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #include "pch.h" 13 | #include "PopupWindow.h" 14 | #include "game.h" 15 | 16 | 17 | extern void OutputDebugPrintf(const char* strOutputString, ...); 18 | #if 0 19 | SYSTEMTIME GetExpiryTime() 20 | { 21 | // Set this Time bomb to approximately one month after compilation. 22 | SYSTEMTIME expiryTime = {}; 23 | expiryTime.wYear = 2018; 24 | expiryTime.wMonth = 12; 25 | expiryTime.wDay = 31; 26 | 27 | return expiryTime; 28 | } 29 | #endif 30 | const PWSTR g_appTitle = L"10bpc demo"; 31 | namespace 32 | { 33 | std::unique_ptr g_game; 34 | }; 35 | 36 | PopupWindow::PopupWindow() 37 | { 38 | m_FileName = NULL; 39 | m_isPattern = true; 40 | // CoInitialize(NULL); 41 | } 42 | PopupWindow::~PopupWindow() 43 | { 44 | m_FileName = NULL; 45 | } 46 | 47 | HRESULT PopupWindow::CreatePopupWindow(bool isPattern, LPWSTR mediaFileName) 48 | { 49 | m_isPattern = isPattern; 50 | 51 | if (!m_isPattern) { 52 | if (NULL == mediaFileName || 3 > wcslen(mediaFileName)) 53 | { 54 | return E_FAIL; 55 | } 56 | else 57 | { 58 | m_FileName = mediaFileName; 59 | _wcslwr(m_FileName); 60 | } 61 | } 62 | 63 | m_hInstance = (HINSTANCE)GetModuleHandle(NULL); 64 | 65 | if (m_hInstance == NULL) 66 | { 67 | return E_FAIL; 68 | } 69 | g_game = std::make_unique(g_appTitle); 70 | 71 | // Register class and create window 72 | { 73 | // Register class 74 | WNDCLASSEX wcex; 75 | wcex.cbSize = sizeof(WNDCLASSEX); 76 | wcex.style = CS_HREDRAW | CS_VREDRAW; 77 | wcex.lpfnWndProc = WndProc; 78 | wcex.cbClsExtra = 0; 79 | wcex.cbWndExtra = 0; 80 | wcex.hInstance = m_hInstance; 81 | wcex.hIcon = LoadIcon(NULL, IDI_WINLOGO); 82 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 83 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 84 | wcex.lpszMenuName = nullptr; 85 | wcex.lpszClassName = L"10bpc demo"; 86 | wcex.hIconSm = LoadIcon(NULL, IDI_WINLOGO); 87 | 88 | HRESULT ret = RegisterClassEx(&wcex); 89 | //if (!RegisterClassEx(&wcex)) 90 | // return 1; 91 | 92 | // Create window 93 | int w, h; 94 | g_game->GetDefaultSize(w, h); 95 | 96 | RECT rc; 97 | rc.top = 0; 98 | rc.left = 0; 99 | rc.right = static_cast(1920); 100 | rc.bottom = static_cast(1080); 101 | 102 | AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); 103 | 104 | HWND hwnd = CreateWindowEx( 105 | 0, 106 | L"10bpc demo", 107 | g_appTitle, 108 | WS_OVERLAPPEDWINDOW, 109 | CW_USEDEFAULT, 110 | CW_USEDEFAULT, 111 | rc.right - rc.left, 112 | rc.bottom - rc.top, 113 | nullptr, 114 | nullptr, 115 | m_hInstance, 116 | nullptr); 117 | 118 | if (!hwnd) 119 | return 1; 120 | 121 | ShowWindow(hwnd, SW_SHOW); 122 | 123 | SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(g_game.get())); 124 | 125 | GetClientRect(hwnd, &rc); 126 | g_game->SetPattern(isPattern); 127 | g_game->Initialize(hwnd, 1920, 1080, m_FileName); 128 | 129 | } 130 | 131 | // Main message loop 132 | MSG msg = { 0 }; 133 | while (WM_QUIT != msg.message) 134 | { 135 | if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) 136 | { 137 | TranslateMessage(&msg); 138 | DispatchMessage(&msg); 139 | } 140 | else 141 | { 142 | g_game->Tick(); 143 | } 144 | } 145 | 146 | g_game.reset(); 147 | 148 | CoUninitialize(); 149 | 150 | return (int)msg.wParam; 151 | } 152 | 153 | LRESULT CALLBACK PopupWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 154 | { 155 | PAINTSTRUCT ps; 156 | HDC hdc; 157 | 158 | static bool s_in_sizemove = false; 159 | static bool s_in_suspend = false; 160 | static bool s_minimized = false; 161 | 162 | auto game = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); 163 | 164 | switch (message) 165 | { 166 | case WM_PAINT: 167 | hdc = BeginPaint(hWnd, &ps); 168 | EndPaint(hWnd, &ps); 169 | break; 170 | 171 | case WM_SIZE: 172 | if (wParam == SIZE_MINIMIZED) 173 | { 174 | if (!s_minimized) 175 | { 176 | s_minimized = true; 177 | if (!s_in_suspend && game) 178 | game->OnSuspending(); 179 | s_in_suspend = true; 180 | } 181 | } 182 | else if (s_minimized) 183 | { 184 | s_minimized = false; 185 | if (s_in_suspend && game) 186 | game->OnResuming(); 187 | s_in_suspend = false; 188 | } 189 | else if (!s_in_sizemove && game) 190 | { 191 | game->OnWindowSizeChanged(LOWORD(lParam), HIWORD(lParam)); 192 | } 193 | break; 194 | 195 | case WM_ENTERSIZEMOVE: 196 | s_in_sizemove = true; 197 | break; 198 | 199 | case WM_EXITSIZEMOVE: 200 | s_in_sizemove = false; 201 | if (game) 202 | { 203 | RECT rc; 204 | GetClientRect(hWnd, &rc); 205 | 206 | game->OnWindowSizeChanged(rc.right - rc.left, rc.bottom - rc.top); 207 | } 208 | break; 209 | 210 | case WM_GETMINMAXINFO: 211 | { 212 | auto info = reinterpret_cast(lParam); 213 | info->ptMinTrackSize.x = 320; 214 | info->ptMinTrackSize.y = 200; 215 | } 216 | break; 217 | 218 | case WM_ACTIVATEAPP: 219 | if (game) 220 | { 221 | if (wParam) 222 | { 223 | game->OnActivated(); 224 | } 225 | else 226 | { 227 | game->OnDeactivated(); 228 | } 229 | } 230 | break; 231 | 232 | case WM_POWERBROADCAST: 233 | switch (wParam) 234 | { 235 | case PBT_APMQUERYSUSPEND: 236 | if (!s_in_suspend && game) 237 | game->OnSuspending(); 238 | s_in_suspend = true; 239 | return TRUE; 240 | 241 | case PBT_APMRESUMESUSPEND: 242 | if (!s_minimized) 243 | { 244 | if (s_in_suspend && game) 245 | game->OnResuming(); 246 | s_in_suspend = false; 247 | } 248 | return TRUE; 249 | } 250 | break; 251 | 252 | case WM_DESTROY: 253 | PostQuitMessage(0); 254 | break; 255 | 256 | 257 | case WM_MENUCHAR: 258 | // A menu is active and the user presses a key that does not correspond 259 | // to any mnemonic or accelerator key. Ignore so we don't produce an error beep. 260 | return MAKELRESULT(0, MNC_CLOSE); 261 | } 262 | 263 | return DefWindowProc(hWnd, message, wParam, lParam); 264 | } -------------------------------------------------------------------------------- /10bpc_demo/StepTimer.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #pragma once 13 | 14 | #include 15 | #include 16 | 17 | namespace DX 18 | { 19 | // Helper class for animation and simulation timing. 20 | class StepTimer 21 | { 22 | public: 23 | StepTimer() : 24 | m_elapsedTicks(0), 25 | m_totalTicks(0), 26 | m_leftOverTicks(0), 27 | m_frameCount(0), 28 | m_framesPerSecond(0), 29 | m_framesThisSecond(0), 30 | m_qpcSecondCounter(0), 31 | m_isFixedTimeStep(false), 32 | m_targetElapsedTicks(TicksPerSecond / 60) 33 | { 34 | if (!QueryPerformanceFrequency(&m_qpcFrequency)) 35 | { 36 | throw std::exception( "QueryPerformanceFrequency" ); 37 | } 38 | 39 | if (!QueryPerformanceCounter(&m_qpcLastTime)) 40 | { 41 | throw std::exception( "QueryPerformanceCounter" ); 42 | } 43 | 44 | // Initialize max delta to 1/10 of a second. 45 | m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; 46 | } 47 | 48 | // Get elapsed time since the previous Update call. 49 | uint64_t GetElapsedTicks() const { return m_elapsedTicks; } 50 | double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } 51 | 52 | // Get total time since the start of the program. 53 | uint64_t GetTotalTicks() const { return m_totalTicks; } 54 | double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } 55 | 56 | // Get total number of updates since start of the program. 57 | uint32_t GetFrameCount() const { return m_frameCount; } 58 | 59 | // Get the current framerate. 60 | uint32_t GetFramesPerSecond() const { return m_framesPerSecond; } 61 | 62 | // Set whether to use fixed or variable timestep mode. 63 | void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } 64 | 65 | // Set how often to call Update when in fixed timestep mode. 66 | void SetTargetElapsedTicks(uint64_t targetElapsed) { m_targetElapsedTicks = targetElapsed; } 67 | void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } 68 | 69 | // Integer format represents time using 10,000,000 ticks per second. 70 | static const uint64_t TicksPerSecond = 10000000; 71 | 72 | static double TicksToSeconds(uint64_t ticks) { return static_cast(ticks) / TicksPerSecond; } 73 | static uint64_t SecondsToTicks(double seconds) { return static_cast(seconds * TicksPerSecond); } 74 | 75 | // After an intentional timing discontinuity (for instance a blocking IO operation) 76 | // call this to avoid having the fixed timestep logic attempt a set of catch-up 77 | // Update calls. 78 | 79 | void ResetElapsedTime() 80 | { 81 | if (!QueryPerformanceCounter(&m_qpcLastTime)) 82 | { 83 | throw std::exception("QueryPerformanceCounter"); 84 | } 85 | 86 | m_leftOverTicks = 0; 87 | m_framesPerSecond = 0; 88 | m_framesThisSecond = 0; 89 | m_qpcSecondCounter = 0; 90 | } 91 | 92 | // Update timer state, calling the specified Update function the appropriate number of times. 93 | template 94 | void Tick(const TUpdate& update) 95 | { 96 | // Query the current time. 97 | LARGE_INTEGER currentTime; 98 | 99 | if (!QueryPerformanceCounter(¤tTime)) 100 | { 101 | throw std::exception( "QueryPerformanceCounter" ); 102 | } 103 | 104 | uint64_t timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; 105 | 106 | m_qpcLastTime = currentTime; 107 | m_qpcSecondCounter += timeDelta; 108 | 109 | // Clamp excessively large time deltas (e.g. after paused in the debugger). 110 | if (timeDelta > m_qpcMaxDelta) 111 | { 112 | timeDelta = m_qpcMaxDelta; 113 | } 114 | 115 | // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. 116 | timeDelta *= TicksPerSecond; 117 | timeDelta /= m_qpcFrequency.QuadPart; 118 | 119 | uint32_t lastFrameCount = m_frameCount; 120 | 121 | if (m_isFixedTimeStep) 122 | { 123 | // Fixed timestep update logic 124 | 125 | // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp 126 | // the clock to exactly match the target value. This prevents tiny and irrelevant errors 127 | // from accumulating over time. Without this clamping, a game that requested a 60 fps 128 | // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually 129 | // accumulate enough tiny errors that it would drop a frame. It is better to just round 130 | // small deviations down to zero to leave things running smoothly. 131 | 132 | if (abs(static_cast(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) 133 | { 134 | timeDelta = m_targetElapsedTicks; 135 | } 136 | 137 | m_leftOverTicks += timeDelta; 138 | 139 | while (m_leftOverTicks >= m_targetElapsedTicks) 140 | { 141 | m_elapsedTicks = m_targetElapsedTicks; 142 | m_totalTicks += m_targetElapsedTicks; 143 | m_leftOverTicks -= m_targetElapsedTicks; 144 | m_frameCount++; 145 | 146 | update(); 147 | } 148 | } 149 | else 150 | { 151 | // Variable timestep update logic. 152 | m_elapsedTicks = timeDelta; 153 | m_totalTicks += timeDelta; 154 | m_leftOverTicks = 0; 155 | m_frameCount++; 156 | 157 | update(); 158 | } 159 | 160 | // Track the current framerate. 161 | if (m_frameCount != lastFrameCount) 162 | { 163 | m_framesThisSecond++; 164 | } 165 | 166 | if (m_qpcSecondCounter >= static_cast(m_qpcFrequency.QuadPart)) 167 | { 168 | m_framesPerSecond = m_framesThisSecond; 169 | m_framesThisSecond = 0; 170 | m_qpcSecondCounter %= m_qpcFrequency.QuadPart; 171 | } 172 | } 173 | 174 | private: 175 | // Source timing data uses QPC units. 176 | LARGE_INTEGER m_qpcFrequency; 177 | LARGE_INTEGER m_qpcLastTime; 178 | uint64_t m_qpcMaxDelta; 179 | 180 | // Derived timing data uses a canonical tick format. 181 | uint64_t m_elapsedTicks; 182 | uint64_t m_totalTicks; 183 | uint64_t m_leftOverTicks; 184 | 185 | // Members for tracking the framerate. 186 | uint32_t m_frameCount; 187 | uint32_t m_framesPerSecond; 188 | uint32_t m_framesThisSecond; 189 | uint64_t m_qpcSecondCounter; 190 | 191 | // Members for configuring fixed timestep mode. 192 | bool m_isFixedTimeStep; 193 | uint64_t m_targetElapsedTicks; 194 | }; 195 | } 196 | -------------------------------------------------------------------------------- /10bpc_demo/GrayscaleEffect.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | #include "pch.h" 12 | #include 13 | #include "GrayscaleEffect.h" 14 | 15 | #define XML(X) TEXT(#X) 16 | 17 | GrayscaleEffect::GrayscaleEffect() : 18 | m_refCount(1), 19 | m_constants{} 20 | { 21 | } 22 | GrayscaleEffect::~GrayscaleEffect() { 23 | if (m_shaderdata) 24 | free(m_shaderdata); 25 | 26 | } 27 | 28 | HRESULT __stdcall GrayscaleEffect::CreateGrayscaleEffectImpl(_Outptr_ IUnknown** ppEffectImpl) 29 | { 30 | // Since the object's refcount is initialized to 1, we don't need to AddRef here. 31 | *ppEffectImpl = static_cast(new (std::nothrow) GrayscaleEffect()); 32 | 33 | if (*ppEffectImpl == nullptr) 34 | { 35 | return E_OUTOFMEMORY; 36 | } 37 | else 38 | { 39 | return S_OK; 40 | } 41 | } 42 | 43 | HRESULT GrayscaleEffect::Register(_In_ ID2D1Factory1* pFactory) 44 | { 45 | // The inspectable metadata of an effect is defined in XML. This can be passed in from an external source 46 | // as well, however for simplicity we just inline the XML. 47 | PCWSTR pszXml = 48 | XML( 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | ); 64 | 65 | const D2D1_PROPERTY_BINDING bindings[] = 66 | { 67 | D2D1_VALUE_TYPE_BINDING(L"OutputSize", &SetOutputSize, &GetOutputSize), 68 | }; 69 | 70 | // This registers the effect with the factory, which will make the effect 71 | // instantiatable. 72 | return pFactory->RegisterEffectFromString( 73 | CLSID_CustomGrayscaleEffect, 74 | pszXml, 75 | bindings, 76 | ARRAYSIZE(bindings), 77 | CreateGrayscaleEffectImpl 78 | ); 79 | } 80 | 81 | IFACEMETHODIMP GrayscaleEffect::Initialize( 82 | _In_ ID2D1EffectContext* pEffectContext, 83 | _In_ ID2D1TransformGraph* pTransformGraph 84 | ) 85 | { 86 | // To maintain consistency across different DPIs, this effect needs to cover more pixels at 87 | // higher than normal DPIs. The context is saved here so the effect can later retrieve the DPI. 88 | m_effectContext = pEffectContext; 89 | 90 | //byte* data = nullptr; 91 | m_shaderdata = nullptr; 92 | UINT size = 0; 93 | 94 | HRESULT hr = S_OK; 95 | 96 | try 97 | { 98 | DX::ReadDataFromFile(DX::GetAbsolutePath(std::wstring(L"GrayscaleEffect.cso")).c_str(), &m_shaderdata, &size); 99 | } 100 | catch (std::exception) 101 | { 102 | // Most likely is caused by a missing or invalid file. 103 | hr = D2DERR_FILE_NOT_FOUND; 104 | } 105 | 106 | if (SUCCEEDED(hr)) 107 | { 108 | hr = pEffectContext->LoadPixelShader(GUID_GrayscaleEffectPixelShader, m_shaderdata, size); 109 | } 110 | 111 | // This loads the shader into the Direct2D image effects system and associates it with the GUID passed in. 112 | // If this method is called more than once (say by other instances of the effect) with the same GUID, 113 | // the system will simply do nothing, ensuring that only one instance of a shader is stored regardless of how 114 | // many time it is used. 115 | if (SUCCEEDED(hr)) 116 | { 117 | // The graph consists of a single transform. In fact, this class is the transform, 118 | // reducing the complexity of implementing an effect when all we need to 119 | // do is use a single pixel shader. 120 | hr = pTransformGraph->SetSingleTransformNode(this); 121 | } 122 | 123 | return hr; 124 | } 125 | 126 | HRESULT GrayscaleEffect::UpdateConstants() 127 | { 128 | // Update the DPI if it has changed. This allows the effect to scale across different DPIs automatically. 129 | m_effectContext->GetDpi(&m_dpi, &m_dpi); 130 | m_constants.dpi = m_dpi; 131 | 132 | return m_drawInfo->SetPixelShaderConstantBuffer(reinterpret_cast(&m_constants), sizeof(m_constants)); 133 | } 134 | 135 | IFACEMETHODIMP GrayscaleEffect::PrepareForRender(D2D1_CHANGE_TYPE changeType) 136 | { 137 | return UpdateConstants(); 138 | } 139 | 140 | // SetGraph is only called when the number of inputs changes. This never happens as we publish this effect 141 | // as a single input effect. 142 | IFACEMETHODIMP GrayscaleEffect::SetGraph(_In_ ID2D1TransformGraph* pGraph) 143 | { 144 | return E_NOTIMPL; 145 | } 146 | 147 | // Called to assign a new render info class, which is used to inform D2D on 148 | // how to set the state of the GPU. 149 | IFACEMETHODIMP GrayscaleEffect::SetDrawInfo(_In_ ID2D1DrawInfo* pDrawInfo) 150 | { 151 | m_drawInfo = pDrawInfo; 152 | 153 | return m_drawInfo->SetPixelShader(GUID_GrayscaleEffectPixelShader); 154 | } 155 | 156 | // Calculates the mapping between the output and input rects. 157 | IFACEMETHODIMP GrayscaleEffect::MapOutputRectToInputRects( 158 | _In_ const D2D1_RECT_L* pOutputRect, 159 | _Out_writes_(inputRectCount) D2D1_RECT_L* pInputRects, 160 | UINT32 inputRectCount 161 | ) const 162 | { 163 | // This effect has no inputs. 164 | if (inputRectCount != 0) 165 | { 166 | return E_INVALIDARG; 167 | } 168 | 169 | // There should never be any inputs to map to. 170 | 171 | return S_OK; 172 | } 173 | 174 | IFACEMETHODIMP GrayscaleEffect::MapInputRectsToOutputRect( 175 | _In_reads_(inputRectCount) CONST D2D1_RECT_L* pInputRects, 176 | _In_reads_(inputRectCount) CONST D2D1_RECT_L* pInputOpaqueSubRects, 177 | UINT32 inputRectCount, 178 | _Out_ D2D1_RECT_L* pOutputRect, 179 | _Out_ D2D1_RECT_L* pOutputOpaqueSubRect 180 | ) 181 | { 182 | // This effect has no inputs. 183 | if (inputRectCount != 0) 184 | { 185 | return E_INVALIDARG; 186 | } 187 | 188 | // The output is infinite and always opaque. 189 | *pOutputRect = { LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX }; 190 | *pOutputOpaqueSubRect = { LONG_MIN, LONG_MIN, LONG_MAX, LONG_MAX }; 191 | 192 | return S_OK; 193 | } 194 | 195 | IFACEMETHODIMP GrayscaleEffect::MapInvalidRect( 196 | UINT32 inputIndex, 197 | D2D1_RECT_L invalidInputRect, 198 | _Out_ D2D1_RECT_L* pInvalidOutputRect 199 | ) const 200 | { 201 | HRESULT hr = S_OK; 202 | 203 | // Indicate that the entire output may be invalid. 204 | *pInvalidOutputRect = m_inputRect; 205 | 206 | return hr; 207 | } 208 | 209 | IFACEMETHODIMP_(UINT32) GrayscaleEffect::GetInputCount() const 210 | { 211 | return 0; 212 | } 213 | 214 | // D2D ensures that that effects are only referenced from one thread at a time. 215 | // To improve performance, we simply increment/decrement our reference count 216 | // rather than use atomic InterlockedIncrement()/InterlockedDecrement() functions. 217 | IFACEMETHODIMP_(ULONG) GrayscaleEffect::AddRef() 218 | { 219 | m_refCount++; 220 | return m_refCount; 221 | } 222 | 223 | IFACEMETHODIMP_(ULONG) GrayscaleEffect::Release() 224 | { 225 | m_refCount--; 226 | 227 | if (m_refCount == 0) 228 | { 229 | delete this; 230 | return 0; 231 | } 232 | else 233 | { 234 | return m_refCount; 235 | } 236 | } 237 | 238 | 239 | IFACEMETHODIMP GrayscaleEffect::QueryInterface( 240 | _In_ REFIID riid, 241 | _Outptr_ void** ppOutput 242 | ) 243 | { 244 | *ppOutput = nullptr; 245 | HRESULT hr = S_OK; 246 | 247 | if (riid == __uuidof(ID2D1EffectImpl)) 248 | { 249 | *ppOutput = reinterpret_cast(this); 250 | } 251 | else if (riid == __uuidof(ID2D1DrawTransform)) 252 | { 253 | *ppOutput = static_cast(this); 254 | } 255 | else if (riid == __uuidof(ID2D1Transform)) 256 | { 257 | *ppOutput = static_cast(this); 258 | } 259 | else if (riid == __uuidof(ID2D1TransformNode)) 260 | { 261 | *ppOutput = static_cast(this); 262 | } 263 | else if (riid == __uuidof(IUnknown)) 264 | { 265 | *ppOutput = this; 266 | } 267 | else 268 | { 269 | hr = E_NOINTERFACE; 270 | } 271 | 272 | if (*ppOutput != nullptr) 273 | { 274 | AddRef(); 275 | } 276 | 277 | return hr; 278 | } 279 | 280 | // Size in pixels. 281 | HRESULT GrayscaleEffect::SetOutputSize(D2D1_POINT_2F size) 282 | { 283 | m_constants.outputSize = size; 284 | return S_OK; 285 | } 286 | 287 | D2D1_POINT_2F GrayscaleEffect::GetOutputSize() const 288 | { 289 | return m_constants.outputSize; 290 | } 291 | -------------------------------------------------------------------------------- /10bpc_demo/Game.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #include "pch.h" 13 | #include "winioctl.h" 14 | #include "ntddvdeo.h" 15 | 16 | #include "Game.h" 17 | #include "GrayscaleEffect.h" 18 | 19 | #include 20 | #include 21 | 22 | 23 | #include "atlbase.h" 24 | #include "atlstr.h" 25 | 26 | void OutputDebugPrintf(const char* strOutputString, ...) 27 | { 28 | char strBuffer[4096] = { 0 }; 29 | va_list vlArgs; 30 | va_start(vlArgs, strOutputString); 31 | 32 | _vsnprintf_s(strBuffer, sizeof(strBuffer) - 1, strOutputString, vlArgs); 33 | va_end(vlArgs); 34 | OutputDebugString(CA2W(strBuffer)); 35 | } 36 | 37 | 38 | 39 | //using namespace concurrency; 40 | 41 | using namespace winrt::Windows::Devices; 42 | using namespace winrt::Windows::Devices::Display; 43 | using namespace winrt::Windows::Devices::Enumeration; 44 | 45 | extern void ExitGame(); 46 | 47 | using namespace DirectX; 48 | using Microsoft::WRL::ComPtr; 49 | 50 | 51 | Game::Game(PWSTR appTitle) 52 | { 53 | m_appTitle = appTitle; 54 | CoInitialize(NULL); 55 | 56 | ConstructorInternal(); 57 | } 58 | Game::~Game() 59 | { 60 | //OutputDebugPrintf("%s \n", __FUNCTION__); 61 | if(m_d2dEffect) 62 | m_d2dEffect.Reset(); 63 | if (m_d2dSource) 64 | m_d2dSource.Reset(); 65 | if (m_deviceResources) 66 | m_deviceResources.reset(); 67 | } 68 | void Game::ConstructorInternal() 69 | { 70 | m_deviceResources = std::make_unique(); 71 | m_effectShaderFilename = std::wstring(L"GrayscaleEffect.cso"); 72 | m_effectClsid = CLSID_CustomGrayscaleEffect; 73 | 74 | m_deviceResources->RegisterDeviceNotify(this); 75 | } 76 | 77 | // Initialize the Direct3D resources required to run. 78 | void Game::Initialize(HWND window, int width, int height, LPWSTR mediaFileName) 79 | { 80 | m_FileName = mediaFileName; 81 | 82 | m_deviceResources->SetWindow(window, width, height); 83 | m_deviceResources->CreateDeviceResources(); 84 | m_deviceResources->SetDpi(96.0f); // TODO: using default 96 DPI for now 85 | m_deviceResources->CreateWindowSizeDependentResources(); 86 | 87 | CreateDeviceIndependentResources(); 88 | CreateDeviceDependentResources(); 89 | } 90 | 91 | // Updates the world. 92 | void Game::Update(DX::StepTimer const& timer) 93 | { 94 | m_deviceResources->PIXBeginEvent(L"Update"); 95 | 96 | float elapsedTime = float(timer.GetElapsedSeconds()); 97 | 98 | // TODO: Add your game logic here. 99 | elapsedTime; 100 | 101 | m_deviceResources->PIXEndEvent(); 102 | } 103 | 104 | // Executes the basic game loop. 105 | void Game::Tick() 106 | { 107 | m_timer.Tick([&]() 108 | { 109 | Update(m_timer); 110 | }); 111 | 112 | Render(); 113 | } 114 | 115 | void Game::UpdateDxgiColorimetryInfo() 116 | { 117 | // Output information is cached on the DXGI Factory. If it is stale we need to create 118 | // a new factory and re-enumerate the displays. 119 | auto d3dDevice = m_deviceResources->GetD3DDevice(); 120 | 121 | ComPtr dxgiDevice; 122 | DX::ThrowIfFailed(d3dDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice))); 123 | 124 | ComPtr dxgiAdapter; 125 | DX::ThrowIfFailed(dxgiDevice->GetAdapter(&dxgiAdapter)); 126 | 127 | ComPtr dxgiFactory; 128 | DX::ThrowIfFailed(dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))); 129 | 130 | // if (!dxgiFactory->IsCurrent()) 131 | { 132 | DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory))); 133 | } 134 | 135 | // Get information about the display we are presenting to. 136 | ComPtr output; 137 | auto sc = m_deviceResources->GetSwapChain(); 138 | DX::ThrowIfFailed(sc->GetContainingOutput(&output)); 139 | 140 | ComPtr output6; 141 | output.As(&output6); 142 | 143 | DX::ThrowIfFailed(output6->GetDesc1(&m_outputDesc)); 144 | 145 | } 146 | 147 | void Game::DrawPattern(ID2D1DeviceContext2 * ctx) //******************* 7. 148 | { 149 | auto rect = m_deviceResources->GetOutputSize(); 150 | 151 | if (!m_effectIsValid) 152 | { 153 | 154 | MessageBox(m_hWindow, L"ERROR: GrayscaleEffect.cso is missing\n",NULL, MB_OK); 155 | } 156 | else 157 | { 158 | DX::ThrowIfFailed(m_d2dEffect->SetValueByName( 159 | L"OutputSize", 160 | D2D1::Point2F((float)rect.right - rect.left, (float)rect.bottom - rect.top))); 161 | 162 | ctx->DrawImage(m_d2dEffect.Get()); 163 | } 164 | 165 | } 166 | 167 | // Common method to render an image test pattern to the screen. 168 | void Game::DrawImageCommon(ID2D1DeviceContext2* ctx) 169 | { 170 | if (m_imageIsValid == true) 171 | { 172 | // Center the image, draw at 1.0x (pixel) zoom. 173 | // TODO: Currently we force all D2D rendering to 96 DPI regardless of display DPI. 174 | // Therefore DIPs = pixels. 175 | auto targetSize = m_deviceResources->GetOutputSize(); 176 | unsigned int width, height; 177 | DX::ThrowIfFailed(m_wicSource->GetSize(&width, &height)); 178 | 179 | float dX = (targetSize.right - targetSize.left - static_cast(width)) / 2.0f; 180 | float dY = (targetSize.bottom - targetSize.top - static_cast(height)) / 2.0f; 181 | 182 | ctx->DrawImage(m_d2dSource.Get(), D2D1::Point2F(dX, dY)); 183 | } 184 | 185 | } 186 | 187 | // Draws the scene. 188 | void Game::Render() 189 | { 190 | m_deviceResources->PIXBeginEvent(L"Render"); 191 | 192 | Clear(); 193 | 194 | auto ctx = m_deviceResources->GetD2DDeviceContext(); 195 | 196 | ctx->BeginDraw(); 197 | 198 | if(m_isPattern) 199 | DrawPattern(ctx); 200 | else 201 | DrawImageCommon(ctx); 202 | 203 | HRESULT hr = ctx->EndDraw(); 204 | if (hr != D2DERR_RECREATE_TARGET) 205 | { 206 | DX::ThrowIfFailed(hr); 207 | } 208 | 209 | m_deviceResources->PIXEndEvent(); 210 | 211 | // Show the new frame. 212 | m_deviceResources->Present(); 213 | } 214 | 215 | // Helper method to clear the back buffers. 216 | void Game::Clear() 217 | { 218 | m_deviceResources->PIXBeginEvent(L"Clear"); 219 | 220 | // Clear the views. 221 | auto context = m_deviceResources->GetD3DDeviceContext(); 222 | auto renderTarget = m_deviceResources->GetRenderTargetView(); 223 | auto depthStencil = m_deviceResources->GetDepthStencilView(); 224 | 225 | context->ClearRenderTargetView(renderTarget, Colors::Black); 226 | context->ClearDepthStencilView(depthStencil, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); 227 | 228 | context->OMSetRenderTargets(1, &renderTarget, depthStencil); 229 | 230 | // Set the viewport. 231 | auto viewport = m_deviceResources->GetScreenViewport(); 232 | context->RSSetViewports(1, &viewport); 233 | 234 | m_deviceResources->PIXEndEvent(); 235 | } 236 | 237 | // Message handlers 238 | void Game::OnActivated() 239 | { 240 | // TODO: Game is becoming active window. 241 | } 242 | 243 | void Game::OnDeactivated() 244 | { 245 | // TODO: Game is becoming background window. 246 | } 247 | 248 | void Game::OnSuspending() 249 | { 250 | // TODO: Game is being power-suspended (or minimized). 251 | } 252 | 253 | void Game::OnResuming() 254 | { 255 | m_timer.ResetElapsedTime(); 256 | 257 | // TODO: Game is being power-resumed (or returning from minimize). 258 | } 259 | 260 | void Game::OnWindowSizeChanged(int width, int height) 261 | { 262 | // Window size changed also corresponds to switching monitors. 263 | if (!m_deviceResources->WindowSizeChanged(width, height)) 264 | return; 265 | } 266 | 267 | // Properties 268 | void Game::GetDefaultSize(int& width, int& height) const 269 | { 270 | width = 1920; 271 | height = 1080; 272 | } 273 | 274 | 275 | #pragma region Direct3D Resources 276 | void Game::CreateDeviceIndependentResources() 277 | { 278 | auto dwFactory = m_deviceResources->GetDWriteFactory(); 279 | DX::ThrowIfFailed(GrayscaleEffect::Register(m_deviceResources->GetD2DFactory())); 280 | } 281 | 282 | 283 | // These are the resources that depend on the device. 284 | void Game::CreateDeviceDependentResources() 285 | { 286 | auto ctx = m_deviceResources->GetD2DDeviceContext(); 287 | 288 | if (m_isPattern) 289 | LoadEffectResources(); 290 | else 291 | LoadImageResources(); 292 | 293 | UpdateDxgiColorimetryInfo(); 294 | 295 | } 296 | 297 | void Game::LoadImageResources() 298 | { 299 | auto wicFactory = m_deviceResources->GetWicImagingFactory(); 300 | auto ctx = m_deviceResources->GetD2DDeviceContext(); 301 | 302 | // This test involves an image file. 303 | if (m_FileName != 0) 304 | { 305 | // First, ensure that there is a WIC source (device independent). 306 | if (m_wicSource == nullptr) 307 | { 308 | ComPtr decoder; 309 | HRESULT hr = wicFactory->CreateDecoderFromFilename( 310 | m_FileName, 311 | nullptr, 312 | GENERIC_READ, 313 | WICDecodeMetadataCacheOnDemand, 314 | &decoder); 315 | 316 | if FAILED(hr) 317 | { 318 | if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) 319 | { 320 | m_imageIsValid = false; 321 | return; 322 | } 323 | else 324 | { 325 | DX::ThrowIfFailed(hr); 326 | } 327 | } 328 | 329 | ComPtr frame; 330 | DX::ThrowIfFailed(decoder->GetFrame(0, &frame)); 331 | 332 | // Always convert to FP16 for JXR support. We ignore color profiles in this tool. 333 | WICPixelFormatGUID outFmt = GUID_WICPixelFormat64bppPRGBAHalf; 334 | 335 | ComPtr converter; 336 | DX::ThrowIfFailed(wicFactory->CreateFormatConverter(&converter)); 337 | DX::ThrowIfFailed(converter->Initialize( 338 | frame.Get(), 339 | outFmt, 340 | WICBitmapDitherTypeNone, 341 | nullptr, 342 | 0.0f, 343 | WICBitmapPaletteTypeCustom)); 344 | 345 | DX::ThrowIfFailed(converter.As(&m_wicSource)); 346 | } 347 | 348 | // Next, ensure that there is a D2D source (device dependent). 349 | if (m_d2dSource == nullptr) 350 | { 351 | assert(m_wicSource != nullptr); 352 | 353 | DX::ThrowIfFailed(ctx->CreateImageSourceFromWic(m_wicSource.Get(), &m_d2dSource)); 354 | 355 | // The image is only valid if both WIC and D2D resources are ready. 356 | m_imageIsValid = true; 357 | } 358 | } 359 | } 360 | 361 | void Game::LoadEffectResources() 362 | { 363 | auto ctx = m_deviceResources->GetD2DDeviceContext(); 364 | // This test involves a shader file. 365 | if (m_effectShaderFilename.compare(L"") != 0) 366 | { 367 | assert(m_effectClsid != GUID{}); 368 | 369 | try 370 | { 371 | DX::ThrowIfFailed(ctx->CreateEffect(m_effectClsid, &m_d2dEffect)); 372 | m_effectIsValid = true; 373 | } 374 | catch (std::exception) 375 | { 376 | // Most likely caused by a missing cso file. Continue on. 377 | m_effectIsValid = false; 378 | } 379 | } 380 | } 381 | 382 | void Game::OnDeviceLost() 383 | { 384 | 385 | } 386 | 387 | void Game::OnDeviceRestored() 388 | { 389 | // CreateDeviceDependentResources(); 390 | 391 | } 392 | #pragma endregion 393 | -------------------------------------------------------------------------------- /10bpc_demo/10bpc_demo.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {40334E22-DA0D-4F55-9830-04F888C4FFC3} 24 | MFCProj 25 | My10bpcdemo 26 | 10.0.19041.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | Dynamic 35 | 36 | 37 | Application 38 | false 39 | v142 40 | true 41 | Unicode 42 | Dynamic 43 | 44 | 45 | Application 46 | true 47 | v142 48 | Unicode 49 | Static 50 | 51 | 52 | Application 53 | false 54 | v142 55 | false 56 | Unicode 57 | Static 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | 80 | 81 | true 82 | 83 | 84 | false 85 | 86 | 87 | false 88 | 89 | 90 | 91 | Use 92 | Level3 93 | true 94 | WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 95 | pch.h 96 | stdcpp17 97 | 98 | 99 | Windows 100 | d3d11.lib;d3dcompiler.lib;dxguid.lib;Dcomp.lib;DXGI.lib;mfplay.lib;Setupapi.lib;d2d1.lib;windowscodecs.lib;dwrite.lib;dxgi.lib;uuid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;odbc32.lib;odbccp32.lib;onecoreuap.lib;pathcch.lib;%(AdditionalDependencies) 101 | 102 | 103 | false 104 | true 105 | _DEBUG;%(PreprocessorDefinitions) 106 | 107 | 108 | 0x0409 109 | _DEBUG;%(PreprocessorDefinitions) 110 | $(IntDir);%(AdditionalIncludeDirectories) 111 | 112 | 113 | Pixel 114 | 115 | 116 | 117 | 118 | Use 119 | Level3 120 | true 121 | _WINDOWS;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 122 | pch.h 123 | stdcpp17 124 | 125 | 126 | Windows 127 | d3d11.lib;d3dcompiler.lib;dxguid.lib;Dcomp.lib;DXGI.lib;mfplay.lib;Setupapi.lib;d2d1.lib;windowscodecs.lib;dwrite.lib;dxgi.lib;uuid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;odbc32.lib;odbccp32.lib;onecoreuap.lib;pathcch.lib;%(AdditionalDependencies) 128 | 129 | 130 | false 131 | true 132 | _DEBUG;%(PreprocessorDefinitions) 133 | 134 | 135 | 0x0409 136 | _DEBUG;%(PreprocessorDefinitions) 137 | $(IntDir);%(AdditionalIncludeDirectories) 138 | 139 | 140 | Pixel 141 | true 142 | 143 | 144 | 145 | 146 | Use 147 | Level3 148 | true 149 | true 150 | true 151 | WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) 152 | pch.h 153 | 154 | 155 | Windows 156 | true 157 | true 158 | 159 | 160 | false 161 | true 162 | NDEBUG;%(PreprocessorDefinitions) 163 | 164 | 165 | 0x0409 166 | NDEBUG;%(PreprocessorDefinitions) 167 | $(IntDir);%(AdditionalIncludeDirectories) 168 | 169 | 170 | 171 | 172 | Use 173 | Level3 174 | true 175 | true 176 | true 177 | _WINDOWS;NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 178 | pch.h 179 | stdcpp17 180 | 181 | 182 | Windows 183 | true 184 | true 185 | d3d11.lib;d3dcompiler.lib;dxguid.lib;Dcomp.lib;DXGI.lib;mfplay.lib;Setupapi.lib;d2d1.lib;windowscodecs.lib;dwrite.lib;dxgi.lib;uuid.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;odbc32.lib;odbccp32.lib;onecoreuap.lib;pathcch.lib;%(AdditionalDependencies) 186 | 187 | 188 | false 189 | true 190 | NDEBUG;%(PreprocessorDefinitions) 191 | 192 | 193 | 0x0409 194 | NDEBUG;%(PreprocessorDefinitions) 195 | $(IntDir);%(AdditionalIncludeDirectories) 196 | 197 | 198 | $(WindowsSDK_IncludePath) 199 | Pixel 200 | true 201 | true 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | Create 223 | Create 224 | Create 225 | Create 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | $(WindowsSDK_IncludePath) 241 | $(WindowsSDK_IncludePath) 242 | true 243 | false 244 | 245 | 246 | 247 | 248 | 249 | -------------------------------------------------------------------------------- /10bpc_demo/DeviceResources.cpp: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | #include "pch.h" 12 | #include "DeviceResources.h" 13 | 14 | using namespace DirectX; 15 | 16 | using Microsoft::WRL::ComPtr; 17 | 18 | namespace 19 | { 20 | #if defined(_DEBUG) 21 | // Check for SDK Layer support. 22 | inline bool SdkLayersAvailable() noexcept 23 | { 24 | HRESULT hr = D3D11CreateDevice( 25 | nullptr, 26 | D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device. 27 | nullptr, 28 | D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers. 29 | nullptr, // Any feature level will do. 30 | 0, 31 | D3D11_SDK_VERSION, 32 | nullptr, // No need to keep the D3D device reference. 33 | nullptr, // No need to know the feature level. 34 | nullptr // No need to keep the D3D device context reference. 35 | ); 36 | 37 | return SUCCEEDED(hr); 38 | } 39 | #endif 40 | }; 41 | #include "atlbase.h" 42 | #include "atlstr.h" 43 | 44 | void OutputDebugPrintf(const char* strOutputString, ...); 45 | 46 | 47 | // Constructor for DeviceResources. 48 | DX::DeviceResources::DeviceResources( 49 | DXGI_FORMAT backBufferFormat, 50 | DXGI_FORMAT depthBufferFormat, 51 | UINT backBufferCount, 52 | D3D_FEATURE_LEVEL minFeatureLevel) : 53 | m_screenViewport{}, 54 | m_backBufferFormat(backBufferFormat), 55 | m_depthBufferFormat(depthBufferFormat), 56 | m_backBufferCount(backBufferCount), 57 | m_window(nullptr), 58 | m_d3dFeatureLevel(D3D_FEATURE_LEVEL_9_1), 59 | m_outputSize{0, 0, 1, 1}, 60 | m_deviceNotify(nullptr), 61 | m_dpi(-1.0f) // Require DPI to be explicitly set. 62 | { 63 | CreateDeviceIndependentResources(); 64 | } 65 | 66 | // Configures resources that don't depend on the Direct3D device. 67 | void DX::DeviceResources::CreateDeviceIndependentResources() 68 | { 69 | // Initialize Direct2D resources. 70 | D2D1_FACTORY_OPTIONS options; 71 | ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS)); 72 | 73 | #if defined(_DEBUG) 74 | // If the project is in a debug build, enable Direct2D debugging via SDK Layers. 75 | options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; 76 | #endif 77 | 78 | // Initialize the Direct2D Factory. 79 | DX::ThrowIfFailed( 80 | D2D1CreateFactory( 81 | D2D1_FACTORY_TYPE_SINGLE_THREADED, 82 | __uuidof(ID2D1Factory5), 83 | &options, 84 | &m_d2dFactory 85 | ) 86 | ); 87 | 88 | // Initialize the DirectWrite Factory. 89 | DX::ThrowIfFailed( 90 | DWriteCreateFactory( 91 | DWRITE_FACTORY_TYPE_SHARED, 92 | __uuidof(IDWriteFactory3), 93 | &m_dwriteFactory 94 | ) 95 | ); 96 | 97 | // Initialize the Windows Imaging Component (WIC) Factory. 98 | DX::ThrowIfFailed( 99 | CoCreateInstance( 100 | CLSID_WICImagingFactory2, 101 | nullptr, 102 | CLSCTX_INPROC_SERVER, 103 | IID_PPV_ARGS(&m_wicFactory) 104 | ) 105 | ); 106 | } 107 | 108 | // Configures the Direct3D device, and stores handles to it and the device context. 109 | void DX::DeviceResources::CreateDeviceResources() 110 | { 111 | UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; 112 | 113 | #if defined(_DEBUG) 114 | if (SdkLayersAvailable()) 115 | { 116 | // If the project is in a debug build, enable debugging via SDK Layers with this flag. 117 | creationFlags |= D3D11_CREATE_DEVICE_DEBUG; 118 | } 119 | else 120 | { 121 | OutputDebugStringA("WARNING: Direct3D Debug Device is not available\n"); 122 | } 123 | #endif 124 | 125 | // Determine DirectX hardware feature levels this app will support. 126 | static const D3D_FEATURE_LEVEL s_featureLevels[] = 127 | { 128 | D3D_FEATURE_LEVEL_11_1, 129 | D3D_FEATURE_LEVEL_11_0, 130 | D3D_FEATURE_LEVEL_10_1, 131 | D3D_FEATURE_LEVEL_10_0, 132 | D3D_FEATURE_LEVEL_9_3, 133 | D3D_FEATURE_LEVEL_9_2, 134 | D3D_FEATURE_LEVEL_9_1, 135 | }; 136 | 137 | ComPtr adapter; 138 | GetHardwareAdapter(adapter.GetAddressOf()); 139 | 140 | // Create the Direct3D 11 API device object and a corresponding context. 141 | ComPtr device; 142 | ComPtr context; 143 | 144 | HRESULT hr = E_FAIL; 145 | if (adapter) 146 | { 147 | hr = D3D11CreateDevice( 148 | adapter.Get(), 149 | D3D_DRIVER_TYPE_UNKNOWN, 150 | nullptr, 151 | creationFlags, 152 | s_featureLevels, 153 | ARRAYSIZE(s_featureLevels), 154 | D3D11_SDK_VERSION, 155 | device.GetAddressOf(), // Returns the Direct3D device created. 156 | &m_d3dFeatureLevel, // Returns feature level of device created. 157 | context.GetAddressOf() // Returns the device immediate context. 158 | ); 159 | } 160 | #if defined(NDEBUG) 161 | else 162 | { 163 | throw std::exception("No Direct3D hardware device found"); 164 | } 165 | #else 166 | if (FAILED(hr)) 167 | { 168 | // If the initialization fails, fall back to the WARP device. 169 | // For more information on WARP, see: 170 | // http://go.microsoft.com/fwlink/?LinkId=286690 171 | DX::ThrowIfFailed(D3D11CreateDevice( 172 | nullptr, 173 | D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device. 174 | nullptr, 175 | creationFlags, 176 | s_featureLevels, 177 | ARRAYSIZE(s_featureLevels), 178 | D3D11_SDK_VERSION, 179 | device.GetAddressOf(), 180 | &m_d3dFeatureLevel, 181 | context.GetAddressOf() 182 | )); 183 | 184 | if (SUCCEEDED(hr)) 185 | { 186 | OutputDebugStringA("Direct3D Adapter - WARP\n"); 187 | } 188 | } 189 | #endif 190 | 191 | // Store pointers to the Direct3D 11.3 API device and immediate context. 192 | DX::ThrowIfFailed( 193 | device.As(&m_d3dDevice) 194 | ); 195 | 196 | DX::ThrowIfFailed( 197 | context.As(&m_d3dContext) 198 | ); 199 | 200 | #ifndef NDEBUG 201 | ComPtr d3dDebug; 202 | if (SUCCEEDED(m_d3dDevice.As(&d3dDebug))) 203 | { 204 | ComPtr d3dInfoQueue; 205 | if (SUCCEEDED(d3dDebug.As(&d3dInfoQueue))) 206 | { 207 | #ifdef _DEBUG 208 | d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); 209 | d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); 210 | #endif 211 | D3D11_MESSAGE_ID hide [] = 212 | { 213 | D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, 214 | }; 215 | D3D11_INFO_QUEUE_FILTER filter = {}; 216 | filter.DenyList.NumIDs = _countof(hide); 217 | filter.DenyList.pIDList = hide; 218 | d3dInfoQueue->AddStorageFilterEntries(&filter); 219 | } 220 | } 221 | #endif 222 | 223 | // Create the Direct2D device object and a corresponding context. 224 | ComPtr dxgiDevice; 225 | DX::ThrowIfFailed( 226 | m_d3dDevice.As(&dxgiDevice) 227 | ); 228 | 229 | DX::ThrowIfFailed( 230 | m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice) 231 | ); 232 | 233 | DX::ThrowIfFailed( 234 | m_d2dDevice->CreateDeviceContext( 235 | D2D1_DEVICE_CONTEXT_OPTIONS_NONE, 236 | &m_d2dContext 237 | ) 238 | ); 239 | } 240 | 241 | // These resources need to be recreated every time the window size is changed. 242 | void DX::DeviceResources::CreateWindowSizeDependentResources() 243 | { 244 | if (!m_window) 245 | { 246 | throw std::exception("Call SetWindow with a valid Win32 window handle"); 247 | } 248 | 249 | // Clear the previous window size specific context. 250 | ID3D11RenderTargetView* nullViews[] = {nullptr}; 251 | m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr); 252 | m_d3dRenderTargetView.Reset(); 253 | m_d3dDepthStencilView.Reset(); 254 | m_renderTarget.Reset(); 255 | m_d2dContext->SetTarget(nullptr); 256 | m_d2dTargetBitmap.Reset(); 257 | m_depthStencil.Reset(); 258 | m_d3dContext->Flush(); // Why can't I call Flush1? 259 | 260 | // Determine the render target size in pixels. 261 | UINT backBufferWidth = std::max(m_outputSize.right - m_outputSize.left, 1); 262 | UINT backBufferHeight = std::max(m_outputSize.bottom - m_outputSize.top, 1); 263 | 264 | if (m_swapChain) 265 | { 266 | // If the swap chain already exists, resize it. 267 | HRESULT hr = m_swapChain->ResizeBuffers( 268 | m_backBufferCount, 269 | backBufferWidth, 270 | backBufferHeight, 271 | m_backBufferFormat, 272 | 0 273 | ); 274 | 275 | if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) 276 | { 277 | #ifdef _DEBUG 278 | char buff[64] = {}; 279 | sprintf_s(buff, "Device Lost on ResizeBuffers: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); 280 | OutputDebugStringA(buff); 281 | #endif 282 | // If the device was removed for any reason, a new device and swap chain will need to be created. 283 | HandleDeviceLost(); 284 | 285 | // Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method 286 | // and correctly set up the new device. 287 | return; 288 | } 289 | else 290 | { 291 | DX::ThrowIfFailed(hr); 292 | } 293 | } 294 | else 295 | { 296 | // Otherwise, create a new one using the same adapter as the existing Direct3D device. 297 | 298 | // This sequence obtains the DXGI factory that was used to create the Direct3D device above. 299 | ComPtr dxgiDevice; 300 | DX::ThrowIfFailed( 301 | m_d3dDevice.As(&dxgiDevice) 302 | ); 303 | 304 | ComPtr dxgiAdapter; 305 | DX::ThrowIfFailed( 306 | dxgiDevice->GetAdapter(&dxgiAdapter) 307 | ); 308 | 309 | ComPtr dxgiFactory; 310 | DX::ThrowIfFailed( 311 | dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory)) 312 | ); 313 | 314 | // Requires DirectX 11.1 or later 315 | DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; 316 | swapChainDesc.Width = backBufferWidth; 317 | swapChainDesc.Height = backBufferHeight; 318 | swapChainDesc.Format = m_backBufferFormat; 319 | swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 320 | swapChainDesc.BufferCount = m_backBufferCount; 321 | swapChainDesc.SampleDesc.Count = 1; 322 | swapChainDesc.SampleDesc.Quality = 0; 323 | swapChainDesc.Scaling = DXGI_SCALING_STRETCH; 324 | swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; 325 | swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; 326 | swapChainDesc.Flags = 0; 327 | 328 | // Create a SwapChain from a Win32 window. 329 | ComPtr swapChain1; 330 | DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForHwnd( 331 | m_d3dDevice.Get(), 332 | m_window, 333 | &swapChainDesc, 334 | nullptr, 335 | nullptr, 336 | swapChain1.ReleaseAndGetAddressOf() 337 | )); 338 | 339 | DX::ThrowIfFailed(swapChain1.As(&m_swapChain)); 340 | 341 | // This class does not support exclusive full-screen mode and prevents DXGI from responding to the ALT+ENTER shortcut 342 | DX::ThrowIfFailed(dxgiFactory->MakeWindowAssociation(m_window, DXGI_MWA_NO_ALT_ENTER)); 343 | } 344 | 345 | // Create a render target view of the swap chain back buffer. 346 | DX::ThrowIfFailed(m_swapChain->GetBuffer(0, IID_PPV_ARGS(m_renderTarget.ReleaseAndGetAddressOf()))); 347 | 348 | DX::ThrowIfFailed(m_d3dDevice->CreateRenderTargetView( 349 | m_renderTarget.Get(), 350 | nullptr, 351 | m_d3dRenderTargetView.ReleaseAndGetAddressOf() 352 | )); 353 | 354 | if (m_depthBufferFormat != DXGI_FORMAT_UNKNOWN) 355 | { 356 | // Create a depth stencil view for use with 3D rendering if needed. 357 | CD3D11_TEXTURE2D_DESC depthStencilDesc( 358 | m_depthBufferFormat, 359 | backBufferWidth, 360 | backBufferHeight, 361 | 1, // This depth stencil view has only one texture. 362 | 1, // Use a single mipmap level. 363 | D3D11_BIND_DEPTH_STENCIL 364 | ); 365 | 366 | DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D( 367 | &depthStencilDesc, 368 | nullptr, 369 | m_depthStencil.ReleaseAndGetAddressOf() 370 | )); 371 | 372 | CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D); 373 | DX::ThrowIfFailed(m_d3dDevice->CreateDepthStencilView( 374 | m_depthStencil.Get(), 375 | &depthStencilViewDesc, 376 | m_d3dDepthStencilView.ReleaseAndGetAddressOf() 377 | )); 378 | 379 | } 380 | 381 | // Set the 3D rendering viewport to target the entire window. 382 | m_screenViewport = CD3D11_VIEWPORT( 383 | 0.0f, 384 | 0.0f, 385 | static_cast(backBufferWidth), 386 | static_cast(backBufferHeight) 387 | ); 388 | 389 | m_d3dContext->RSSetViewports(1, &m_screenViewport); 390 | 391 | // Create a Direct2D target bitmap from the swapchain. 392 | CD3D11_TEXTURE2D_DESC d2dTargetDesc( 393 | m_backBufferFormat, 394 | backBufferWidth, 395 | backBufferHeight, 396 | 1, // Only one texture. 397 | 1, // Use a single mipmap level. 398 | D3D11_BIND_RENDER_TARGET); 399 | 400 | D2D1_BITMAP_PROPERTIES1 bitmapProperties = 401 | D2D1::BitmapProperties1( 402 | D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, 403 | D2D1::PixelFormat(m_backBufferFormat, D2D1_ALPHA_MODE_PREMULTIPLIED), 404 | m_dpi, 405 | m_dpi 406 | ); 407 | 408 | ComPtr targetDxgiSurface; 409 | DX::ThrowIfFailed(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&targetDxgiSurface))); 410 | 411 | DX::ThrowIfFailed( 412 | m_d2dContext->CreateBitmapFromDxgiSurface( 413 | targetDxgiSurface.Get(), 414 | &bitmapProperties, 415 | &m_d2dTargetBitmap 416 | ) 417 | ); 418 | 419 | m_d2dContext->SetTarget(m_d2dTargetBitmap.Get()); 420 | m_d2dContext->SetDpi(m_dpi, m_dpi); 421 | } 422 | 423 | // This method is called in the event handler for the DpiChanged event. 424 | void DX::DeviceResources::SetDpi(float dpi) 425 | { 426 | if (dpi != m_dpi) 427 | { 428 | m_dpi = dpi; 429 | 430 | // When the display DPI changes, the logical size of the window (measured in Dips) also changes and needs to be updated. 431 | UpdateLogicalSize(m_outputSize, m_dpi); 432 | m_d2dContext->SetDpi(m_dpi, m_dpi); 433 | //CreateWindowSizeDependentResources(); 434 | } 435 | } 436 | 437 | // This method is called when the Win32 window is created (or re-created). 438 | void DX::DeviceResources::SetWindow(HWND window, int width, int height) 439 | { 440 | m_window = window; 441 | 442 | m_outputSize.left = m_outputSize.top = 0; 443 | m_outputSize.right = width; 444 | m_outputSize.bottom = height; 445 | } 446 | 447 | // This method is called when the Win32 window changes size 448 | bool DX::DeviceResources::WindowSizeChanged(int width, int height) 449 | { 450 | RECT newRc; 451 | newRc.left = newRc.top = 0; 452 | newRc.right = width; 453 | newRc.bottom = height; 454 | 455 | if (newRc == m_outputSize) 456 | { 457 | return false; 458 | } 459 | 460 | m_outputSize = newRc; 461 | 462 | UpdateLogicalSize(m_outputSize, m_dpi); 463 | CreateWindowSizeDependentResources(); 464 | return true; 465 | } 466 | 467 | // Recreate all device resources and set them back to the current state. 468 | void DX::DeviceResources::HandleDeviceLost() 469 | { 470 | if (m_deviceNotify) 471 | { 472 | m_deviceNotify->OnDeviceLost(); 473 | } 474 | 475 | m_d3dContext.Reset(); 476 | m_swapChain.Reset(); 477 | m_d3dAnnotation.Reset(); 478 | m_renderTarget.Reset(); 479 | m_depthStencil.Reset(); 480 | m_d3dRenderTargetView.Reset(); 481 | m_d3dDepthStencilView.Reset(); 482 | 483 | m_d2dDevice.Reset(); 484 | m_d2dContext.Reset(); 485 | m_d2dTargetBitmap.Reset(); 486 | 487 | #ifdef _DEBUG 488 | { 489 | ComPtr d3dDebug; 490 | if (SUCCEEDED(m_d3dDevice.As(&d3dDebug))) 491 | { 492 | d3dDebug->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY); 493 | } 494 | } 495 | #endif 496 | 497 | m_d3dDevice.Reset(); 498 | 499 | CreateDeviceResources(); 500 | CreateWindowSizeDependentResources(); 501 | 502 | if (m_deviceNotify) 503 | { 504 | m_deviceNotify->OnDeviceRestored(); 505 | } 506 | } 507 | 508 | // Present the contents of the swap chain to the screen. 509 | void DX::DeviceResources::Present() 510 | { 511 | //OutputDebugPrintf("%s \n", __FUNCTION__); 512 | 513 | // The first argument instructs DXGI to block until VSync, putting the application 514 | // to sleep until the next VSync. This ensures we don't waste any cycles rendering 515 | // frames that will never be displayed to the screen. 516 | HRESULT hr = m_swapChain->Present(1, 0); 517 | 518 | if (m_d3dContext) 519 | { 520 | // Discard the contents of the render target. 521 | // This is a valid operation only when the existing contents will be entirely 522 | // overwritten. If dirty or scroll rects are used, this call should be removed. 523 | m_d3dContext->DiscardView(m_d3dRenderTargetView.Get()); 524 | 525 | if(m_d3dDepthStencilView) 526 | { 527 | // Discard the contents of the depth stencil. 528 | m_d3dContext->DiscardView(m_d3dDepthStencilView.Get()); 529 | } 530 | } 531 | 532 | // If the device was removed either by a disconnection or a driver upgrade, we 533 | // must recreate all device resources. 534 | if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) 535 | { 536 | #ifdef _DEBUG 537 | char buff[64] = {}; 538 | sprintf_s(buff, "Device Lost on Present: Reason code 0x%08X\n", (hr == DXGI_ERROR_DEVICE_REMOVED) ? m_d3dDevice->GetDeviceRemovedReason() : hr); 539 | OutputDebugStringA(buff); 540 | #endif 541 | HandleDeviceLost(); 542 | } 543 | else 544 | { 545 | DX::ThrowIfFailed(hr); 546 | } 547 | } 548 | 549 | 550 | // This method acquires the first available hardware adapter. 551 | // If no such adapter can be found, *ppAdapter will be set to nullptr. 552 | void DX::DeviceResources::GetHardwareAdapter(IDXGIAdapter1** ppAdapter) 553 | { 554 | *ppAdapter = nullptr; 555 | 556 | ComPtr dxgiFactory; 557 | DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(dxgiFactory.GetAddressOf()))); 558 | 559 | ComPtr adapter; 560 | for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != dxgiFactory->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()); adapterIndex++) 561 | { 562 | DXGI_ADAPTER_DESC1 desc; 563 | adapter->GetDesc1(&desc); 564 | 565 | if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) 566 | { 567 | // Don't select the Basic Render Driver adapter. 568 | continue; 569 | } 570 | 571 | #ifdef _DEBUG 572 | wchar_t buff[256] = {}; 573 | swprintf_s(buff, L"Direct3D Adapter (%u): VID:%04X, PID:%04X - %ls\n", adapterIndex, desc.VendorId, desc.DeviceId, desc.Description); 574 | OutputDebugStringW(buff); 575 | #endif 576 | 577 | break; 578 | } 579 | 580 | *ppAdapter = adapter.Detach(); 581 | } 582 | // Updates the (primarily Direct2D) DPI-dependent measurements. 583 | void DX::DeviceResources::UpdateLogicalSize(RECT outputSize, float dpi) 584 | { 585 | m_logicalSize = { 586 | 0.0f, 587 | 0.0f, 588 | outputSize.right * 96.0f / dpi, 589 | outputSize.bottom * 96.0f / dpi }; 590 | } 591 | -------------------------------------------------------------------------------- /10bpc_demo/BasicMath.h: -------------------------------------------------------------------------------- 1 | //********************************************************* 2 | // 3 | // Copyright (c) Microsoft. All rights reserved. 4 | // This code is licensed under the MIT License (MIT). 5 | // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 6 | // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY 7 | // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 8 | // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. 9 | // 10 | //********************************************************* 11 | 12 | #pragma once 13 | 14 | #define _USE_MATH_DEFINES 15 | #include 16 | //#include 17 | 18 | 19 | // This header defines math and matrix helper functions and structures used 20 | // by DirectX SDK samples. 21 | 22 | // Common Constants 23 | 24 | #define M_E_F 2.71828183f 25 | #define M_PI_F 3.1415927f 26 | #define TO_RADF (M_PI_F/180.0f) 27 | #define TO_DEGF (180.0f/M_PI_F) 28 | 29 | //#define max(x,y) ((x)>(y)?(x):(y)) 30 | //#define min(x,y) ((x)<(y)?(x):(y)) 31 | 32 | // Template Vector & Matrix Classes 33 | 34 | template struct Vector2 35 | { 36 | union 37 | { 38 | struct 39 | { 40 | T x; 41 | T y; 42 | }; 43 | struct 44 | { 45 | T r; 46 | T g; 47 | }; 48 | struct 49 | { 50 | T u; 51 | T v; 52 | }; 53 | }; 54 | 55 | Vector2(const float v[]) 56 | { 57 | *this = v; // use assignment operator implementation 58 | } 59 | 60 | // assignment operator 61 | Vector2& operator=(const float v[]) 62 | { 63 | this->x = v[0]; 64 | this->y = v[1]; 65 | return *this; 66 | } 67 | 68 | T& operator[](unsigned int index) 69 | { 70 | return static_cast(this)[index]; 71 | } 72 | 73 | Vector2(T _x = 0, T _y = 0) : x(_x), y(_y) { } 74 | }; 75 | 76 | template struct Vector3 77 | { 78 | union 79 | { 80 | struct 81 | { 82 | T x; 83 | T y; 84 | T z; 85 | }; 86 | struct 87 | { 88 | T r; 89 | T g; 90 | T b; 91 | }; 92 | struct 93 | { 94 | T u; 95 | T v; 96 | T w; // this is really risky 97 | }; 98 | }; 99 | 100 | Vector3(const float v[]) 101 | { 102 | *this = v; // use assignment operator implementation 103 | } 104 | 105 | // assignment operator 106 | Vector3& operator=(const float v[]) 107 | { 108 | this->x = v[0]; 109 | this->y = v[1]; 110 | this->y = v[2]; 111 | return *this; 112 | } 113 | 114 | T& operator[](unsigned int index) 115 | { 116 | return static_cast(this)[index]; 117 | } 118 | 119 | Vector3(T _x = 0, T _y = 0, T _z = 0) : x(_x), y(_y), z(_z) { } 120 | }; 121 | 122 | 123 | template struct Matrix3x3 124 | { 125 | union 126 | { 127 | struct 128 | { 129 | T _11; T _12; T _13; 130 | T _21; T _22; T _23; 131 | T _31; T _32; T _33; 132 | }; 133 | struct 134 | { 135 | T _m00; T _m01; T _m02; 136 | T _m10; T _m11; T _m12; 137 | T _m20; T _m21; T _m22; 138 | }; 139 | }; 140 | 141 | Matrix3x3(T value = 0) 142 | { 143 | _11 = _12 = _13 = value; 144 | _21 = _22 = _23 = value; 145 | _31 = _32 = _33 = value; 146 | } 147 | 148 | Matrix3x3( 149 | T i11, T i12, T i13, 150 | T i21, T i22, T i23, 151 | T i31, T i32, T i33 152 | ) 153 | { 154 | _11 = i11; _12 = i12; _13 = i13; 155 | _21 = i21; _22 = i22; _23 = i23; 156 | _31 = i31; _32 = i32; _33 = i33; 157 | } 158 | 159 | T* operator[](unsigned int index) 160 | { 161 | return &(reinterpret_cast(this)[index * 3]); 162 | } 163 | }; 164 | 165 | template struct Vector4 166 | { 167 | union 168 | { 169 | struct 170 | { 171 | T x; 172 | T y; 173 | T z; 174 | T w; 175 | }; 176 | struct 177 | { 178 | T r; 179 | T g; 180 | T b; 181 | T a; 182 | }; 183 | }; 184 | 185 | Vector4(const float v[]) 186 | { 187 | *this = v; // use assignment operator implementation 188 | } 189 | 190 | // assignment operator 191 | Vector4& operator=(const float v[]) 192 | { 193 | this->x = v[0]; 194 | this->y = v[1]; 195 | this->y = v[2]; 196 | this->y = v[3]; 197 | return *this; 198 | } 199 | 200 | T& operator[](unsigned int index) 201 | { 202 | return static_cast(this)[index]; 203 | } 204 | 205 | Vector4(T _x = 0, T _y = 0, T _z = 0, T _w = 0) : x(_x), y(_y), z(_z), w(_w) { } 206 | }; 207 | 208 | template struct Matrix4x4 209 | { 210 | union 211 | { 212 | struct 213 | { 214 | T _11; T _12; T _13; T _14; 215 | T _21; T _22; T _23; T _24; 216 | T _31; T _32; T _33; T _34; 217 | T _41; T _42; T _43; T _44; 218 | }; 219 | struct 220 | { 221 | T _m00; T _m01; T _m02; T _m03; 222 | T _m10; T _m11; T _m12; T _m13; 223 | T _m20; T _m21; T _m22; T _m23; 224 | T _m30; T _m31; T _m32; T _m33; 225 | }; 226 | }; 227 | 228 | Matrix4x4(T value = 0) 229 | { 230 | _11 = _12 = _13 = _14 = value; 231 | _21 = _22 = _23 = _24 = value; 232 | _31 = _32 = _33 = _34 = value; 233 | _41 = _42 = _43 = _44 = value; 234 | } 235 | 236 | Matrix4x4( 237 | T i11, T i12, T i13, T i14, 238 | T i21, T i22, T i23, T i24, 239 | T i31, T i32, T i33, T i34, 240 | T i41, T i42, T i43, T i44 241 | ) 242 | { 243 | _11 = i11; _12 = i12; _13 = i13; _14 = i14; 244 | _21 = i21; _22 = i22; _23 = i23; _24 = i24; 245 | _31 = i31; _32 = i32; _33 = i33; _34 = i34; 246 | _41 = i41; _42 = i42; _43 = i43; _44 = i44; 247 | } 248 | 249 | T* operator[](unsigned int index) 250 | { 251 | return &(reinterpret_cast(this)[index*4]); 252 | } 253 | }; 254 | // TODO really should add Double4x4 255 | 256 | 257 | // Template Vector Operations 258 | 259 | template 260 | T dot(Vector2 a, Vector2 b) 261 | { 262 | return a.x * b.x + a.y * b.y; 263 | } 264 | 265 | template 266 | T dot(Vector3 a, Vector3 b) 267 | { 268 | return a.x * b.x + a.y * b.y + a.z * b.z; 269 | } 270 | 271 | template 272 | T dot(Vector4 a, Vector4 b) 273 | { 274 | return a.x * b.x + a.y * b.y + a.z * b.z + a.w + b.w; 275 | } 276 | 277 | template 278 | T length(Vector2 a) 279 | { 280 | return sqrtf(a.x * a.x + a.y * a.y); 281 | } 282 | 283 | template 284 | T length(Vector3 a) 285 | { 286 | return sqrtf(a.x * a.x + a.y * a.y + a.z * a.z); 287 | } 288 | 289 | template 290 | T length(Vector4 a) 291 | { 292 | return sqrtf(a.x * a.x + a.y * a.y + a.z * a.z + a.w * a.w); 293 | } 294 | 295 | template 296 | T distance( Vector2 a, Vector2 b ) 297 | { 298 | return sqrtf( dot( a-b, a-b ) ); 299 | } 300 | 301 | template 302 | T distance( Vector3 a, Vector3 b ) 303 | { 304 | return sqrtf( dot( a-b, a-b ) ); 305 | } 306 | 307 | template 308 | T distance(Vector4 a, Vector4 b) 309 | { 310 | return sqrtf( dot( a-b, a-b ) ); 311 | } 312 | 313 | template 314 | float cross(Vector2 a, Vector2 b) 315 | { 316 | return (a.x*b.y) - (a.y*b.x); 317 | } 318 | template 319 | Vector3 cross(Vector3 a, Vector3 b) 320 | { 321 | return Vector3((a.y*b.z)-(a.z*b.y), (a.z*b.x)-(a.x*b.z), (a.x*b.y)-(a.y*b.x)); 322 | } 323 | 324 | template 325 | Vector2 normalize(Vector2 a) 326 | { 327 | T len = length(a); 328 | return Vector2(a.x / len, a.y / len); 329 | } 330 | 331 | template 332 | Vector3 normalize(Vector3 a) 333 | { 334 | T len = length(a); 335 | return Vector3(a.x / len, a.y / len, a.z / len); 336 | } 337 | 338 | template 339 | Vector4 normalize(Vector4 a) 340 | { 341 | T len = length(a); 342 | return Vector4(a.x / len, a.y / len, a.z / len, a.w / len); 343 | } 344 | 345 | // Template Vector Operators 346 | 347 | template 348 | Vector2 operator-(Vector2 a, Vector2 b) 349 | { 350 | return Vector2(a.x - b.x, a.y - b.y); 351 | } 352 | 353 | template 354 | Vector2 operator-(Vector2 a) 355 | { 356 | return Vector2(-a.x, -a.y); 357 | } 358 | 359 | template 360 | Vector3 operator-(Vector3 a, Vector3 b) 361 | { 362 | return Vector3(a.x - b.x, a.y - b.y, a.z - b.z); 363 | } 364 | 365 | template 366 | Vector3 operator-(Vector3 a) 367 | { 368 | return Vector3(-a.x, -a.y, -a.z); 369 | } 370 | 371 | template 372 | Vector4 operator-(Vector4 a, Vector4 b) 373 | { 374 | return Vector4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); 375 | } 376 | 377 | template 378 | Vector4 operator-(Vector4 a) 379 | { 380 | return Vector4(-a.x, -a.y, -a.z, -a.w); 381 | } 382 | 383 | template 384 | Vector2 operator+(Vector2 a, Vector2 b) 385 | { 386 | return Vector2(a.x + b.x, a.y + b.y); 387 | } 388 | 389 | template 390 | Vector3 operator+(Vector3 a, Vector3 b) 391 | { 392 | return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); 393 | } 394 | /* 395 | template 396 | Vector3 operator+=(Vector3 a, Vector3 b) 397 | { 398 | // return Vector3(a.x + b.x, a.y + b.y, a.z + b.z); // this is a no-op for some reason BUG TODO 399 | a.x += b.x; a.y += b.y; a.z += b.z; return a; 400 | } 401 | */ 402 | 403 | template 404 | Vector4 operator+(Vector4 a, Vector4 b) 405 | { 406 | return Vector4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); 407 | } 408 | 409 | template 410 | Vector2 operator*(Vector2 a, T s) 411 | { 412 | return Vector2(a.x * s, a.y * s); 413 | } 414 | 415 | template 416 | Vector2 operator*(T s, Vector2 a) 417 | { 418 | return a * s; 419 | } 420 | 421 | template 422 | Vector2 operator*(Vector2 a, Vector2 b) 423 | { 424 | return Vector2(a.x * b.x, a.y * b.y); 425 | } 426 | 427 | template 428 | Vector2 operator/(Vector2 a, T s) 429 | { 430 | return Vector2(a.x / s, a.y / s); 431 | } 432 | template 433 | Vector2 operator/=(Vector2 a, T s) 434 | { 435 | return Vector2(a.x / s, a.y / s); 436 | } 437 | 438 | template 439 | Vector3 operator*(Vector3 a, T s) 440 | { 441 | return Vector3(a.x * s, a.y * s, a.z * s); 442 | } 443 | template 444 | Vector3 operator*=(Vector3 a, T s) 445 | { 446 | return Vector3(a.x * s, a.y * s, a.z * s); 447 | } 448 | 449 | template 450 | Vector3 operator*(T s, Vector3 a) 451 | { 452 | return a * s; 453 | } 454 | 455 | template 456 | Vector3 operator*(Vector3 a, Vector3 b) 457 | { 458 | return Vector3(a.x * b.x, a.y * b.y, a.z * b.z); 459 | } 460 | 461 | template 462 | Vector3 operator/(Vector3 a, T s) 463 | { 464 | return Vector3(a.x / s, a.y / s, a.z / s); 465 | } 466 | template 467 | Vector3 operator/=(Vector3 a, T s) 468 | { 469 | return Vector3(a.x / s, a.y / s, a.z / s); 470 | } 471 | 472 | template 473 | Vector3 operator/(Vector3 a, Vector3 b) 474 | { 475 | return Vector3(a.x / b.x, a.y / b.y, a.z / b.z); 476 | } 477 | 478 | template 479 | Vector3 operator/=(Vector3 a, Vector3 b) 480 | { 481 | return Vector3(a.x / b.x, a.y / b.y, a.z / b.z); 482 | } 483 | 484 | template 485 | Vector4 operator*(Vector4 a, T s) 486 | { 487 | return Vector4(a.x * s, a.y * s, a.z * s, a.w * s); 488 | } 489 | 490 | template 491 | Vector4 operator*(T s, Vector4 a) 492 | { 493 | return a * s; 494 | } 495 | 496 | template 497 | Vector4 operator*(Vector4 a, Vector4 b) 498 | { 499 | return Vector4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); 500 | } 501 | 502 | template 503 | Vector4 operator/(Vector4 a, T s) 504 | { 505 | return Vector4(a.x / s, a.y / s, a.z / s, a.w / s); 506 | } 507 | 508 | // project a vector into a plane with normal 509 | template 510 | Vector3 project( Vector3 vec, Vector3 normal ) 511 | { 512 | float component = dot( vec, normal ); // component of vec normal to plane 513 | return vec - component*normal; // subtract to get in-plane component 514 | } 515 | 516 | // project a point into a plane defined by origin and normal 517 | template 518 | Vector3 project( Vector3 point, Vector3 origin, Vector3 normal ) 519 | { 520 | Vector3 toPoint = point - origin; 521 | return project( toPoint, normal ) + origin; 522 | } 523 | 524 | // clamp all components to 0..1 range 525 | template 526 | Vector2 saturate(Vector2 v) 527 | { 528 | v.x = (v.x > 1.0f ? 1.0f : v.x); 529 | v.x = (v.x < 0.0f ? 0.0f : v.x); 530 | v.y = (v.y > 1.0f ? 1.0f : v.y); 531 | v.y = (v.y < 0.0f ? 0.0f : v.y); 532 | 533 | return Vector2(v.x, v.y ); 534 | } 535 | 536 | // clamp all components to 0..1 range 537 | template 538 | Vector3 saturate( Vector3 v) 539 | { 540 | v.x = (v.x > 1.0f ? 1.0f : v.x); 541 | v.x = (v.x < 0.0f ? 0.0f : v.x); 542 | v.y = (v.y > 1.0f ? 1.0f : v.y); 543 | v.y = (v.y < 0.0f ? 0.0f : v.y); 544 | v.z = (v.z > 1.0f ? 1.0f : v.z); 545 | v.z = (v.z < 0.0f ? 0.0f : v.z); 546 | 547 | return Vector3(v.x, v.y, v.z); 548 | } 549 | 550 | #if 0 551 | float clamp(float v, float min, float max) 552 | { 553 | if (v > max) v = max; else 554 | if (v < min) v = min; 555 | return v; 556 | } 557 | #endif 558 | 559 | template 560 | Vector2 clamp(Vector2 v, float min, float max) 561 | { 562 | if (v.x > max) v.x = max; else 563 | if (v.x < min) v.x = min; 564 | if (v.y > max) v.y = max; else 565 | if (v.y < min) v.y = min; 566 | return Vector2(v.x, v.y, v.z); 567 | } 568 | 569 | template 570 | Vector3 clamp(Vector3 v, float min, float max) 571 | { 572 | if (v.x > max) v.x = max; else 573 | if (v.x < min) v.x = min; 574 | if (v.y > max) v.y = max; else 575 | if (v.y < min) v.y = min; 576 | if (v.z > max) v.z = max; else 577 | if (v.z < min) v.z = min; 578 | return Vector3(v.x, v.y, v.z); 579 | } 580 | 581 | template 582 | Vector4 clamp(Vector4 v, float min, float max) 583 | { 584 | if (v.x > max) v.x = max; else 585 | if (v.x < min) v.x = min; 586 | if (v.y > max) v.y = max; else 587 | if (v.y < min) v.y = min; 588 | if (v.z > max) v.z = max; else 589 | if (v.z < min) v.z = min; 590 | if (v.w > max) v.w = max; else 591 | if (v.w < min) v.w = min; 592 | return Vector4(v.x, v.y, v.z); 593 | } 594 | 595 | // Template Matrix Operations 596 | // 3x3 597 | template 598 | Vector3 mul(Matrix3x3 m, Vector3 v) 599 | { 600 | return Vector3 601 | (v.x * m._11 + v.y * m._12 + v.z * m._13, 602 | v.x * m._21 + v.y * m._22 + v.z * m._23, 603 | v.x * m._31 + v.y * m._32 + v.z * m._33 ); 604 | } 605 | 606 | template 607 | Vector3 operator * (Matrix3x3 m, Vector3 v) 608 | { 609 | return mul(m, v); 610 | } 611 | 612 | template 613 | Vector3 mul(Vector3 v, Matrix3x3 m) 614 | { 615 | return Vector3 616 | (v.x * m._11 + v.y * m._21 + v.z * m._31, 617 | v.x * m._12 + v.y * m._22 + v.z * m._32, 618 | v.x * m._13 + v.y * m._23 + v.z * m._33); 619 | } 620 | 621 | template 622 | Vector3 operator * (Vector3 v, Matrix3x3 m) 623 | { 624 | return mul(v, m); 625 | } 626 | 627 | template 628 | Matrix3x3 transpose(Matrix3x3 m) 629 | { 630 | return Matrix3x3( 631 | m._11, m._21, m._31, 632 | m._12, m._22, m._32, 633 | m._13, m._23, m._33); 634 | } 635 | 636 | // if performance is too slow, we can replace with DirectXMath version 637 | template 638 | Matrix3x3 mul( Matrix3x3 m1, Matrix3x3 m2) 639 | { 640 | Matrix3x3 mOut; 641 | 642 | for (int i = 0; i < 3; i++) 643 | { 644 | for (int j = 0; j < 3; j++) 645 | { 646 | for (int k = 0; k < 3; k++) 647 | { 648 | mOut[i][j] += m1[i][k] * m2[k][j]; 649 | } 650 | } 651 | } 652 | return mOut; 653 | } 654 | 655 | template 656 | Matrix3x3 operator * (Matrix3x3 m1, Matrix3x3 m2) 657 | { 658 | return mul(m1, m2); 659 | } 660 | 661 | template 662 | Matrix3x3 operator *= (Matrix3x3 m1, Matrix3x3 m2) // this is broken for some reason! 663 | { 664 | return mul(m1, m2); 665 | } 666 | 667 | // Cramer's rule is fast enough for 3x3 668 | template 669 | Matrix3x3 inv(Matrix3x3 m) 670 | { 671 | double det = (double) m._11 * ((double)m._22 * (double)m._33 - (double)m._23 * (double)m._32) 672 | - (double) m._12 * ((double)m._21 * (double)m._33 - (double)m._23 * (double)m._31) 673 | + (double) m._13 * ((double)m._21 * (double)m._32 - (double)m._22 * (double)m._31); 674 | if (abs(det) < 1.0e-9) 675 | { 676 | cerr << "Error: Matrix Not Invertible" << endl; 677 | abort(); 678 | } 679 | Matrix3x3 ret; 680 | ret._11 = (float)((m._22 * m._33 - m._23 * m._32) / det); 681 | ret._12 = (float)((m._13 * m._32 - m._12 * m._33) / det); 682 | ret._13 = (float)((m._12 * m._23 - m._13 * m._22) / det); 683 | ret._21 = (float)((m._23 * m._31 - m._21 * m._33) / det); 684 | ret._22 = (float)((m._11 * m._33 - m._13 * m._31) / det); 685 | ret._23 = (float)((m._13 * m._21 - m._11 * m._23) / det); 686 | ret._31 = (float)((m._21 * m._32 - m._22 * m._31) / det); 687 | ret._32 = (float)((m._12 * m._31 - m._11 * m._32) / det); 688 | ret._33 = (float)((m._11 * m._22 - m._12 * m._21) / det); 689 | return ret; 690 | } 691 | 692 | 693 | // 4x4 694 | template 695 | Vector4 mul( Matrix4x4 m, Vector4 v ) 696 | { 697 | return Vector4 698 | (v.x * m._11 + v.y * m._12 + v.z * m._13 + v.w * m._14, 699 | v.x * m._21 + v.y * m._22 + v.z * m._23 + v.w * m._24, 700 | v.x * m._31 + v.y * m._32 + v.z * m._33 + v.w * m._34, 701 | v.x * m._41 + v.y * m._42 + v.z * m._43 + v.w * m._44); 702 | } 703 | 704 | template 705 | Vector4 operator * ( Matrix4x4 m, Vector4 v ) 706 | { 707 | return mul( m, v ); 708 | } 709 | 710 | 711 | template 712 | Vector3 mul( Vector3 v, Matrix4x4 m ) 713 | { 714 | return Vector3 715 | (v.x * m._11 + v.y * m._21 + v.z * m._31 + m._41, 716 | v.x * m._12 + v.y * m._22 + v.z * m._32 + m._42, 717 | v.x * m._13 + v.y * m._23 + v.z * m._33 + m._43 ); 718 | } 719 | 720 | template 721 | Vector3 mulNorm( Vector3 v, Matrix4x4 m ) 722 | { 723 | return Vector3 724 | (v.x * m._11 + v.y * m._21 + v.z * m._31, 725 | v.x * m._12 + v.y * m._22 + v.z * m._32, 726 | v.x * m._13 + v.y * m._23 + v.z * m._33 ); 727 | } 728 | 729 | template 730 | Vector3 operator * ( Vector3 v, Matrix4x4 m ) 731 | { 732 | return mul( v, m ); 733 | } 734 | 735 | template 736 | Vector3 mul( Matrix4x4 m, Vector3 v ) 737 | { 738 | return Vector3 739 | (v.x * m._11 + v.y * m._12 + v.z * m._13 + m._14, 740 | v.x * m._21 + v.y * m._22 + v.z * m._23 + m._24, 741 | v.x * m._31 + v.y * m._32 + v.z * m._33 + m._34 ); 742 | } 743 | 744 | template 745 | Vector3 operator * ( Matrix4x4 m, Vector3 v ) 746 | { 747 | return mul( m, v ); 748 | } 749 | 750 | 751 | template 752 | Matrix4x4 transpose(Matrix4x4 m) 753 | { 754 | return Matrix4x4( 755 | m._11, m._21, m._31, m._41, 756 | m._12, m._22, m._32, m._42, 757 | m._13, m._23, m._33, m._43, 758 | m._14, m._24, m._34, m._44 ); 759 | } 760 | 761 | // if performance is too slow, we can replace with DirectXMath version 762 | template 763 | Matrix4x4 mul(Matrix4x4 m1, Matrix4x4 m2) 764 | { 765 | Matrix4x4 mOut; 766 | 767 | for (int i = 0; i < 4; i++) 768 | { 769 | for (int j = 0; j < 4; j++) 770 | { 771 | for (int k = 0; k < 4; k++) 772 | { 773 | mOut[i][j] += m1[i][k] * m2[k][j]; 774 | } 775 | } 776 | } 777 | 778 | return mOut; 779 | } 780 | 781 | template 782 | Matrix4x4 operator * ( Matrix4x4 m1, Matrix4x4 m2 ) 783 | { 784 | return mul( m1, m2 ); 785 | } 786 | /* 787 | template 788 | Matrix4x4 operator *= ( Matrix4x4 m1, Matrix4x4 m2 ) // this is broken for some reason! 789 | { 790 | return mul( m1, m2 ); 791 | } 792 | */ 793 | // clamp all components to 0..1 range 794 | template 795 | Vector4 saturate(Vector4 v) 796 | { 797 | v.x = (v.x > 1.0f ? 1.0f : v.x); 798 | v.x = (v.x < 0.0f ? 0.0f : v.x); 799 | v.y = (v.y > 1.0f ? 1.0f : v.y); 800 | v.y = (v.y < 0.0f ? 0.0f : v.y); 801 | v.z = (v.z > 1.0f ? 1.0f : v.z); 802 | v.z = (v.z < 0.0f ? 0.0f : v.z); 803 | v.w = (v.w > 1.0f ? 1.0f : v.w); 804 | v.w = (v.w < 0.0f ? 0.0f : v.w); 805 | 806 | return Vector4(v.x, v.y, v.z, v.w); 807 | } 808 | 809 | // works with scale factor as long as it is same in all 3 axes 810 | template 811 | Matrix4x4 fastMatrixInverse( Matrix4x4 matIn ) 812 | { 813 | Matrix4x4 mat; 814 | double sx; 815 | 816 | // Calculate the square of the isotropic scale factor 817 | sx = matIn._11*matIn._11 + matIn._12*matIn._12 + matIn._13*matIn._13; 818 | sx = 1.0/sx; 819 | 820 | // invert rotation component (upper left 3x3) by transposing 821 | mat._11 = (float) sx*matIn._11; 822 | mat._12 = (float) sx*matIn._21; 823 | mat._13 = (float) sx*matIn._31; 824 | mat._21 = (float) sx*matIn._12; 825 | mat._22 = (float) sx*matIn._22; 826 | mat._23 = (float) sx*matIn._32; 827 | mat._31 = (float) sx*matIn._13; 828 | mat._32 = (float) sx*matIn._23; 829 | mat._33 = (float) sx*matIn._33; 830 | 831 | // negate translations and xform them by rotation component (rotate them) 832 | float tx = -matIn._41; 833 | float ty = -matIn._42; 834 | float tz = -matIn._43; 835 | mat._41 = tx*mat._11 + ty*mat._21 + tz*mat._31; 836 | mat._42 = tx*mat._12 + ty*mat._22 + tz*mat._32; 837 | mat._43 = tx*mat._13 + ty*mat._23 + tz*mat._33; 838 | 839 | // do last column 840 | mat._14 = matIn._14; 841 | mat._24 = matIn._24; 842 | mat._34 = matIn._34; 843 | mat._44 = matIn._44; 844 | 845 | return mat; 846 | } 847 | 848 | // Common HLSL-compatible vector typedefs 849 | 850 | typedef unsigned int uint; 851 | 852 | typedef Vector2 float2; 853 | typedef Vector3 float3; 854 | typedef Vector4 float4; 855 | 856 | typedef Matrix3x3 float3x3; 857 | typedef Matrix4x4 float4x4; 858 | typedef Matrix4x4 matrix; 859 | 860 | typedef Vector2 half2; 861 | typedef Vector3 half3; 862 | typedef Vector4 half4; 863 | 864 | // TODO: add constructor for D2D_POINT_2F etc. 865 | 866 | // Standard Matrix Intializers 867 | 868 | 869 | inline float4x4 identity() 870 | { 871 | float4x4 mOut; 872 | 873 | mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f; 874 | mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f; 875 | mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f; 876 | mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f; 877 | 878 | return mOut; 879 | } 880 | 881 | inline float4x4 translation(float x, float y, float z) 882 | { 883 | float4x4 mOut; 884 | 885 | mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f; 886 | mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f; 887 | mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f; 888 | mOut._41 = x; mOut._42 = y; mOut._43 = z; mOut._44 = 1.0f; 889 | 890 | return mOut; 891 | } 892 | 893 | inline float4x4 translation( float3 t ) 894 | { 895 | return translation( t.x, t.y, t.z ); 896 | } 897 | 898 | inline float4x4 scale(float x, float y, float z) 899 | { 900 | float4x4 mOut; 901 | 902 | mOut._11 = x; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f; 903 | mOut._21 = 0.0f; mOut._22 = y; mOut._23 = 0.0f; mOut._24 = 0.0f; 904 | mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = z; mOut._34 = 0.0f; 905 | mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f; 906 | 907 | return mOut; 908 | } 909 | 910 | inline float4x4 scale(float s) 911 | { 912 | float4x4 mOut; 913 | 914 | mOut._11 = s; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f; 915 | mOut._21 = 0.0f; mOut._22 = s; mOut._23 = 0.0f; mOut._24 = 0.0f; 916 | mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = s; mOut._34 = 0.0f; 917 | mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f; 918 | 919 | return mOut; 920 | } 921 | 922 | inline float4x4 rotationX(float a) 923 | { 924 | float sinAngle = sinf(a); 925 | float cosAngle = cosf(a); 926 | 927 | float4x4 mOut; 928 | 929 | mOut._11 = 1.0f; mOut._12 = 0.0f; mOut._13 = 0.0f; mOut._14 = 0.0f; 930 | mOut._21 = 0.0f; mOut._22 = cosAngle; mOut._23 = -sinAngle; mOut._24 = 0.0f; 931 | mOut._31 = 0.0f; mOut._32 = sinAngle; mOut._33 = cosAngle; mOut._34 = 0.0f; 932 | mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f; 933 | 934 | return mOut; 935 | } 936 | 937 | inline float4x4 rotationY(float a) 938 | { 939 | float sinAngle = sinf(a); 940 | float cosAngle = cosf(a); 941 | 942 | float4x4 mOut; 943 | 944 | mOut._11 = cosAngle; mOut._12 = 0.0f; mOut._13 = sinAngle; mOut._14 = 0.0f; 945 | mOut._21 = 0.0f; mOut._22 = 1.0f; mOut._23 = 0.0f; mOut._24 = 0.0f; 946 | mOut._31 = -sinAngle; mOut._32 = 0.0f; mOut._33 = cosAngle; mOut._34 = 0.0f; 947 | mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f; 948 | 949 | return mOut; 950 | } 951 | 952 | inline float4x4 rotationZ(float a) 953 | { 954 | float sinAngle = sinf(a); 955 | float cosAngle = cosf(a); 956 | 957 | float4x4 mOut; 958 | 959 | mOut._11 = cosAngle; mOut._12 = -sinAngle; mOut._13 = 0.0f; mOut._14 = 0.0f; 960 | mOut._21 = sinAngle; mOut._22 = cosAngle; mOut._23 = 0.0f; mOut._24 = 0.0f; 961 | mOut._31 = 0.0f; mOut._32 = 0.0f; mOut._33 = 1.0f; mOut._34 = 0.0f; 962 | mOut._41 = 0.0f; mOut._42 = 0.0f; mOut._43 = 0.0f; mOut._44 = 1.0f; 963 | 964 | return mOut; 965 | } 966 | /* 967 | // 3D Rotation matrix for an arbitrary axis specified by x, y and z 968 | inline float4x4 rotationArbitrary(float3 axis, float a) 969 | { 970 | axis = normalize(axis); 971 | 972 | float sinAngle = sinf(a); 973 | float cosAngle = cosf(a); 974 | float oneMinusCosAngle = 1 - cosAngle; 975 | 976 | float4x4 mOut; 977 | 978 | mOut._11 = 1.0f + oneMinusCosAngle * (axis.x * axis.x - 1.0f); 979 | mOut._12 = axis.z * sinAngle + oneMinusCosAngle * axis.x * axis.y; 980 | mOut._13 = -axis.y * sinAngle + oneMinusCosAngle * axis.x * axis.z; 981 | mOut._41 = 0.0f; 982 | 983 | mOut._21 = -axis.z * sinAngle + oneMinusCosAngle * axis.y * axis.x; 984 | mOut._22 = 1.0f + oneMinusCosAngle * (axis.y * axis.y - 1.0f); 985 | mOut._23 = axis.x * sinAngle + oneMinusCosAngle * axis.y * axis.z; 986 | mOut._24 = 0.0f; 987 | 988 | mOut._31 = axis.y * sinAngle + oneMinusCosAngle * axis.z * axis.x; 989 | mOut._32 = -axis.x * sinAngle + oneMinusCosAngle * axis.z * axis.y; 990 | mOut._33 = 1.0f + oneMinusCosAngle * (axis.z * axis.z - 1.0f); 991 | mOut._34 = 0.0f; 992 | 993 | mOut._41 = 0.0f; 994 | mOut._42 = 0.0f; 995 | mOut._43 = 0.0f; 996 | mOut._44 = 1.0f; 997 | 998 | return mOut; 999 | } 1000 | 1001 | //================================================================================================== 1002 | // vLookAt -stuffs vectors into a matrix to orient object from vBase towards vTarget in plane of Normal 1003 | //================================================================================================== 1004 | inline float4x4 lookAt( const float3 vBase, const float3 vTarget, const float3 vPlaneNormal ) 1005 | { 1006 | float4x4 mOut; 1007 | float3 vForward, vLeft, vVert; 1008 | 1009 | vForward = vTarget - vBase; 1010 | vForward = normalize( vForward ); 1011 | vVert = cross( vForward, vPlaneNormal ); 1012 | vVert = normalize( vVert ); 1013 | 1014 | mOut._11 = vPlaneNormal.x; 1015 | mOut._12 = vPlaneNormal.y; 1016 | mOut._13 = vPlaneNormal.z; 1017 | mOut._14 = 0; 1018 | 1019 | mOut._21 = vVert.x; 1020 | mOut._22 = vVert.y; 1021 | mOut._23 = vVert.z; 1022 | mOut._24 = 0; 1023 | 1024 | mOut._31 = vForward.x; 1025 | mOut._32 = vForward.y; 1026 | mOut._33 = vForward.z; 1027 | mOut._34 = 0; 1028 | 1029 | mOut._41 = vBase.x; 1030 | mOut._42 = vBase.y; 1031 | mOut._43 = vBase.z; 1032 | mOut._44 = 1; 1033 | 1034 | return mOut; 1035 | } 1036 | 1037 | //================================================================================================== 1038 | // vLookAtYZ point Y-axis along vUp, and up-orientation () from fwd vector. 1039 | //================================================================================================== 1040 | inline float4x4 lookAtYZ( const float3 vPos, const float3 vTo, const float3 vUp ) 1041 | { 1042 | float4x4 mOut; 1043 | 1044 | float3 vLeft = normalize( cross( vTo, vUp ) ); // or could extract from top row of bugMat 1045 | 1046 | mOut._11 = vLeft.x; 1047 | mOut._12 = vLeft.y; 1048 | mOut._13 = vLeft.z; 1049 | mOut._14 = 0; 1050 | 1051 | mOut._21 = vTo.x; 1052 | mOut._22 = vTo.y; 1053 | mOut._23 = vTo.z; 1054 | mOut._24 = 0; 1055 | 1056 | float3 vFwd = normalize( cross( vLeft, vTo ) ); 1057 | mOut._31 = vFwd.x; 1058 | mOut._32 = vFwd.y; 1059 | mOut._33 = vFwd.z; 1060 | mOut._34 = 0; 1061 | 1062 | mOut._41 = vPos.x; 1063 | mOut._42 = vPos.y; 1064 | mOut._43 = vPos.z; 1065 | mOut._44 = 1; 1066 | 1067 | 1068 | return mOut; 1069 | } 1070 | 1071 | inline float stepFunc( float t ) 1072 | { 1073 | if ( t <= 0 ) 1074 | return 0; 1075 | else if ( t>0 ) 1076 | return 1; 1077 | } 1078 | 1079 | inline float smoothStep( float t ) 1080 | { 1081 | if ( t <= 0 ) 1082 | return 0; 1083 | else if ( t>=1 ) 1084 | return 1; 1085 | else 1086 | return t*t*(3 - 2*t); 1087 | } 1088 | 1089 | float periodicSmoothStep( float x ) 1090 | { 1091 | float base = floorf( x ); 1092 | float frac = x - base; 1093 | return base + smoothStep( frac ); 1094 | } 1095 | */ --------------------------------------------------------------------------------