lowpoly-walking-simulator/directx11_hellovr/dxHelloworld1/dxHelloworld1.cpp

1053 lines
27 KiB
C++
Raw Normal View History

2024-11-14 11:54:38 +00:00
// dxHelloworld1.cpp : <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ㡣
//
#include "stdafx.h"
#include "dxHelloworld1.h"
#include <d3d11.h>
#include <DirectXColors.h>
#include "cameraclass.h"
#include "modelclass.h"
#include "colorshaderclass.h"
#include <DirectXMath.h>
#include "../openvr/headers/openvr.h"
#include "rendertextureclass.h"
#include "debugwindowclass.h"
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "openvr_api.lib")
#define MAX_LOADSTRING 100
//#define VR_DISABLED
// ȫ<>ֱ<EFBFBD><D6B1><EFBFBD>:
HINSTANCE hInst; // <20><>ǰʵ<C7B0><CAB5>
WCHAR szTitle[MAX_LOADSTRING]; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>
WCHAR szWindowClass[MAX_LOADSTRING]; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
UINT clientWidth = 1280;
UINT clientHeight = 720;
const float SCREEN_DEPTH = 1000.0f;
const float SCREEN_NEAR = 0.1f;
const float MOVE_STEP = 0.3f;
const float ROTATE_STEP = 5;
D3DXMATRIX m_projectionMatrix;
D3DXMATRIX m_orthoMatrix;
ID3D11Device* pDevice = nullptr;
ID3D11DeviceContext* pImmediateContext = nullptr;
ID3D11Texture2D* pBackBufferTex;
IDXGISwapChain* pSwapChain = nullptr;
ID3D11RenderTargetView* pRenderTargetView = nullptr;
ID3D11DepthStencilView* pDepthStencilView = nullptr;
ID3D11DepthStencilState * pDSState;
ID3D11DepthStencilState* m_depthDisabledStencilState;
D3D_DRIVER_TYPE driverType;
D3D_FEATURE_LEVEL featureLevel;
D3D11_VIEWPORT viewport;
CameraClass* m_CameraLeft = nullptr,
*m_CameraRight = nullptr;
ModelClass* m_Model = nullptr;
ColorShaderClass* m_ColorShader = nullptr;
RenderTextureClass* m_RenderTextureLeft, *m_RenderTextureRight;
DebugWindowClass* m_DebugWindowLeft, *m_DebugWindowRight;
uint32_t m_nRenderWidth;
uint32_t m_nRenderHeight;
float m_fNearClip;
float m_fFarClip;
float m_fScaleSpacing;
float m_fScale;
Matrix4 m_mat4HMDPose;
Matrix4 m_mat4eyePosLeft;
Matrix4 m_mat4eyePosRight;
Matrix4 m_mat4ProjectionCenter;
Matrix4 m_mat4ProjectionLeft;
Matrix4 m_mat4ProjectionRight;
vr::IVRSystem *m_pHMD;
vr::IVRRenderModels *m_pRenderModels;
vr::TrackedDevicePose_t m_rTrackedDevicePose[vr::k_unMaxTrackedDeviceCount];
Matrix4 m_rmat4DevicePose[vr::k_unMaxTrackedDeviceCount];
int m_iTrackedControllerCount;
int m_iTrackedControllerCount_Last;
int m_iValidPoseCount;
int m_iValidPoseCount_Last;
bool m_bShowCubes;
std::string m_strPoseClasses; // what classes we saw poses for this frame
char m_rDevClassChar[vr::k_unMaxTrackedDeviceCount]; // for each device, a character representing its class
namespace Memory
{
template <class T> void SafeDelete(T& t)
{
if (t)
{
delete t;
t = nullptr;
}
}
template <class T> void SafeDeleteArr(T& t)
{
if (t)
{
delete[]t;
t = nullptr;
}
}
template <class T> void SafeRelease(T& t)
{
if (t)
{
t->Release();
t = nullptr;
}
}
}
// <20>˴<EFBFBD><CBB4><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD>а<EFBFBD><D0B0><EFBFBD><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
// d3d function prototypes
bool init(HWND hWnd);
void render_frame(void);
void clean(void);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: <20>ڴ˷<DAB4><CBB7>ô<EFBFBD><C3B4>
// <20><>ʼ<EFBFBD><CABC>ȫ<EFBFBD><C8AB><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_DXHELLOWORLD1, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// ִ<><D6B4>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DXHELLOWORLD1));
MSG msg;
bool done, result;
// Initialize the message structure.
ZeroMemory(&msg, sizeof(MSG));
// Loop until there is a quit message from the window or the user.
done = false;
while (!done)
{
// Handle the windows messages.
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// If windows signals to end the application then exit out.
if (msg.message == WM_QUIT)
{
done = true;
}
else
{
// Otherwise do the frame processing.
render_frame();
}
}
clean();
return (int) msg.wParam;
}
void MyDebug(LPCWSTR msg)
{
MessageBox(NULL, msg, _T(""), 0);
}
//
// <20><><EFBFBD><EFBFBD>: MyRegisterClass()
//
// Ŀ<><C4BF>: ע<><EFBFBD><E1B4B0><EFBFBD>
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DXHELLOWORLD1));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_DXHELLOWORLD1);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// <20><><EFBFBD><EFBFBD>: InitInstance(HINSTANCE, int)
//
// Ŀ<><C4BF>: <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//
// ע<><D7A2>:
//
// <20>ڴ˺<DAB4><CBBA><EFBFBD><EFBFBD>У<EFBFBD><D0A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȫ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>򴰿ڡ<F2B4B0BF>
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // <20><>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6B4A2>ȫ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD>
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, clientWidth, clientHeight, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
if (!init(hWnd))
{
exit(0);
}
return TRUE;
}
//
// <20><><EFBFBD><EFBFBD>: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// Ŀ<><C4BF>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>Ϣ<EFBFBD><CFA2>
//
// WM_COMMAND - <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD>ó<EFBFBD><C3B3><EFBFBD><EFBFBD>˵<EFBFBD>
// WM_PAINT - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// WM_DESTROY - <20><><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// <20><><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD>ѡ<EFBFBD><D1A1>:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: <20>ڴ˴<DAB4><CBB4><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9> hdc <20><><EFBFBD>κλ<CEBA>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD>...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ڡ<EFBFBD><DAA1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
void dprintf(const char *fmt, ...)
{
va_list args;
char buffer[2048];
va_start(args, fmt);
vsprintf_s(buffer, fmt, args);
va_end(args);
OutputDebugStringA(buffer);
}
string MatrixToString(const Matrix4& matrix)
{
char buf[1000];
int start = 0;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
start += sprintf_s(buf + start, ARRAYSIZE(buf) - start, "%.5f, ", matrix[j * 4 + i]);
}
start += sprintf_s(buf + start, ARRAYSIZE(buf) - start, "\n");
}
string temp(buf);
return temp;
}
Matrix4 GetHMDMatrixPoseEye(vr::Hmd_Eye nEye)
{
if (!m_pHMD)
return Matrix4();
vr::HmdMatrix34_t matEyeRight = m_pHMD->GetEyeToHeadTransform(nEye);
Matrix4 matrixObj(
matEyeRight.m[0][0], matEyeRight.m[1][0], matEyeRight.m[2][0], 0.0,
matEyeRight.m[0][1], matEyeRight.m[1][1], matEyeRight.m[2][1], 0.0,
matEyeRight.m[0][2], matEyeRight.m[1][2], matEyeRight.m[2][2], 0.0,
matEyeRight.m[0][3], matEyeRight.m[1][3], matEyeRight.m[2][3], 1.0f
);
return matrixObj.invert();
}
Matrix4 GetHMDMatrixProjectionEye(vr::Hmd_Eye nEye)
{
if (!m_pHMD)
return Matrix4();
// TODO check here
vr::HmdMatrix44_t mat = m_pHMD->GetProjectionMatrix(nEye, m_fNearClip, m_fFarClip);
return Matrix4(
mat.m[0][0], mat.m[1][0], mat.m[2][0], mat.m[3][0],
mat.m[0][1], mat.m[1][1], mat.m[2][1], mat.m[3][1],
mat.m[0][2], mat.m[1][2], mat.m[2][2], mat.m[3][2],
mat.m[0][3], mat.m[1][3], mat.m[2][3], mat.m[3][3]
);
}
void SetupCameras()
{
m_mat4ProjectionLeft = GetHMDMatrixProjectionEye(vr::Eye_Left);
m_mat4ProjectionRight = GetHMDMatrixProjectionEye(vr::Eye_Right);
m_mat4eyePosLeft = GetHMDMatrixPoseEye(vr::Eye_Left);
m_mat4eyePosRight = GetHMDMatrixPoseEye(vr::Eye_Right);
//dprintf("left = %s\n, right = %s\n", MatrixToString(m_mat4ProjectionLeft).c_str(),
// MatrixToString(m_mat4ProjectionRight).c_str());
}
Matrix4 GetCurrentViewProjectionMatrix(vr::Hmd_Eye nEye)
{
Matrix4 matMVP;
if (nEye == vr::Eye_Left)
{
matMVP = m_mat4ProjectionLeft * m_mat4eyePosLeft * m_mat4HMDPose;
}
else if (nEye == vr::Eye_Right)
{
matMVP = m_mat4ProjectionRight * m_mat4eyePosRight * m_mat4HMDPose;
}
//dprintf("pleft = %s\n, eyeLeft = %s\n, hmdPose = %s\n",
// MatrixToString(m_mat4ProjectionLeft).c_str(),
// MatrixToString(m_mat4eyePosLeft).c_str(),
// MatrixToString(m_mat4HMDPose).c_str());
return matMVP;
}
Matrix4 ConvertSteamVRMatrixToMatrix4( const vr::HmdMatrix34_t &matPose )
{
Matrix4 matrixObj(
matPose.m[0][0], matPose.m[1][0], matPose.m[2][0], 0.0,
matPose.m[0][1], matPose.m[1][1], matPose.m[2][1], 0.0,
matPose.m[0][2], matPose.m[1][2], matPose.m[2][2], 0.0,
matPose.m[0][3], matPose.m[1][3], matPose.m[2][3], 1.0f
);
return matrixObj;
}
void UpdateHMDMatrixPose()
{
if (!m_pHMD)
return;
vr::VRCompositor()->WaitGetPoses(m_rTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0);
m_iValidPoseCount = 0;
m_strPoseClasses = "";
for (int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; ++nDevice)
{
if (m_rTrackedDevicePose[nDevice].bPoseIsValid)
{
m_iValidPoseCount++;
m_rmat4DevicePose[nDevice] = ConvertSteamVRMatrixToMatrix4(m_rTrackedDevicePose[nDevice].mDeviceToAbsoluteTracking);
if (m_rDevClassChar[nDevice] == 0)
{
switch (m_pHMD->GetTrackedDeviceClass(nDevice))
{
case vr::TrackedDeviceClass_Controller: m_rDevClassChar[nDevice] = 'C'; break;
case vr::TrackedDeviceClass_HMD: m_rDevClassChar[nDevice] = 'H'; break;
case vr::TrackedDeviceClass_Invalid: m_rDevClassChar[nDevice] = 'I'; break;
case vr::TrackedDeviceClass_GenericTracker: m_rDevClassChar[nDevice] = 'O'; break;
case vr::TrackedDeviceClass_TrackingReference: m_rDevClassChar[nDevice] = 'T'; break;
default: m_rDevClassChar[nDevice] = '?'; break;
}
}
m_strPoseClasses += m_rDevClassChar[nDevice];
}
}
if (m_rTrackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid)
{
m_mat4HMDPose = m_rmat4DevicePose[vr::k_unTrackedDeviceIndex_Hmd].invert();
}
else
{
dprintf("pose not valid");
}
}
// this function initializes D3D and VR
bool init(HWND hWnd)
{
UINT createDeviceFlags = 0;
#ifdef DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
#ifndef VR_DISABLED
// Loading the SteamVR Runtime
vr::EVRInitError eError = vr::VRInitError_None;
m_pHMD = vr::VR_Init(&eError, vr::VRApplication_Scene);
if (eError != vr::VRInitError_None)
{
m_pHMD = NULL;
char buf[1024];
sprintf_s(buf, ARRAYSIZE(buf), "Unable to init VR runtime: %s", vr::VR_GetVRInitErrorAsEnglishDescription(eError));
string temp(buf);
wstring wtemp(temp.begin(), temp.end());
MessageBox(hWnd, wtemp.c_str(), L"VR_Init Failed", 0);
return false;
}
m_pHMD->GetRecommendedRenderTargetSize(&m_nRenderWidth, &m_nRenderHeight);
dprintf("width = %d, height = %d", m_nRenderWidth, m_nRenderHeight);
//m_nRenderWidth /= 2;
//m_nRenderHeight /= 4;
//clientWidth = m_nRenderWidth;
//clientHeight = m_nRenderHeight;
m_pRenderModels = (vr::IVRRenderModels *)vr::VR_GetGenericInterface(vr::IVRRenderModels_Version, &eError);
if (!m_pRenderModels)
{
m_pHMD = NULL;
vr::VR_Shutdown();
char buf[1024];
sprintf_s(buf, ARRAYSIZE(buf), "Unable to get render model interface: %s", vr::VR_GetVRInitErrorAsEnglishDescription(eError));
string temp(buf);
wstring wtemp(temp.begin(), temp.end());
MessageBox(hWnd, wtemp.c_str(), L"VR_Init Failed", NULL);
return false;
}
if (!vr::VRCompositor())
{
dprintf("Compositor initialization failed. See log file for details\n");
return false;
}
#endif
// CREATE DEVICE AND SWAP CHAIN
D3D_DRIVER_TYPE driverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE, // the first thing to try, if failed, go to the next
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE
};
UINT numDriverTypes = ARRAYSIZE(driverTypes);
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0, // texture size and others..
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3
};
UINT numFeatureLevels = ARRAYSIZE(featureLevels);
DXGI_SWAP_CHAIN_DESC swapDesc;
ZeroMemory(&swapDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapDesc.BufferCount = 1;
swapDesc.BufferDesc.Width = clientWidth;
swapDesc.BufferDesc.Height = clientHeight;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // unsigned normal
swapDesc.BufferDesc.RefreshRate.Numerator = 60;
swapDesc.BufferDesc.RefreshRate.Denominator = 1;
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapDesc.OutputWindow = hWnd;
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapDesc.Windowed = true;
swapDesc.SampleDesc.Count = 1; // multisampling, which antialiasing for geometry. Turn it off
swapDesc.SampleDesc.Quality = 0;
swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // alt-enter fullscreen
swapDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
HRESULT errorCode;
for (unsigned i = 0; i < numDriverTypes; ++i)
{
errorCode = D3D11CreateDeviceAndSwapChain(NULL, driverTypes[i], NULL, createDeviceFlags,
featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &swapDesc, &pSwapChain, &pDevice,
&featureLevel, &pImmediateContext);
if (SUCCEEDED(errorCode))
{
driverType = driverTypes[i];
break;
}
}
if (FAILED(errorCode))
{
OutputDebugString(_T("FAILED TO CREATE DEVICE AND SWAP CHAIN"));
MyDebug(_T("FAILED TO CREATE DEVICE AND SWAP CHAIN"));
return false;
}
HRESULT result;
// CREATE RENDER TARGET VIEW
result = pSwapChain->GetBuffer(NULL, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBufferTex));
if (FAILED(result))
{
return false;
}
D3D11_TEXTURE2D_DESC BBDesc;
ZeroMemory(&BBDesc, sizeof(D3D11_TEXTURE2D_DESC));
pBackBufferTex->GetDesc(&BBDesc);
D3D11_RENDER_TARGET_VIEW_DESC RTVDesc;
ZeroMemory(&RTVDesc, sizeof(D3D11_RENDER_TARGET_VIEW_DESC));
RTVDesc.Format = BBDesc.Format;
RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
//RTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
RTVDesc.Texture2D.MipSlice = 0;
result = pDevice->CreateRenderTargetView(pBackBufferTex, &RTVDesc, &pRenderTargetView);
if (FAILED(result))
{
MyDebug(_T("ERROR"));
}
Memory::SafeRelease(pBackBufferTex);
// CREATE DEPTH STENCIL
ID3D11Texture2D* pDepthStencil = NULL;
D3D11_TEXTURE2D_DESC descDepth;
ZeroMemory(&descDepth, sizeof(descDepth));
descDepth.Width = m_nRenderWidth;// swapDesc.BufferDesc.Width;
descDepth.Height = m_nRenderHeight;// swapDesc.BufferDesc.Height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;// DXGI_FORMAT_D32_FLOAT;//DXGI_FORMAT_D24_UNORM_S8_UINT;;//pDeviceSettings->d3d11.AutoDepthStencilFormat;
// DXGI_FORMAT_D32_FLOAT_S8X24_UINT
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
result = pDevice->CreateTexture2D(&descDepth, NULL, &pDepthStencil);
if (FAILED(result))
return false;
D3D11_DEPTH_STENCIL_DESC dsDesc;
ZeroMemory(&dsDesc, sizeof(dsDesc));
// Depth test parameters
dsDesc.DepthEnable = true;
dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
dsDesc.DepthFunc = D3D11_COMPARISON_LESS;
// Stencil test parameters
dsDesc.StencilEnable = true;
dsDesc.StencilReadMask = 0xFF;
dsDesc.StencilWriteMask = 0xFF;
// Stencil operations if pixel is front-facing
dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Stencil operations if pixel is back-facing
dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Create depth stencil state
result = pDevice->CreateDepthStencilState(&dsDesc, &pDSState);
if (FAILED(result))
{
return false;
}
// Bind depth stencil state
pImmediateContext->OMSetDepthStencilState(pDSState, 1);
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
ZeroMemory(&descDSV, sizeof(descDSV));
descDSV.Format = descDepth.Format;// DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
//descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
descDSV.Texture2D.MipSlice = 0;
// Create the depth stencil view
result = pDevice->CreateDepthStencilView(pDepthStencil, // Depth stencil texture
&descDSV, // Depth stencil desc
&pDepthStencilView); // [out] Depth stencil view
if (FAILED(result))
{
WCHAR buf[100];
wsprintf(buf, L"%x", result);
MyDebug(buf);
MyDebug(L"CreateDepthStencilView failed.");
return false;
}
//BIND RENDER TARGET VIEW
pImmediateContext->OMSetRenderTargets(1, &pRenderTargetView, pDepthStencilView); // depth stencil view is for shadow map
D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc;
// Clear the second depth stencil state before setting the parameters.
ZeroMemory(&depthDisabledStencilDesc, sizeof(depthDisabledStencilDesc));
// Now create a second depth stencil state which turns off the Z buffer for 2D rendering. The only difference is
// that DepthEnable is set to false, all other parameters are the same as the other depth stencil state.
depthDisabledStencilDesc.DepthEnable = false;
depthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS;
depthDisabledStencilDesc.StencilEnable = true;
depthDisabledStencilDesc.StencilReadMask = 0xFF;
depthDisabledStencilDesc.StencilWriteMask = 0xFF;
depthDisabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthDisabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthDisabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
depthDisabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthDisabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
// Create the state using the device.
result = pDevice->CreateDepthStencilState(&depthDisabledStencilDesc, &m_depthDisabledStencilState);
if (FAILED(result))
{
return false;
}
//VIEWPORT CREATION
viewport.Width = static_cast<float>(m_nRenderWidth);
viewport.Height = static_cast<float>(m_nRenderHeight);
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
// BIND VIEWPORT
pImmediateContext->RSSetViewports(1, &viewport);
// Create the camera object.
m_CameraLeft = new CameraClass;
if (!m_CameraLeft)
{
return false;
}
// Set the initial position of the camera.
m_CameraLeft->SetPosition(0.0f, 0.0f, -10.0f);
// Create the camera object.
m_CameraRight = new CameraClass;
if (!m_CameraRight)
{
return false;
}
// Set the initial position of the camera.
m_CameraRight->SetPosition(1.5f, 0.0f, -10.0f);
// Create the model object.
m_Model = new ModelClass;
if (!m_Model)
{
return false;
}
// Initialize the model object.
result = m_Model->Initialize(pDevice, pImmediateContext, L"cube_texture.png");
if (!result)
{
MessageBox(hWnd, L"Could not initialize the model object.", L"Error", MB_OK);
return false;
}
// Create the color shader object.
m_ColorShader = new ColorShaderClass;
if (!m_ColorShader)
{
return false;
}
// Initialize the color shader object.
result = m_ColorShader->Initialize(pDevice, hWnd);
if (!result)
{
MessageBox(hWnd, L"Could not initialize the color shader object.", L"Error", MB_OK);
return false;
}
// Create the render to texture object.
m_RenderTextureLeft = new RenderTextureClass;
if (!m_RenderTextureLeft)
{
return false;
}
// Initialize the render to texture object.
result = m_RenderTextureLeft->Initialize(pDevice, m_nRenderWidth, m_nRenderHeight);
if (!result)
{
return false;
}
m_RenderTextureRight = new RenderTextureClass;
if (!m_RenderTextureRight)
{
return false;
}
// Initialize the render to texture object.
result = m_RenderTextureRight->Initialize(pDevice, m_nRenderWidth, m_nRenderHeight);
if (!result)
{
return false;
}
// Create the debug window object.
m_DebugWindowLeft = new DebugWindowClass;
if (!m_DebugWindowLeft)
{
return false;
}
// Initialize the debug window object.
result = m_DebugWindowLeft->Initialize(pDevice, clientWidth, clientHeight, clientWidth/2, clientHeight);
if (!result)
{
MessageBox(hWnd, L"Could not initialize the debug window object.", L"Error", MB_OK);
return false;
}
m_DebugWindowRight = new DebugWindowClass;
if (!m_DebugWindowRight)
{
return false;
}
// Initialize the debug window object.
result = m_DebugWindowRight->Initialize(pDevice, clientWidth, clientHeight, clientWidth/2, clientHeight);
// Create an orthographic projection matrix for 2D rendering.
//D3DXMatrixOrthoLH(&m_orthoMatrix, (float)screenWidth, (float)screenHeight, screenNear, screenDepth);
DirectX::XMMATRIX mo = DirectX::XMMatrixOrthographicLH((float)clientWidth, (float)clientHeight, 0, 10);
m_orthoMatrix.set((const float*)&mo.r);
m_fScale = 0.3f;
m_fScaleSpacing = 4.0f;
m_fNearClip = 0.1f;
m_fFarClip = 30.0f;
SetupCameras();
if (!vr::VRCompositor())
{
printf("Compositor initialization failed. See log file for details\n");
return false;
}
return true;
}
void TurnZBufferOn()
{
pImmediateContext->OMSetDepthStencilState(pDSState, 1);
return;
}
void TurnZBufferOff()
{
pImmediateContext->OMSetDepthStencilState(m_depthDisabledStencilState, 1);
return;
}
bool errorshown = false;
bool RenderScene(vr::Hmd_Eye nEye)
{
bool result;
D3DXMATRIX viewMatrix, projectionMatrix, worldMatrix, orthoMatrix;
projectionMatrix = GetCurrentViewProjectionMatrix(nEye);
// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing.
m_Model->Render(pImmediateContext);
// Render the model using the color shader.
result = m_ColorShader->Render(pImmediateContext, m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix, m_Model->GetTexture());
if (!errorshown && !result)
{
errorshown = true;
return false;
MyDebug(_T("render failed"));
}
return true;
}
bool RenderToTexture()
{
bool result;
// Set the render target to be the render to texture.
m_RenderTextureLeft->SetRenderTarget(pImmediateContext, pDepthStencilView);
//Clear the render to texture background to blue so we can differentiate it from the rest of the normal scene.
// Clear the render to texture.
m_RenderTextureLeft->ClearRenderTarget(pImmediateContext, pDepthStencilView, 0.0f, 0.0f, 1.0f, 1.0f);
// Render the scene now and it will draw to the render to texture instead of the back buffer.
result = RenderScene(vr::Hmd_Eye::Eye_Left);
if (!result)
{
return false;
}
// Set the render target to be the render to texture.
m_RenderTextureRight->SetRenderTarget(pImmediateContext, pDepthStencilView);
//Clear the render to texture background to blue so we can differentiate it from the rest of the normal scene.
// Clear the render to texture.
m_RenderTextureRight->ClearRenderTarget(pImmediateContext, pDepthStencilView, 0.0f, 0.0f, 1.0f, 1.0f);
// Render the scene now and it will draw to the render to texture instead of the back buffer.
result = RenderScene(vr::Hmd_Eye::Eye_Right);
if (!result)
{
return false;
}
// Reset the render target back to the original back buffer and not the render to texture anymore.
pImmediateContext->OMSetRenderTargets(1, &pRenderTargetView, pDepthStencilView);
return true;
}
// this is the function used to render a single frame
void render_frame(void)
{
bool result;
// Render the entire scene to the texture first.
result = RenderToTexture();
if (!result)
{
return;
}
D3DXMATRIX orthoMatrix;
TurnZBufferOff();
result = m_DebugWindowLeft->Render(pImmediateContext, 0, 0);
if (!result)
{
return;
}
orthoMatrix = m_orthoMatrix;
Matrix4 identity;
// Render the debug window using the texture shader.
result = m_ColorShader->Render(pImmediateContext, m_DebugWindowLeft->GetIndexCount(), identity, identity,
orthoMatrix, m_RenderTextureLeft->GetShaderResourceView());
if (!result)
{
return;
}
result = m_DebugWindowRight->Render(pImmediateContext, 546, 0);
if (!result)
{
return;
}
orthoMatrix = m_orthoMatrix;
// Render the debug window using the texture shader.
result = m_ColorShader->Render(pImmediateContext, m_DebugWindowRight->GetIndexCount(), identity, identity,
orthoMatrix, m_RenderTextureRight->GetShaderResourceView());
if (!result)
{
return;
}
TurnZBufferOn();
pSwapChain->Present(0, 0);
vr::Texture_t leftEyeTexture = { m_RenderTextureLeft->GetTexture(), vr::TextureType_DirectX, vr::ColorSpace_Auto};
vr::EVRCompositorError error1 = vr::VRCompositor()->Submit(vr::Eye_Left, &leftEyeTexture);
vr::Texture_t rightEyeTexture = { m_RenderTextureRight->GetTexture(), vr::TextureType_DirectX, vr::ColorSpace_Auto};
vr::VRCompositor()->Submit(vr::Eye_Right, &rightEyeTexture);
if (error1)
dprintf("error is %d \n", error1);
UpdateHMDMatrixPose();
}
// this is the function that cleans up D3D and VR
void clean(void)
{
// Release the color shader object.
if(m_ColorShader)
{
m_ColorShader->Shutdown();
delete m_ColorShader;
m_ColorShader = 0;
}
// Release the model object.
if(m_Model)
{
m_Model->Shutdown();
delete m_Model;
m_Model = 0;
}
// Release the camera object.
if(m_CameraLeft)
{
delete m_CameraLeft;
m_CameraLeft = 0;
}
if (pImmediateContext) pImmediateContext->ClearState();
Memory::SafeRelease(pDepthStencilView);
Memory::SafeRelease(pRenderTargetView);
Memory::SafeRelease(pSwapChain);
Memory::SafeRelease(pImmediateContext);
Memory::SafeRelease(pDevice);
m_RenderTextureLeft->Shutdown();
m_RenderTextureRight->Shutdown();
m_DebugWindowLeft->Shutdown();
m_DebugWindowRight->Shutdown();
if (m_pHMD)
{
vr::VR_Shutdown();
}
}