void OVR_SDL2_app::conf_OVR() { // Configure the renderer. Zeroing the configuration stucture causes all // display, window, and device specifications to take on current values // as put in place by SDL. This should work cross-platform, but doesn't. // A workaround is currently (0.4.3b) required under linux. SDL_SysWMinfo info; ovrGLConfig cfg; memset(&info, 0, sizeof (SDL_SysWMinfo)); memset(&cfg, 0, sizeof (ovrGLConfig)); SDL_VERSION(&info.version); SDL_GetWindowWMInfo(window, &info); cfg.OGL.Header.API = ovrRenderAPI_OpenGL; cfg.OGL.Header.RTSize.w = hmd->Resolution.w; cfg.OGL.Header.RTSize.h = hmd->Resolution.h; #ifdef __linux__ cfg.OGL.Disp = info.info.x11.display; cfg.OGL.Win = info.info.x11.window; #endif // Set the configuration and receive eye render descriptors in return. ovrHmd_ConfigureRendering(hmd, &cfg.Config, ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive, hmd->DefaultEyeFov, erd); offset[0] = erd[0].HmdToEyeViewOffset; offset[1] = erd[1].HmdToEyeViewOffset; // Determine the buffer size required by each eye of the current HMD. ovrSizei size[2]; size[0] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, hmd->DefaultEyeFov[0], 1); size[1] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, hmd->DefaultEyeFov[1], 1); // Initialize the off-screen render buffers. We're using one buffer per-eye // instead of concatenating both eyes into a single buffer. for (int i = 0; i < 2; i++) { if ((buffer[i] = new framebuffer(size[i].w, size[i].h))) { ovrGLTexture *p = reinterpret_cast<ovrGLTexture*>(tex + i); memset(p, 0, sizeof (ovrGLTexture)); p->OGL.Header.API = ovrRenderAPI_OpenGL; p->OGL.Header.TextureSize = size[i]; p->OGL.Header.RenderViewport.Size = size[i]; p->OGL.TexId = buffer[i]->color; } } }
virtual void initGl() { CubeScene::initGl(); ovrRenderAPIConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.Header.API = ovrRenderAPI_OpenGL; cfg.Header.RTSize = hmd->Resolution; cfg.Header.Multisample = 1; int distortionCaps = ovrDistortionCap_Chromatic; ovrEyeRenderDesc eyeRenderDescs[2]; int configResult = ovrHmd_ConfigureRendering(hmd, &cfg, distortionCaps, hmd->DefaultEyeFov, eyeRenderDescs); for_each_eye([&](ovrEyeType eye){ PerEyeArg & eyeArg = eyes[eye]; ovrFovPort fov = hmd->DefaultEyeFov[eye]; ovrTextureHeader & textureHeader = textures[eye].Header; ovrSizei texSize = ovrHmd_GetFovTextureSize(hmd, eye, fov, 1.0f); textureHeader.API = ovrRenderAPI_OpenGL; textureHeader.TextureSize = texSize; textureHeader.RenderViewport.Size = texSize; textureHeader.RenderViewport.Pos.x = 0; textureHeader.RenderViewport.Pos.y = 0; eyeArg.frameBuffer.init(Rift::fromOvr(texSize)); ((ovrGLTexture&)textures[eye]).OGL.TexId = eyeArg.frameBuffer.color->texture; ovrVector3f offset = eyeRenderDescs[eye].ViewAdjust; ovrMatrix4f projection = ovrMatrix4f_Projection(fov, 0.01f, 100, true); eyeArg.projection = Rift::fromOvr(projection); eyeArg.modelviewOffset = glm::translate(glm::mat4(), Rift::fromOvr(offset)); }); }
void OculusInterface::initOculus(float _devicePixelAspect) { m_devicePixelAspect=_devicePixelAspect; std::cout<<"setting device aspect "<<m_devicePixelAspect<<"\n"; m_hmd = ovrHmd_Create(0); if (!m_hmd) { std::cerr<<"Unable to create HMD: "<< ovrHmd_GetLastError(NULL)<<std::endl; std::cerr<<"Attempting to run without HMD\n"; // If we didn't detect an Hmd, create a simulated one for debugging. m_hmd = ovrHmd_CreateDebug(ovrHmd_DK1); if (!m_hmd) { // Failed Hmd creation. exit(EXIT_FAILURE); } } m_windowWidth=m_hmd->Resolution.w; m_windowHeight=m_hmd->Resolution.h; oculusDebug(); // Start the sensor which provides the Rift’s pose and motion. ovrHmd_ConfigureTracking(m_hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, 0); // let's fill in some info about oculus m_eyeres[0] = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left, m_hmd->DefaultEyeFov[0], 1.0); m_eyeres[1] = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right, m_hmd->DefaultEyeFov[1],1.0); /* and create a single render target texture to encompass both eyes */ //m_fbWidth = m_eyeres[0].w + m_eyeres[1].w; //m_fbHeight = m_eyeres[0].h > m_eyeres[1].h ? m_eyeres[0].h : m_eyeres[1].h; ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left,m_hmd->DefaultEyeFov[0], m_devicePixelAspect); ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right,m_hmd->DefaultEyeFov[1], m_devicePixelAspect); // Determine dimensions to fit into a single render target. ovrSizei renderTargetSize; m_fbWidth = recommenedTex0Size.w + recommenedTex1Size.w; m_fbHeight = std::max ( recommenedTex0Size.h, recommenedTex1Size.h ); createRenderTarget(); createOVRGLConfig(); createOVRTextureBuffers(); /* enable low-persistence display and dynamic prediction for lattency compensation */ ovrHmd_SetEnabledCaps(m_hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); /* configure SDK-rendering and enable chromatic abberation correction, vignetting, and * timewrap, which shifts the image before drawing to counter any lattency between the call * to ovrHmd_GetEyePose and ovrHmd_EndFrame. */ unsigned int dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive; if(!ovrHmd_ConfigureRendering(m_hmd, &m_glcfg.Config, dcaps, m_hmd->DefaultEyeFov, m_eyeRdesc)) { fprintf(stderr, "failed to configure distortion renderer\n"); } }
void initGl() { GlfwApp::initGl(); ovrFovPort eyeFovPorts[2]; for_each_eye([&](ovrEyeType eye){ ovrTextureHeader & eyeTextureHeader = textures[eye].Header; eyeFovPorts[eye] = hmd->DefaultEyeFov[eye]; eyeTextureHeader.TextureSize = ovrHmd_GetFovTextureSize(hmd, eye, hmd->DefaultEyeFov[eye], 1.0f); eyeTextureHeader.RenderViewport.Size = eyeTextureHeader.TextureSize; eyeTextureHeader.RenderViewport.Pos.x = 0; eyeTextureHeader.RenderViewport.Pos.y = 0; eyeTextureHeader.API = ovrRenderAPI_OpenGL; eyeFramebuffers[eye] = FramebufferWrapperPtr(new FramebufferWrapper()); eyeFramebuffers[eye]->init(ovr::toGlm(eyeTextureHeader.TextureSize)); ((ovrGLTexture&)textures[eye]).OGL.TexId = oglplus::GetName(eyeFramebuffers[eye]->color); }); ovrGLConfig cfg; memset(&cfg, 0, sizeof(ovrGLConfig)); cfg.OGL.Header.API = ovrRenderAPI_OpenGL; cfg.OGL.Header.Multisample = 1; /** * In the Direct3D examples in the Oculus SDK, they make the point that the * onscreen window size does not need to match the Rift resolution. However * this doesn't currently work in OpenGL, so we have to create the window at * the full resolution of the Rift and ensure that we use the same * size here when setting the BackBufferSize. */ cfg.OGL.Header.BackBufferSize = ovr::fromGlm(getSize()); ON_LINUX([&]{ cfg.OGL.Disp = (Display*)glfw::getNativeDisplay(getWindow()); }); int distortionCaps = 0 | ovrDistortionCap_TimeWarp | ovrDistortionCap_Vignette; ON_LINUX([&]{ distortionCaps |= ovrDistortionCap_LinuxDevFullscreen; }); ovrEyeRenderDesc eyeRenderDescs[2]; int configResult = ovrHmd_ConfigureRendering(hmd, &cfg.Config, distortionCaps, eyeFovPorts, eyeRenderDescs); if (!configResult) { FAIL("Unable to configure SDK based distortion rendering"); } for_each_eye([&](ovrEyeType eye){ eyeOffsets[eye] = eyeRenderDescs[eye].HmdToEyeViewOffset; eyeProjections[eye] = ovr::toGlm( ovrMatrix4f_Projection(eyeFovPorts[eye], 0.01f, 1000.0f, true)); }); }
void OVRShutdown() { if ( _OVRGlobals.HMD ) { ovrHmd_ConfigureRendering( _OVRGlobals.HMD, NULL, 0, NULL, NULL ); ovrHmd_Destroy( _OVRGlobals.HMD ); _OVRGlobals.HMD = NULL; } ovr_Shutdown(); }
bool HeadMountedDisplay::configureRendering( const ovrRenderAPIConfig* conf, kvs::UInt32 caps, const ovrFovPort fov[2], ovrEyeRenderDesc desc[2] ) { ovrBool ret; KVS_OVR_CALL( ret = ovrHmd_ConfigureRendering( m_handler, conf, caps, fov, desc ) ); return ret == ovrTrue; }
void RiftSetup() { ovr_Initialize(); s_hmd = ovrHmd_Create(0); if (!s_hmd) { s_hmd = ovrHmd_CreateDebug(ovrHmd_DK1); } ovrHmd_GetDesc(s_hmd, &s_hmdDesc); DumpHMDInfo(s_hmdDesc); uint32_t supportedSensorCaps = ovrSensorCap_Orientation; uint32_t requiredSensorCaps = ovrSensorCap_Orientation; ovrBool success = ovrHmd_StartSensor(s_hmd, supportedSensorCaps, requiredSensorCaps); if (!success) { fprintf(stderr, "ERROR: HMD does not have required capabilities!\n"); exit(2); } // Figure out dimensions of render target ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(s_hmd, ovrEye_Left, s_hmdDesc.DefaultEyeFov[0], 1.0f); ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(s_hmd, ovrEye_Right, s_hmdDesc.DefaultEyeFov[1], 1.0f); s_renderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w; s_renderTargetSize.h = std::max(recommenedTex0Size.h, recommenedTex1Size.h); CreateRenderTarget(s_renderTargetSize.w, s_renderTargetSize.h); s_eyeTexture[0].Header.API = ovrRenderAPI_OpenGL; s_eyeTexture[0].Header.TextureSize = s_renderTargetSize; s_eyeTexture[0].Header.RenderViewport.Pos = {0, 0}; s_eyeTexture[0].Header.RenderViewport.Size = {s_renderTargetSize.w / 2, s_renderTargetSize.h}; ((ovrGLTexture*)(&s_eyeTexture[0]))->OGL.TexId = s_fboTex; s_eyeTexture[1].Header.API = ovrRenderAPI_OpenGL; s_eyeTexture[1].Header.TextureSize = s_renderTargetSize; s_eyeTexture[1].Header.RenderViewport.Pos = {s_renderTargetSize.w / 2, 0}; s_eyeTexture[1].Header.RenderViewport.Size = {s_renderTargetSize.w / 2, s_renderTargetSize.h}; ((ovrGLTexture*)(&s_eyeTexture[1]))->OGL.TexId = s_fboTex; // Configure ovr SDK Rendering ovrGLConfig cfg; memset(&cfg, 0, sizeof(ovrGLConfig)); cfg.OGL.Header.API = ovrRenderAPI_OpenGL; cfg.OGL.Header.RTSize = {s_config->width, s_config->height}; cfg.OGL.Header.Multisample = 0; // TODO: on windows need to set HWND, on Linux need to set other parameters if (!ovrHmd_ConfigureRendering(s_hmd, &cfg.Config, s_hmdDesc.DistortionCaps, s_hmdDesc.DefaultEyeFov, s_eyeRenderDesc)) { fprintf(stderr, "ERROR: HMD configure rendering failed!\n"); exit(3); } }
void initGl() { RiftGlfwApp::initGl(); Resource * sceneImages = SCENE_IMAGES_DK2; if (hmd->Type == ovrHmd_DK1) { sceneImages = SCENE_IMAGES_DK1; } for_each_eye([&](ovrEyeType eye){ glm::uvec2 textureSize; GlUtils::getImageAsTexture(sceneTextures[eye], sceneImages[eye], textureSize); memset(eyeTextures + eye, 0, sizeof(eyeTextures[eye])); ovrTextureHeader & eyeTextureHeader = eyeTextures[eye].Header; eyeTextureHeader.TextureSize = Rift::toOvr(textureSize); eyeTextureHeader.RenderViewport.Size = eyeTextureHeader.TextureSize; eyeTextureHeader.API = ovrRenderAPI_OpenGL; ((ovrGLTextureData&)eyeTextures[eye]).TexId = sceneTextures[eye]->texture; }); ovrRenderAPIConfig config; memset(&config, 0, sizeof(config)); config.Header.API = ovrRenderAPI_OpenGL; config.Header.RTSize = Rift::toOvr(windowSize); config.Header.Multisample = 1; #if defined(OVR_OS_WIN32) ((ovrGLConfigData&)config).Window = 0; #elif defined(OVR_OS_LINUX) ((ovrGLConfigData&)config).Win = 0; ((ovrGLConfigData&)config).Disp = 0; #endif int distortionCaps = ovrDistortionCap_Vignette | ovrDistortionCap_Chromatic; ovrEyeRenderDesc eyeRenderDescs[2]; int configResult = ovrHmd_ConfigureRendering(hmd, &config, distortionCaps, hmd->DefaultEyeFov, eyeRenderDescs); if (0 == configResult) { FAIL("Unable to configure rendering"); } ovrhmd_EnableHSWDisplaySDKRender(hmd, false); }
VR::VR(Game &game) { // create HMD if (!(m_hmd = ovrHmd_Create(0))) { std::cerr << "couldn't create Oculus HMD, falling back to debug HMD" << std::endl; if (!(m_hmd = ovrHmd_CreateDebug(ovrHmd_DK2))) throw Error("couldn't create debug HMD"); } orient_window(game); // enable position, rotation tracking ovrHmd_ConfigureTracking(m_hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, 0); // calculate framebuffer resolution and create framebuffer ovrSizei eye_res[2]; eye_res[0] = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left, m_hmd->DefaultEyeFov[0], 1.0); eye_res[1] = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right, m_hmd->DefaultEyeFov[1], 1.0); m_fb_width = eye_res[0].w + eye_res[1].w; m_fb_height = eye_res[0].h > eye_res[1].h ? eye_res[0].h : eye_res[1].h; update_fb(); // fill in ovrGLConfig ovrGLConfig glcfg; memset(&glcfg, 0, sizeof glcfg); glcfg.OGL.Header.API = ovrRenderAPI_OpenGL; glcfg.OGL.Header.RTSize = m_hmd->Resolution; glcfg.OGL.Header.Multisample = 1; glcfg.OGL.Window = GetActiveWindow(); glcfg.OGL.DC = wglGetCurrentDC(); if (!(m_hmd->HmdCaps & ovrHmdCap_ExtendDesktop)) ovrHmd_AttachToWindow(m_hmd, glcfg.OGL.Window, 0, 0); // enable HMD, distortion capabilities and enable SDK rendering ovrHmd_SetEnabledCaps(m_hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); if (!ovrHmd_ConfigureRendering(m_hmd, &glcfg.Config, ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive, m_hmd->DefaultEyeFov, m_eye_rdesc)) throw Error("failed to configure distortion rendering"); // disable health/safety warning ovrhmd_EnableHSWDisplaySDKRender(m_hmd, 0); }
void Oculus::ConfigureBackBufferRendering(ViewState* view_state, Texture* back_buffer) { ovrD3D11Config oculus_config; oculus_config.D3D11.Header.API = ovrRenderAPI_D3D11; oculus_config.D3D11.Header.BackBufferSize = OculusHelper::ConvertArrayToSizei(view_state->window_details.screen_size); oculus_config.D3D11.Header.Multisample = 1; oculus_config.D3D11.pDevice = view_state->device_interface; oculus_config.D3D11.pDeviceContext = view_state->device_context; oculus_config.D3D11.pBackBufferRT = back_buffer->GetRenderTargetView(); oculus_config.D3D11.pSwapChain = view_state->swap_chain; ovrHmd_ConfigureRendering(head_mounted_display, &oculus_config.Config, ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive, eye_fovs, eye_rendering_desc); ovrHmd_AttachToWindow(head_mounted_display, view_state->window_handler, NULL, NULL); }
/** * ERRORODE 0 => OK * ERRORCODE 1 => Unable to configure OVR Render */ int init_render_ovr(){ // Configure and Init rendering using the OVR render Core. // Input => rendered 3D texture (Two passes: 1 Left, 1 Right) // Output auto, on defined window // Configure rendering with OpenGL ovrGLConfig cfg; cfg.OGL.Header.API = ovrRenderAPI_OpenGL; cfg.OGL.Header.RTSize = OVR::Sizei( hmd->Resolution.w, hmd->Resolution.h ); cfg.OGL.Header.Multisample = 1; cfg.OGL.Window = sdl_window_info.info.win.window; cfg.OGL.DC = GetWindowDC(sdl_window_info.info.win.window); ovrFovPort eyesFov[2] = { hmd->DefaultEyeFov[0], hmd->DefaultEyeFov[1] }; if ( mode == MODE_OCULUS ){ if ( !ovrHmd_ConfigureRendering(hmd, &cfg.Config, hmd->DistortionCaps, eyesFov, eyesRenderDesc) ) return 1; // Direct OVR SDK output to Oculus Display ovrHmd_AttachToWindow(hmd, sdl_window_info.info.win.window, nullptr, nullptr); } EyeTexture[0].OGL.Header.API = ovrRenderAPI_OpenGL; EyeTexture[0].OGL.Header.TextureSize = renderTargetSize; EyeTexture[0].OGL.Header.RenderViewport.Size = recommendedTex0Size; EyeTexture[0].OGL.Header.RenderViewport.Pos.x = 0; EyeTexture[0].OGL.Header.RenderViewport.Pos.y = 0; EyeTexture[0].OGL.TexId = renderedTex; EyeTexture[1].OGL.Header.API = ovrRenderAPI_OpenGL; EyeTexture[1].OGL.Header.TextureSize = renderTargetSize; EyeTexture[1].OGL.Header.RenderViewport.Size = recommendedTex1Size; EyeTexture[1].OGL.Header.RenderViewport.Pos.x = recommendedTex0Size.w; EyeTexture[1].OGL.Header.RenderViewport.Pos.y = 0; EyeTexture[1].OGL.TexId = renderedTex; eyeTex[0] = EyeTexture[0].Texture; eyeTex[1] = EyeTexture[1].Texture; return 0; }
void RiftRenderingApp::initializeRiftRendering() { ovrGLConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.OGL.Header.API = ovrRenderAPI_OpenGL; cfg.OGL.Header.BackBufferSize = ovr::fromGlm(hmdNativeResolution); cfg.OGL.Header.Multisample = 1; ON_WINDOWS([&]{ cfg.OGL.Window = (HWND)getNativeWindow(); }); int distortionCaps = 0 | ovrDistortionCap_Vignette | ovrDistortionCap_Overdrive | ovrDistortionCap_TimeWarp; ON_LINUX([&]{ distortionCaps |= ovrDistortionCap_LinuxDevFullscreen; }); ovrEyeRenderDesc eyeRenderDescs[2]; int configResult = ovrHmd_ConfigureRendering(hmd, &cfg.Config, distortionCaps, hmd->MaxEyeFov, eyeRenderDescs); assert(configResult); for_each_eye([&](ovrEyeType eye){ const ovrEyeRenderDesc & erd = eyeRenderDescs[eye]; ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, 0.01f, 100000.0f, true); projections[eye] = ovr::toGlm(ovrPerspectiveProjection); eyeOffsets[eye] = erd.HmdToEyeViewOffset; }); // Allocate the frameBuffer that will hold the scene, and then be // re-rendered to the screen with distortion glm::uvec2 frameBufferSize = ovr::toGlm(eyeTextures[0].Header.TextureSize); for_each_eye([&](ovrEyeType eye) { eyeFramebuffers[eye] = FramebufferWrapperPtr(new FramebufferWrapper()); eyeFramebuffers[eye]->init(frameBufferSize); ((ovrGLTexture&)(eyeTextures[eye])).OGL.TexId = oglplus::GetName(eyeFramebuffers[eye]->color); }); }
void initGl() { RiftGlfwApp::initGl(); Resource * sceneImages = SCENE_IMAGES_DK2; if (hmd->Type == ovrHmd_DK1) { sceneImages = SCENE_IMAGES_DK1; } for_each_eye([&](ovrEyeType eye){ glm::uvec2 textureSize; sceneTextures[eye] = oria::load2dTexture(sceneImages[eye], textureSize); memset(eyeTextures + eye, 0, sizeof(eyeTextures[eye])); ovrTextureHeader & eyeTextureHeader = eyeTextures[eye].Header; eyeTextureHeader.TextureSize = ovr::fromGlm(textureSize); eyeTextureHeader.RenderViewport.Size = eyeTextureHeader.TextureSize; eyeTextureHeader.API = ovrRenderAPI_OpenGL; ((ovrGLTextureData&)eyeTextures[eye]).TexId = oglplus::GetName(*sceneTextures[eye]); }); ovrRenderAPIConfig config; memset(&config, 0, sizeof(config)); config.Header.API = ovrRenderAPI_OpenGL; config.Header.BackBufferSize = ovr::fromGlm(getSize()); config.Header.Multisample = 1; #if defined(OVR_OS_WIN32) ((ovrGLConfigData&)config).Window = 0; #elif defined(OVR_OS_LINUX) ((ovrGLConfigData&)config).Disp = 0; #endif int distortionCaps = ovrDistortionCap_Vignette; ovrEyeRenderDesc eyeRenderDescs[2]; int configResult = ovrHmd_ConfigureRendering(hmd, &config, distortionCaps, hmd->DefaultEyeFov, eyeRenderDescs); if (0 == configResult) { FAIL("Unable to configure rendering"); } }
// Active GL context is required for the following int RiftAppSkeleton::ConfigureSDKRendering() { if (m_Hmd == NULL) return 1; ovrSizei l_TextureSizeLeft = ovrHmd_GetFovTextureSize(m_Hmd, ovrEye_Left, m_Hmd->DefaultEyeFov[0], 1.0f); ovrSizei l_TextureSizeRight = ovrHmd_GetFovTextureSize(m_Hmd, ovrEye_Right, m_Hmd->DefaultEyeFov[1], 1.0f); ovrSizei l_TextureSize; l_TextureSize.w = l_TextureSizeLeft.w + l_TextureSizeRight.w; l_TextureSize.h = (l_TextureSizeLeft.h>l_TextureSizeRight.h ? l_TextureSizeLeft.h : l_TextureSizeRight.h); // Oculus Rift eye configurations... m_EyeFov[0] = m_Hmd->DefaultEyeFov[0]; m_EyeFov[1] = m_Hmd->DefaultEyeFov[1]; m_Cfg.OGL.Header.API = ovrRenderAPI_OpenGL; m_Cfg.OGL.Header.Multisample = 0; const int l_DistortionCaps = ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp; ovrHmd_ConfigureRendering(m_Hmd, &m_Cfg.Config, l_DistortionCaps, m_EyeFov, m_EyeRenderDesc); // Reset this state before rendering anything else or we get a black screen. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glUseProgram(0); l_EyeTexture[0].OGL.Header.API = ovrRenderAPI_OpenGL; l_EyeTexture[0].OGL.Header.TextureSize.w = l_TextureSize.w; l_EyeTexture[0].OGL.Header.TextureSize.h = l_TextureSize.h; l_EyeTexture[0].OGL.Header.RenderViewport.Pos.x = 0; l_EyeTexture[0].OGL.Header.RenderViewport.Pos.y = 0; l_EyeTexture[0].OGL.Header.RenderViewport.Size.w = l_TextureSize.w/2; l_EyeTexture[0].OGL.Header.RenderViewport.Size.h = l_TextureSize.h; l_EyeTexture[0].OGL.TexId = m_renderBuffer.tex; // Right eye the same, except for the x-position in the texture... l_EyeTexture[1] = l_EyeTexture[0]; l_EyeTexture[1].OGL.Header.RenderViewport.Pos.x = (l_TextureSize.w+1) / 2; return 0; }
void initGl() { RiftGlfwApp::initGl(); ovrGLConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.OGL.Header.API = ovrRenderAPI_OpenGL; cfg.OGL.Header.RTSize = Rift::toOvr(windowSize); cfg.OGL.Header.Multisample = 1; int distortionCaps = 0 | ovrDistortionCap_Vignette | ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp ; int configResult = ovrHmd_ConfigureRendering(hmd, &cfg.Config, distortionCaps, hmd->MaxEyeFov, eyeRenderDescs); #ifdef _DEBUG ovrhmd_EnableHSWDisplaySDKRender(hmd, false); #endif for_each_eye([&](ovrEyeType eye){ const ovrEyeRenderDesc & erd = eyeRenderDescs[eye]; ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, 0.01f, 100000.0f, true); projections[eye] = Rift::fromOvr(ovrPerspectiveProjection); }); /////////////////////////////////////////////////////////////////////////// // Initialize OpenGL settings and variables glEnable(GL_BLEND); ovrLock.lock(); renderWindow = glfwCreateWindow(100, 100, "Ofscreen", nullptr, window); threadPtr = std::unique_ptr<std::thread>(new std::thread(&SimpleScene::runOvrThread, this)); glfwMakeContextCurrent(window); }
virtual void initGl() { RiftGlfwApp::initGl(); ovrRenderAPIConfig cfg; memset(&cfg, 0, sizeof(cfg)); cfg.Header.API = ovrRenderAPI_OpenGL; cfg.Header.BackBufferSize = ovr::fromGlm(getSize()); cfg.Header.Multisample = 1; int distortionCaps = ovrDistortionCap_Vignette; ovrEyeRenderDesc eyeRenderDescs[2]; int configResult = ovrHmd_ConfigureRendering(hmd, &cfg, distortionCaps, hmd->DefaultEyeFov, eyeRenderDescs); for_each_eye([&](ovrEyeType eye){ PerEyeArg & eyeArgs = eyes[eye]; ovrFovPort fov = hmd->DefaultEyeFov[eye]; ovrSizei texSize = ovrHmd_GetFovTextureSize(hmd, eye, fov, 1.0f); eyeArgs.framebuffer = FramebufferWrapperPtr(new FramebufferWrapper()); eyeArgs.framebuffer->init(ovr::toGlm(texSize)); ovrTextureHeader & textureHeader = eyeTextures[eye].Header; textureHeader.API = ovrRenderAPI_OpenGL; textureHeader.TextureSize = texSize; textureHeader.RenderViewport.Size = texSize; textureHeader.RenderViewport.Pos.x = 0; textureHeader.RenderViewport.Pos.y = 0; ((ovrGLTextureData&)eyeTextures[eye]).TexId = oglplus::GetName(eyeArgs.framebuffer->color); eyeArgs.modelviewOffset = glm::translate(glm::mat4(), ovr::toGlm(eyeRenderDescs[eye].HmdToEyeViewOffset)); ovrMatrix4f projection = ovrMatrix4f_Projection(fov, 0.01f, 100, true); eyeArgs.projection = ovr::toGlm(projection); }); }
//------------------------------------------------------------------------------------- int Init() { // Initializes LibOVR, and the Rift ovr_Initialize(); HMD = ovrHmd_Create(0); if (!HMD) { MessageBoxA(NULL,"Oculus Rift not detected.","", MB_OK); return(1); } if (HMD->ProductName[0] == '\0') MessageBoxA(NULL,"Rift detected, display not enabled.","", MB_OK); //Setup Window and Graphics - use window frame if relying on Oculus driver const int backBufferMultisample = 1; bool UseAppWindowFrame = (HMD->HmdCaps & ovrHmdCap_ExtendDesktop) ? false : true; HWND window = Util_InitWindowAndGraphics(Recti(HMD->WindowsPos, HMD->Resolution), FullScreen, backBufferMultisample, UseAppWindowFrame,&pRender); if (!window) return 1; ovrHmd_AttachToWindow(HMD, window, NULL, NULL); //Configure Stereo settings. Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(HMD, ovrEye_Left, HMD->DefaultEyeFov[0], 1.0f); Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(HMD, ovrEye_Right, HMD->DefaultEyeFov[1], 1.0f); Sizei RenderTargetSize; RenderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w; RenderTargetSize.h = max ( recommenedTex0Size.h, recommenedTex1Size.h ); const int eyeRenderMultisample = 1; pRendertargetTexture = pRender->CreateTexture(Texture_RGBA | Texture_RenderTarget | eyeRenderMultisample, RenderTargetSize.w, RenderTargetSize.h, NULL); // The actual RT size may be different due to HW limits. RenderTargetSize.w = pRendertargetTexture->GetWidth(); RenderTargetSize.h = pRendertargetTexture->GetHeight(); // Initialize eye rendering information. // The viewport sizes are re-computed in case RenderTargetSize changed due to HW limitations. ovrFovPort eyeFov[2] = { HMD->DefaultEyeFov[0], HMD->DefaultEyeFov[1] } ; EyeRenderViewport[0].Pos = Vector2i(0,0); EyeRenderViewport[0].Size = Sizei(RenderTargetSize.w / 2, RenderTargetSize.h); EyeRenderViewport[1].Pos = Vector2i((RenderTargetSize.w + 1) / 2, 0); EyeRenderViewport[1].Size = EyeRenderViewport[0].Size; #if SDK_RENDER // Query D3D texture data. EyeTexture[0].D3D11.Header.API = ovrRenderAPI_D3D11; EyeTexture[0].D3D11.Header.TextureSize = RenderTargetSize; EyeTexture[0].D3D11.Header.RenderViewport = EyeRenderViewport[0]; EyeTexture[0].D3D11.pTexture = pRendertargetTexture->Tex.GetPtr(); EyeTexture[0].D3D11.pSRView = pRendertargetTexture->TexSv.GetPtr(); // Right eye uses the same texture, but different rendering viewport. EyeTexture[1] = EyeTexture[0]; EyeTexture[1].D3D11.Header.RenderViewport = EyeRenderViewport[1]; // Configure d3d11. ovrD3D11Config d3d11cfg; d3d11cfg.D3D11.Header.API = ovrRenderAPI_D3D11; d3d11cfg.D3D11.Header.RTSize = Sizei(HMD->Resolution.w, HMD->Resolution.h); d3d11cfg.D3D11.Header.Multisample = backBufferMultisample; d3d11cfg.D3D11.pDevice = pRender->Device; d3d11cfg.D3D11.pDeviceContext = pRender->Context; d3d11cfg.D3D11.pBackBufferRT = pRender->BackBufferRT; d3d11cfg.D3D11.pSwapChain = pRender->SwapChain; if (!ovrHmd_ConfigureRendering(HMD, &d3d11cfg.Config, ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive, eyeFov, EyeRenderDesc)) return(1); #else //Shader vertex format D3D11_INPUT_ELEMENT_DESC DistortionMeshVertexDesc[] = { {"Position", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"Position", 1, DXGI_FORMAT_R32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"Position", 2, DXGI_FORMAT_R32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TexCoord", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TexCoord", 2, DXGI_FORMAT_R32G32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0}}; //Distortion vertex shader const char* vertexShader = "float2 EyeToSourceUVScale, EyeToSourceUVOffset; \n" "float4x4 EyeRotationStart, EyeRotationEnd; \n" "float2 TimewarpTexCoord(float2 TexCoord, float4x4 rotMat) \n" "{ \n" // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic // aberration and distortion). These are now "real world" vectors in direction (x,y,1) // relative to the eye of the HMD. Apply the 3x3 timewarp rotation to these vectors. " float3 transformed = float3( mul ( rotMat, float4(TexCoord.xy, 1, 1) ).xyz); \n" // Project them back onto the Z=1 plane of the rendered images. " float2 flattened = (transformed.xy / transformed.z); \n" // Scale them into ([0,0.5],[0,1]) or ([0.5,0],[0,1]) UV lookup space (depending on eye) " return(EyeToSourceUVScale * flattened + EyeToSourceUVOffset); \n" "} \n" "void main(in float2 Position : POSITION, in float timewarpLerpFactor : POSITION1, \n" " in float Vignette : POSITION2, in float2 TexCoord0 : TEXCOORD0, \n" " in float2 TexCoord1 : TEXCOORD1, in float2 TexCoord2 : TEXCOORD2, \n" " out float4 oPosition : SV_Position, \n" " out float2 oTexCoord0 : TEXCOORD0, out float2 oTexCoord1 : TEXCOORD1, \n" " out float2 oTexCoord2 : TEXCOORD2, out float oVignette : TEXCOORD3) \n" "{ \n" " float4x4 lerpedEyeRot = lerp(EyeRotationStart, EyeRotationEnd, timewarpLerpFactor);\n" " oTexCoord0 = TimewarpTexCoord(TexCoord0,lerpedEyeRot); \n" " oTexCoord1 = TimewarpTexCoord(TexCoord1,lerpedEyeRot); \n" " oTexCoord2 = TimewarpTexCoord(TexCoord2,lerpedEyeRot); \n" " oPosition = float4(Position.xy, 0.5, 1.0); oVignette = Vignette; \n" "}"; //Distortion pixel shader const char* pixelShader = "Texture2D Texture : register(t0); \n" "SamplerState Linear : register(s0); \n" "float4 main(in float4 oPosition : SV_Position, in float2 oTexCoord0 : TEXCOORD0, \n" " in float2 oTexCoord1 : TEXCOORD1, in float2 oTexCoord2 : TEXCOORD2, \n" " in float oVignette : TEXCOORD3) : SV_Target \n" "{ \n" // 3 samples for fixing chromatic aberrations " float R = Texture.Sample(Linear, oTexCoord0.xy).r; \n" " float G = Texture.Sample(Linear, oTexCoord1.xy).g; \n" " float B = Texture.Sample(Linear, oTexCoord2.xy).b; \n" " return (oVignette*float4(R,G,B,1)); \n" "}"; pRender->InitShaders(vertexShader, pixelShader, &Shaders, &VertexIL,DistortionMeshVertexDesc,6); for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) { // Allocate mesh vertices, registering with renderer using the OVR vertex format. ovrDistortionMesh meshData; ovrHmd_CreateDistortionMesh(HMD, (ovrEyeType) eyeNum, eyeFov[eyeNum], ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp, &meshData); MeshVBs[eyeNum] = *pRender->CreateBuffer(); MeshVBs[eyeNum]->Data(Buffer_Vertex,meshData.pVertexData,sizeof(ovrDistortionVertex)*meshData.VertexCount); MeshIBs[eyeNum] = *pRender->CreateBuffer(); MeshIBs[eyeNum]->Data(Buffer_Index,meshData.pIndexData,sizeof(unsigned short) * meshData.IndexCount); ovrHmd_DestroyDistortionMesh( &meshData ); //Create eye render description for use later EyeRenderDesc[eyeNum] = ovrHmd_GetRenderDesc(HMD, (ovrEyeType) eyeNum, eyeFov[eyeNum]); //Do scale and offset ovrHmd_GetRenderScaleAndOffset(eyeFov[eyeNum],RenderTargetSize, EyeRenderViewport[eyeNum], UVScaleOffset[eyeNum]); } #endif ovrHmd_SetEnabledCaps(HMD, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); // Start the sensor which informs of the Rift's pose and motion ovrHmd_ConfigureTracking(HMD, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, 0); // This creates lights and models. pRoomScene = new Scene; sbuilder.PopulateRoomScene(pRoomScene, pRender); return (0); }
GMO double linkWindowHandle(void* windowHandle) { const int eyeRenderMultisample = 1; const int backBufferMultisample = 1; //HWND handle = GetWindow((HWND)(int)windowHandle, GW_OWNER); //HWND handle = (HWND) (int) windowHandle; HWND handle = (HWND) windowHandle; /* * This function returns the passed windows' title. Just to debug / test LPWSTR title; GetWindowText(handle, title, GetWindowTextLength(handle) + 1); MessageBox(NULL, (LPCWSTR)title, (LPCWSTR)title, MB_ICONWARNING); MessageBoxA(NULL, (LPCSTR)title, (LPCSTR)title, MB_ICONWARNING); */ hWnd = handle; ovrHmd_AttachToWindow(HMD, handle, NULL, NULL); Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(HMD, ovrEye_Left, HMD->DefaultEyeFov[0], 1.0f); Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(HMD, ovrEye_Right, HMD->DefaultEyeFov[1], 1.0f); Sizei RenderTargetSize; RenderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w; RenderTargetSize.h = max ( recommenedTex0Size.h, recommenedTex1Size.h ); bool UseAppWindowFrame = true;//(HMD->HmdCaps & ovrHmdCap_ExtendDesktop) ? false : true; HWND window = Util_InitWindowAndGraphics(Recti(HMD->WindowsPos, HMD->Resolution), FullScreen, backBufferMultisample, 1,&pRender, handle); pRendertargetTexture = pRender->CreateTexture(Texture_RGBA | Texture_RenderTarget | eyeRenderMultisample, RenderTargetSize.w, RenderTargetSize.h, NULL); // The actual RT size may be different due to HW limits. RenderTargetSize.w = pRendertargetTexture->GetWidth(); RenderTargetSize.h = pRendertargetTexture->GetHeight(); // Initialize eye rendering information. // The viewport sizes are re-computed in case RenderTargetSize changed due to HW limitations. ovrFovPort eyeFov[2] = { HMD->DefaultEyeFov[0], HMD->DefaultEyeFov[1] } ; EyeRenderViewport[0].Pos = Vector2i(0,0); EyeRenderViewport[0].Size = Sizei(RenderTargetSize.w / 2, RenderTargetSize.h); EyeRenderViewport[1].Pos = Vector2i((RenderTargetSize.w + 1) / 2, 0); EyeRenderViewport[1].Size = EyeRenderViewport[0].Size; EyeTexture[0].D3D11.Header.API = ovrRenderAPI_D3D11; EyeTexture[0].D3D11.Header.TextureSize = RenderTargetSize; EyeTexture[0].D3D11.Header.RenderViewport = EyeRenderViewport[0]; EyeTexture[0].D3D11.pTexture = pRendertargetTexture->Tex.GetPtr(); EyeTexture[0].D3D11.pSRView = pRendertargetTexture->TexSv.GetPtr(); // Right eye uses the same texture, but different rendering viewport. EyeTexture[1] = EyeTexture[0]; EyeTexture[1].D3D11.Header.RenderViewport = EyeRenderViewport[1]; // Configure d3d11. ovrD3D11Config d3d11cfg; d3d11cfg.D3D11.Header.API = ovrRenderAPI_D3D11; d3d11cfg.D3D11.Header.RTSize = Sizei(HMD->Resolution.w, HMD->Resolution.h); d3d11cfg.D3D11.Header.Multisample = backBufferMultisample; d3d11cfg.D3D11.pDevice = pRender->Device; d3d11cfg.D3D11.pDeviceContext = pRender->Context; d3d11cfg.D3D11.pBackBufferRT = pRender->BackBufferRT; d3d11cfg.D3D11.pSwapChain = pRender->SwapChain; if (!ovrHmd_ConfigureRendering(HMD, &d3d11cfg.Config, ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive, eyeFov, EyeRenderDesc)) return -2; // Some settings might be changed here lateron. ovrHmd_SetEnabledCaps(HMD, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction);// | ovrHmdCap_ExtendDesktop); // Start the sensor which informs of the Rift's pose and motion ovrHmd_ConfigureTracking(HMD, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, 0); return 1; }
bool OVR::postReset(void* _nwh, ovrRenderAPIConfig* _config, bool _debug) { if (_debug) { switch (_config->Header.API) { #if BGFX_CONFIG_RENDERER_DIRECT3D11 case ovrRenderAPI_D3D11: { ovrD3D11ConfigData* data = (ovrD3D11ConfigData*)_config; # if OVR_VERSION > OVR_VERSION_043 m_rtSize = data->Header.BackBufferSize; # else m_rtSize = data->Header.RTSize; # endif // OVR_VERSION > OVR_VERSION_043 } break; #endif // BGFX_CONFIG_RENDERER_DIRECT3D11 #if BGFX_CONFIG_RENDERER_OPENGL case ovrRenderAPI_OpenGL: { ovrGLConfigData* data = (ovrGLConfigData*)_config; # if OVR_VERSION > OVR_VERSION_043 m_rtSize = data->Header.BackBufferSize; # else m_rtSize = data->Header.RTSize; # endif // OVR_VERSION > OVR_VERSION_043 } break; #endif // BGFX_CONFIG_RENDERER_OPENGL case ovrRenderAPI_None: default: BX_CHECK(false, "You should not be here!"); break; } m_debug = true; return false; } if (!m_initialized) { return false; } if (!_debug) { m_hmd = ovrHmd_Create(0); } if (NULL == m_hmd) { m_hmd = ovrHmd_CreateDebug(ovrHmd_DK2); BX_WARN(NULL != m_hmd, "Unable to initialize OVR."); if (NULL == m_hmd) { return false; } } BX_TRACE("HMD: %s, %s, firmware: %d.%d" , m_hmd->ProductName , m_hmd->Manufacturer , m_hmd->FirmwareMajor , m_hmd->FirmwareMinor ); ovrBool result; result = ovrHmd_AttachToWindow(m_hmd, _nwh, NULL, NULL); if (!result) { goto ovrError; } ovrFovPort eyeFov[2] = { m_hmd->DefaultEyeFov[0], m_hmd->DefaultEyeFov[1] }; result = ovrHmd_ConfigureRendering(m_hmd , _config , 0 #if OVR_VERSION < OVR_VERSION_050 | ovrDistortionCap_Chromatic // permanently enabled >= v5.0 #endif | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive | ovrDistortionCap_NoRestore | ovrDistortionCap_HqDistortion , eyeFov , m_erd ); if (!result) { goto ovrError; } ovrHmd_SetEnabledCaps(m_hmd , 0 | ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction ); result = ovrHmd_ConfigureTracking(m_hmd , 0 | ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position , 0 ); if (!result) { ovrError: BX_TRACE("Failed to initialize OVR."); ovrHmd_Destroy(m_hmd); m_hmd = NULL; return false; } ovrSizei sizeL = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left, m_hmd->DefaultEyeFov[0], 1.0f); ovrSizei sizeR = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right, m_hmd->DefaultEyeFov[1], 1.0f); m_rtSize.w = sizeL.w + sizeR.w; m_rtSize.h = bx::uint32_max(sizeL.h, sizeR.h); m_warning = true; return true; }
void Renderer::initOVR() { ovr_Initialize(); Config& config = Core::get().config(); if(!config.getBool("Renderer.OVR", false)) { return; } hmd_ = ovrHmd_Create(0); if(!hmd_) { fprintf(stderr, "Failed to create OVR HMD, falling back to fake one\n"); hmd_ = ovrHmd_CreateDebug(ovrHmd_DK2); } ovrSizei leftEyeTexSize = ovrHmd_GetFovTextureSize(hmd_, ovrEye_Left, hmd_->DefaultEyeFov[ovrEye_Left], 1.0f); ovrSizei rightEyeTexSize = ovrHmd_GetFovTextureSize(hmd_, ovrEye_Right, hmd_->DefaultEyeFov[ovrEye_Right], 1.0f); renderTexSize_.w = leftEyeTexSize.w + rightEyeTexSize.w; renderTexSize_.h = max(leftEyeTexSize.h, rightEyeTexSize.h); glGenTextures(1, &renderTex_); glBindTexture(GL_TEXTURE_2D, renderTex_); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, renderTexSize_.w, renderTexSize_.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &renderTexSize_.w); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &renderTexSize_.h); glGenTextures(1, &depthTex_); glBindTexture(GL_TEXTURE_2D, depthTex_); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, renderTexSize_.w, renderTexSize_.h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, nullptr); eyeViewport_[ovrEye_Left].Pos.x = 0; eyeViewport_[ovrEye_Left].Pos.y = 0; eyeViewport_[ovrEye_Left].Size.w = renderTexSize_.w / 2; eyeViewport_[ovrEye_Left].Size.h = renderTexSize_.h; eyeViewport_[ovrEye_Right].Pos.x = renderTexSize_.w / 2; eyeViewport_[ovrEye_Right].Pos.y = 0; eyeViewport_[ovrEye_Right].Size.w = renderTexSize_.w / 2; eyeViewport_[ovrEye_Right].Size.h = renderTexSize_.h; eyeTexture_[ovrEye_Left].OGL.Header.API = ovrRenderAPI_OpenGL; eyeTexture_[ovrEye_Left].OGL.Header.TextureSize = renderTexSize_; eyeTexture_[ovrEye_Left].OGL.Header.RenderViewport = eyeViewport_[ovrEye_Left]; eyeTexture_[ovrEye_Left].OGL.TexId = renderTex_; eyeTexture_[ovrEye_Right].OGL.Header.API = ovrRenderAPI_OpenGL; eyeTexture_[ovrEye_Right].OGL.Header.TextureSize = renderTexSize_; eyeTexture_[ovrEye_Right].OGL.Header.RenderViewport = eyeViewport_[ovrEye_Right]; eyeTexture_[ovrEye_Right].OGL.TexId = renderTex_; ovrSizei targetSize; SDL_GetWindowSize(window_, &targetSize.w, &targetSize.h); SDL_SysWMinfo wmInfo; SDL_VERSION(&wmInfo.version); if(!SDL_GetWindowWMInfo(window_, &wmInfo)) { throw runtime_error("Failed to get window info"); } ovrGLConfig cfg; cfg.OGL.Header.API = ovrRenderAPI_OpenGL; cfg.OGL.Header.RTSize = targetSize; cfg.OGL.Header.Multisample = 1; // yes? #if defined(OVR_OS_WIN32) cfg.OGL.Window = wmInfo.info.win.window; cfg.OGL.DC = GetDC(wmInfo.info.win.window); #elif defined(OVR_OS_MAC) // Mac does not have any fields #else #error Implement for this OS. #endif unsigned int distortionCaps = ovrDistortionCap_Chromatic|ovrDistortionCap_TimeWarp|ovrDistortionCap_Overdrive; if(!ovrHmd_ConfigureRendering(hmd_, &cfg.Config, distortionCaps, hmd_->DefaultEyeFov, eyeRenderDesc_)) { throw runtime_error("Failed to configure HMD rendering"); } #ifdef OVR_OS_WIN32 if(!ovrHmd_AttachToWindow(hmd_, wmInfo.info.win.window, nullptr, nullptr)) { throw runtime_error("Failed to attach HMD to window"); } #endif glGenFramebuffers(1, &framebuffer_); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTex_, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTex_, 0); if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { throw runtime_error("Framebuffer not complete"); } glBindFramebuffer(GL_FRAMEBUFFER, 0); unsigned int trackingCaps = ovrTrackingCap_Orientation|ovrTrackingCap_Position; if(!ovrHmd_ConfigureTracking(hmd_, trackingCaps, 0)) { throw runtime_error("Failed to configure HMD tracking"); } // warning will disappear as soon as the timeout expires ovrHmd_DismissHSWDisplay(hmd_); }
CoinRiftWidget::CoinRiftWidget() : QGLWidget() { for (int eye = 0; eye < 2; eye++) { reinterpret_cast<ovrGLTextureData*>(&eyeTexture[eye])->TexId = 0; #ifdef USE_FRAMEBUFFER frameBufferID[eye] = 0; depthBufferID[eye] = 0; #endif } // OVR will do the swapping. setAutoBufferSwap(false); hmd = ovrHmd_Create(0); if (!hmd) { qDebug() << "Could not find Rift device."; throw; } if (!ovrHmd_ConfigureTracking (hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position )) { // Capabilities we require. qDebug() << "Could not start Rift motion sensor."; throw; } resize(hmd->Resolution.w, hmd->Resolution.h); // Configure stereo settings. ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, hmd->DefaultEyeFov[0], 1.0f); ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, hmd->DefaultEyeFov[1], 1.0f); #ifdef USE_SO_OFFSCREEN_RENDERER renderer = new SoOffscreenRenderer(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), std::max(recommenedTex1Size.h, recommenedTex1Size.h))); renderer->setComponents(SoOffscreenRenderer::RGB_TRANSPARENCY); BackgroundColor = SbColor(.0f, .0f, .8f); renderer->setBackgroundColor(BackgroundColor); #endif #ifdef USE_FRAMEBUFFER m_sceneManager = new SoSceneManager(); m_sceneManager->setViewportRegion(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w), std::max(recommenedTex1Size.h, recommenedTex1Size.h))); m_sceneManager->setBackgroundColor(SbColor(.0f, .0f, .8f)); #endif basePosition = SbVec3f(0.0f, 0.0f, -2.0f); // light handling SoDirectionalLight *light = new SoDirectionalLight(); light->direction.setValue(1,-1,-1); SoDirectionalLight *light2 = new SoDirectionalLight(); light2->direction.setValue(-1,-1,-1); light2->intensity.setValue(0.6); light2->color.setValue(0.8,0.8,1); scene = new SoSeparator(0); // Placeholder. for (int eye = 0; eye < 2; eye++) { rootScene[eye] = new SoSeparator(); rootScene[eye]->ref(); camera[eye] = new SoFrustumCamera(); camera[eye]->position.setValue(basePosition); camera[eye]->focalDistance.setValue(5.0f); camera[eye]->viewportMapping.setValue(SoCamera::LEAVE_ALONE); rootScene[eye]->addChild(camera[eye]); rootScene[eye]->addChild(light); rootScene[eye]->addChild(light2); rootScene[eye]->addChild(scene); } // Populate ovrEyeDesc[2]. eyeRenderDesc[0].Eye = ovrEye_Left; eyeRenderDesc[1].Eye = ovrEye_Right; eyeRenderDesc[0].Fov = hmd->DefaultEyeFov[0]; eyeRenderDesc[1].Fov = hmd->DefaultEyeFov[1]; #ifdef USE_SO_OFFSCREEN_RENDERER eyeTexture[0].Header.TextureSize.w = renderer->getViewportRegion().getViewportSizePixels().getValue()[0]; eyeTexture[0].Header.TextureSize.h = renderer->getViewportRegion().getViewportSizePixels().getValue()[1]; eyeTexture[1].Header.TextureSize = eyeTexture[0].Header.TextureSize; #endif #ifdef USE_FRAMEBUFFER eyeTexture[0].Header.TextureSize = recommenedTex0Size; eyeTexture[1].Header.TextureSize = recommenedTex1Size; #endif eyeTexture[0].Header.RenderViewport.Pos.x = 0; eyeTexture[0].Header.RenderViewport.Pos.y = 0; eyeTexture[0].Header.RenderViewport.Size = eyeTexture[0].Header.TextureSize; eyeTexture[1].Header.RenderViewport.Pos = eyeTexture[0].Header.RenderViewport.Pos; eyeTexture[1].Header.RenderViewport.Size = eyeTexture[1].Header.TextureSize; const int backBufferMultisample = 0; // TODO This is a guess? ovrGLConfig cfg; cfg.OGL.Header.API = ovrRenderAPI_OpenGL; cfg.OGL.Header.RTSize = hmd->Resolution; cfg.OGL.Header.Multisample = backBufferMultisample; cfg.OGL.Window = reinterpret_cast<HWND>(winId()); makeCurrent(); //cfg.OGL.WglContext = wglGetCurrentContext(); // http://stackoverflow.com/questions/17532033/qglwidget-get-gl-contextes-for-windows cfg.OGL.DC = wglGetCurrentDC(); qDebug() << "Window:" << cfg.OGL.Window; //qDebug() << "Context:" << cfg.OGL.WglContext; qDebug() << "DC:" << cfg.OGL.DC; int DistortionCaps = 0; DistortionCaps |= ovrDistortionCap_Chromatic; // DistortionCaps |= ovrDistortionCap_TimeWarp; // Produces black screen... DistortionCaps |= ovrDistortionCap_Vignette; DistortionCaps |= ovrDistortionCap_HqDistortion; bool VSyncEnabled(false); // TODO This is a guess. if (!ovrHmd_ConfigureRendering( hmd, &cfg.Config, /*(VSyncEnabled ? 0 : ovrHmdCap_NoVSync),*/ DistortionCaps, hmd->DefaultEyeFov,//eyes, eyeRenderDesc)) { qDebug() << "Could not configure OVR rendering."; throw; } static const float nearPlane = 0.01; for (int eye = 0; eye < 2; eye++) { camera[eye]->aspectRatio.setValue((eyeRenderDesc[eye].Fov.LeftTan + eyeRenderDesc[eye].Fov.RightTan) / (eyeRenderDesc[eye].Fov.UpTan + eyeRenderDesc[eye].Fov.DownTan)); camera[eye]->nearDistance.setValue(nearPlane); camera[eye]->farDistance.setValue(10000.0f); camera[eye]->left.setValue(-eyeRenderDesc[eye].Fov.LeftTan * nearPlane); camera[eye]->right.setValue(eyeRenderDesc[eye].Fov.RightTan * nearPlane); camera[eye]->top.setValue(eyeRenderDesc[eye].Fov.UpTan * nearPlane); camera[eye]->bottom.setValue(-eyeRenderDesc[eye].Fov.DownTan * nearPlane); } }
void OcculusCameraComponent::init() { ovr_Initialize(); parent->getStage()->getGame()->getGraphicsHandle()->setAutoBufferSwap( false ); hmd = ovrHmd_Create(0); if (hmd) { ovrSizei resolution = hmd->Resolution; resolution; } else { hmd = ovrHmd_CreateDebug( ovrHmdType::ovrHmd_DK2 ); } // Start the sensor which provides the Rift’s pose and motion. //ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); ovrHmd_ConfigureTracking(hmd, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, 0); ovrHmd_RecenterPose( hmd ); ovrFovPort eyeFov[2] = { hmd->DefaultEyeFov[0], hmd->DefaultEyeFov[1] } ; ovrGLConfig oglConfig; oglConfig.OGL.Header.API = ovrRenderAPI_OpenGL; oglConfig.OGL.Header.RTSize = OVR::Sizei(hmd->Resolution.w, hmd->Resolution.h); oglConfig.OGL.Header.Multisample = 1; oglConfig.OGL.Window = parent->getStage()->getGame()->getGraphicsHandle()->getHandle(); oglConfig.OGL.DC = parent->getStage()->getGame()->getGraphicsHandle()->getHDC(); #pragma comment(lib,"libovrd.lib") ovrBool result = ovrHmd_ConfigureRendering( hmd, &oglConfig.Config, ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive, eyeFov, EyeRenderDesc); result; ovrHmd_AttachToWindow(hmd, oglConfig.OGL.Window, NULL, NULL); //Sets up FBOS // Configure Stereo settings. OVR::Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, hmd->DefaultEyeFov[0], 1.0f); OVR::Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, hmd->DefaultEyeFov[1], 1.0f); OVR::Sizei renderTargetSize; renderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w; renderTargetSize.h = max ( recommenedTex0Size.h, recommenedTex1Size.h ); renderTarget = FrameBufferObject::createFrameBuffer( renderTargetSize.w, renderTargetSize.h ); //Set up viewports EyeRenderViewport[0].Pos = OVR::Vector2i(0,0); EyeRenderViewport[0].Size = OVR::Sizei(renderTarget->width / 2, renderTarget->height); EyeRenderViewport[1].Pos = OVR::Vector2i((renderTarget->width + 1) / 2, 0); EyeRenderViewport[1].Size = EyeRenderViewport[0].Size; EyeTexture[0].OGL.Header.API = ovrRenderAPI_OpenGL; EyeTexture[0].OGL.Header.TextureSize = renderTargetSize; EyeTexture[0].OGL.Header.RenderViewport = EyeRenderViewport[0]; EyeTexture[0].OGL.TexId = renderTarget->colorTexture->textureID; EyeTexture[1].OGL.Header.API = ovrRenderAPI_OpenGL; EyeTexture[1].OGL.Header.TextureSize = renderTargetSize; EyeTexture[1].OGL.Header.RenderViewport = EyeRenderViewport[1]; EyeTexture[1].OGL.TexId = renderTarget->colorTexture->textureID; }
/** Initialize the Oculus HMD. * * @param pos The position that we want the Oculus HMD to start at. */ static void viewmat_init_hmd_oculus(const float pos[3]) { #ifdef MISSING_OVR msg(MSG_FATAL, "Oculus support is missing: You have not compiled this code against the LibOVR library.\n"); exit(EXIT_FAILURE); #else ovr_Initialize(NULL); int useDebugMode = 0; hmd = ovrHmd_Create(0); if(!hmd) { msg(MSG_WARNING, "Failed to open Oculus HMD. Is ovrd running? Is libOVRRT*.so.* in /usr/lib, /usr/local/lib, or the current directory?\n"); msg(MSG_WARNING, "Press any key to proceed with Oculus debugging window.\n"); char c; if(fscanf(stdin, "%c", &c) < 0) { msg(MSG_ERROR, "fscanf error.\n"); exit(EXIT_FAILURE); } hmd = ovrHmd_CreateDebug(ovrHmd_DK2); useDebugMode = 1; if(!hmd) { msg(MSG_ERROR, "Oculus: Failed to create virtual debugging HMD\n"); exit(EXIT_FAILURE); } } msg(MSG_INFO, "Initialized HMD: %s - %s\n", hmd->Manufacturer, hmd->ProductName); #if 0 printf("default fov tangents left eye:\n"); printf("up=%f\n", hmd->DefaultEyeFov[ovrEye_Left].UpTan); printf("up=%f\n", hmd->DefaultEyeFov[ovrEye_Left].DownTan); printf("up=%f\n", hmd->DefaultEyeFov[ovrEye_Left].LeftTan); printf("up=%f\n", hmd->DefaultEyeFov[ovrEye_Left].RightTan); #endif /* pixelDensity can range between 0 to 1 (where 1 has the highest * resolution). Using smaller values will result in smaller * textures that each eye is rendered into. */ float pixelDensity = 1; /* Number of multisample antialiasing while rendering the scene * for each eye. */ GLint msaa_samples = 2; recommendTexSizeL = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, hmd->DefaultEyeFov[ovrEye_Left], pixelDensity); recommendTexSizeR = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, hmd->DefaultEyeFov[ovrEye_Right], pixelDensity); GLuint leftTextureAA,rightTextureAA; leftFramebufferAA = kuhl_gen_framebuffer_msaa(recommendTexSizeL.w, recommendTexSizeL.h, &leftTextureAA, NULL, msaa_samples); rightFramebufferAA = kuhl_gen_framebuffer_msaa(recommendTexSizeR.w, recommendTexSizeR.h, &rightTextureAA, NULL, msaa_samples); GLuint leftTexture,rightTexture; leftFramebuffer = kuhl_gen_framebuffer(recommendTexSizeL.w, recommendTexSizeL.h, &leftTexture, NULL); rightFramebuffer = kuhl_gen_framebuffer(recommendTexSizeR.w, recommendTexSizeR.h, &rightTexture, NULL); //printf("Left recommended texture size: %d %d\n", recommendTexSizeL.w, recommendTexSizeL.h); //printf("Right recommended texture size: %d %d\n", recommendTexSizeR.w, recommendTexSizeR.h); EyeTexture[0].OGL.Header.API = ovrRenderAPI_OpenGL; EyeTexture[0].OGL.Header.TextureSize.w = recommendTexSizeL.w; EyeTexture[0].OGL.Header.TextureSize.h = recommendTexSizeL.h; EyeTexture[0].OGL.Header.RenderViewport.Pos.x = 0; EyeTexture[0].OGL.Header.RenderViewport.Pos.y = 0; EyeTexture[0].OGL.Header.RenderViewport.Size.w = recommendTexSizeL.w; EyeTexture[0].OGL.Header.RenderViewport.Size.h = recommendTexSizeL.h; EyeTexture[1].OGL.Header.API = ovrRenderAPI_OpenGL; EyeTexture[1].OGL.Header.TextureSize.w = recommendTexSizeR.w; EyeTexture[1].OGL.Header.TextureSize.h = recommendTexSizeR.h; EyeTexture[1].OGL.Header.RenderViewport.Pos.x = 0; EyeTexture[1].OGL.Header.RenderViewport.Pos.y = 0; EyeTexture[1].OGL.Header.RenderViewport.Size.w = recommendTexSizeR.w; EyeTexture[1].OGL.Header.RenderViewport.Size.h = recommendTexSizeR.h; EyeTexture[0].OGL.TexId = leftTexture; EyeTexture[1].OGL.TexId = rightTexture; union ovrGLConfig glcfg; memset(&glcfg, 0, sizeof(glcfg)); glcfg.OGL.Header.API=ovrRenderAPI_OpenGL; glcfg.OGL.Header.Multisample = 0; glcfg.OGL.Disp = glXGetCurrentDisplay(); if(hmd->Type == ovrHmd_DK2 && useDebugMode == 0) { /* Since the DK2 monitor is rotated, we need to swap the width * and height here so that the final image correctly fills the * entire screen. */ glcfg.OGL.Header.BackBufferSize.h=hmd->Resolution.w; glcfg.OGL.Header.BackBufferSize.w=hmd->Resolution.h; } else { glcfg.OGL.Header.BackBufferSize.h=hmd->Resolution.h; glcfg.OGL.Header.BackBufferSize.w=hmd->Resolution.w; } // interferes with PROJAT_FULLSCREEN // glutReshapeWindow(glcfg.OGL.Header.BackBufferSize.w, // glcfg.OGL.Header.BackBufferSize.h); unsigned int trackingcap = 0; trackingcap |= ovrTrackingCap_Orientation; // orientation tracking trackingcap |= ovrTrackingCap_Position; // position tracking trackingcap |= ovrTrackingCap_MagYawCorrection; // use magnetic compass ovrHmd_ConfigureTracking(hmd, trackingcap, 0); unsigned int hmd_caps = 0; hmd_caps |= ovrHmdCap_DynamicPrediction; // enable internal latency feedback /* disable vsync; allow frame rate higher than display refresh rate, can cause tearing. On some windowing systems, you using this setting reduces issues with overrunning the time budget and tearing still does not occur. */ hmd_caps |= ovrHmdCap_NoVSync; hmd_caps |= ovrHmdCap_LowPersistence; // Less blur during rotation; dimmer screen ovrHmd_SetEnabledCaps(hmd, hmd_caps); /* Distortion options * See OVR_CAPI.h for additional options */ unsigned int distort_caps = 0; distort_caps |= ovrDistortionCap_LinuxDevFullscreen; // Screen rotation for DK2 // distort_caps |= ovrDistortionCap_Chromatic; // Chromatic aberration correction - Necessary for 0.4.4, turned on permanently in 0.5.0.1 distort_caps |= ovrDistortionCap_Vignette; // Apply gradient to edge of image // distort_caps |= ovrDistortionCap_OverDrive; // Overdrive brightness transitions to compensate for DK2 artifacts /* Shift image based on time difference between * ovrHmd_GetEyePose() and ovrHmd_EndFrame(). This option seems to * reduce FPS on at least one machine. */ //distort_caps |= ovrDistortionCap_TimeWarp; if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, distort_caps, hmd->DefaultEyeFov, eye_rdesc)) { msg(MSG_FATAL, "Failed to configure distortion renderer.\n"); exit(EXIT_FAILURE); } /* disable health and safety warning */ ovrHmd_DismissHSWDisplay(hmd); vec3f_copy(oculus_initialPos, pos); // Try to connect to VRPN viewmat_init_vrpn(); // TODO: We are supposed to do these things when we are done: //ovrHmd_Destroy(hmd); //ovr_Shutdown(); #endif }
int OVRConfigureRenderer(int width, int height, float znear, float zfar, float ipd, float multisample, int lowpersistence, int dynamicprediction, int vsync, int chromatic, int timewarp, int vignette, int state, int flip, int srgb, int overdrive, int profile) { unsigned hmdCaps; unsigned int distortionCaps; ovrFovPort eyeFov[EYE_ALL] = { _OVRGlobals.HMD->DefaultEyeFov[EYE_LEFT], _OVRGlobals.HMD->DefaultEyeFov[EYE_RIGHT] }; float FovSideTanMax = OVR::FovPort::Max(_OVRGlobals.HMD->DefaultEyeFov[EYE_LEFT], _OVRGlobals.HMD->DefaultEyeFov[EYE_RIGHT]).GetMaxSideTan(); //float FovSideTanLimit = OVR::FovPort::Max(_OVRGlobals.HMD->MaxEyeFov[EYE_LEFT], _OVRGlobals.HMD->MaxEyeFov[EYE_RIGHT]).GetMaxSideTan(); ovrBool didSetIPD = 0; // generate the HMD and distortion caps hmdCaps = (lowpersistence ? ovrHmdCap_LowPersistence : 0) | (dynamicprediction ? ovrHmdCap_DynamicPrediction : 0) | (vsync ? 0 : ovrHmdCap_NoVSync); distortionCaps = (chromatic ? ovrDistortionCap_Chromatic : 0) | (timewarp ? ovrDistortionCap_TimeWarp : 0) | (vignette ? ovrDistortionCap_Vignette : 0) | (state ? 0 : ovrDistortionCap_NoRestore) | (flip ? ovrDistortionCap_FlipInput : 0) | (srgb ? ovrDistortionCap_SRGB : 0) | (overdrive ? ovrDistortionCap_Overdrive : 0) | (profile ? ovrDistortionCap_ProfileNoTimewarpSpinWaits : 0); didSetIPD = ovrHmd_SetFloat( _OVRGlobals.HMD, OVR_KEY_IPD, ipd * 0.001 ); ovrHmd_SetEnabledCaps( _OVRGlobals.HMD, hmdCaps ); ovrRenderAPIConfig config = ovrRenderAPIConfig(); config.Header.API = ovrRenderAPI_OpenGL; config.Header.RTSize.w = width; config.Header.RTSize.h = height; config.Header.Multisample = multisample > 1 ? 1 : 0; // clamp fov eyeFov[EYE_LEFT] = OVR::FovPort::Min(eyeFov[EYE_LEFT], OVR::FovPort(FovSideTanMax)); eyeFov[EYE_RIGHT] = OVR::FovPort::Min(eyeFov[EYE_RIGHT], OVR::FovPort(FovSideTanMax)); if ( !ovrHmd_ConfigureRendering( _OVRGlobals.HMD, &config, distortionCaps, eyeFov, _OVRGlobals.EyeRenderDesc ) ) { return 0; } #ifdef DEBUG ovrhmd_EnableHSWDisplaySDKRender( _OVRGlobals.HMD, false ); #else ovrHmd_DismissHSWDisplay( _OVRGlobals.HMD ); #endif _OVRGlobals.IPD = ovrHmd_GetFloat( _OVRGlobals.HMD, OVR_KEY_IPD, ipd * 0.001 ); // create the projection _OVRGlobals.Eye[EYE_LEFT].Projection = ovrMatrix4f_Projection( _OVRGlobals.EyeRenderDesc[EYE_LEFT].Fov, znear, zfar, true ); _OVRGlobals.Eye[EYE_RIGHT].Projection = ovrMatrix4f_Projection( _OVRGlobals.EyeRenderDesc[EYE_RIGHT].Fov, znear, zfar, true ); // transpose the projection OVR::Matrix4 <float>transposeLeft = _OVRGlobals.Eye[EYE_LEFT].Projection; OVR::Matrix4 <float>transposeRight = _OVRGlobals.Eye[EYE_RIGHT].Projection; _OVRGlobals.Eye[EYE_LEFT].Projection = transposeLeft.Transposed(); _OVRGlobals.Eye[EYE_RIGHT].Projection = transposeRight.Transposed(); // TODO: ortho { float orthoDistance = 0.8f; // 2D is 0.8 meter from camera OVR::Vector2f orthoScale0 = OVR::Vector2f(1.0f) / OVR::Vector2f(_OVRGlobals.EyeRenderDesc[EYE_LEFT].PixelsPerTanAngleAtCenter); OVR::Vector2f orthoScale1 = OVR::Vector2f(1.0f) / OVR::Vector2f(_OVRGlobals.EyeRenderDesc[EYE_RIGHT].PixelsPerTanAngleAtCenter); _OVRGlobals.Eye[EYE_LEFT].OrthoProjection = ovrMatrix4f_OrthoSubProjection(_OVRGlobals.Eye[EYE_LEFT].Projection, orthoScale0, orthoDistance, _OVRGlobals.EyeRenderDesc[EYE_LEFT].ViewAdjust.x); _OVRGlobals.Eye[EYE_RIGHT].OrthoProjection = ovrMatrix4f_OrthoSubProjection(_OVRGlobals.Eye[EYE_RIGHT].Projection, orthoScale1, orthoDistance, _OVRGlobals.EyeRenderDesc[EYE_RIGHT].ViewAdjust.x); OVR::Matrix4 <float>transposeLeftOrtho = _OVRGlobals.Eye[EYE_LEFT].OrthoProjection; OVR::Matrix4 <float>transposeRightOrtho = _OVRGlobals.Eye[EYE_RIGHT].OrthoProjection; _OVRGlobals.Eye[EYE_LEFT].OrthoProjection = transposeLeftOrtho.Transposed(); _OVRGlobals.Eye[EYE_RIGHT].OrthoProjection = transposeRightOrtho.Transposed(); } return 1; }
void OculusWorldDemoApp::CalculateHmdValues() { // Initialize eye rendering information for ovrHmd_Configure. // The viewport sizes are re-computed in case RenderTargetSize changed due to HW limitations. ovrFovPort eyeFov[2]; eyeFov[0] = HmdDesc.DefaultEyeFov[0]; eyeFov[1] = HmdDesc.DefaultEyeFov[1]; // Clamp Fov based on our dynamically adjustable FovSideTanMax. // Most apps should use the default, but reducing Fov does reduce rendering cost. eyeFov[0] = FovPort::Min(eyeFov[0], FovPort(FovSideTanMax)); eyeFov[1] = FovPort::Min(eyeFov[1], FovPort(FovSideTanMax)); if (ForceZeroIpd) { // ForceZeroIpd does three things: // 1) Sets FOV to maximum symmetrical FOV based on both eyes // 2) Sets eye ViewAdjust values to 0.0 (effective IPD == 0) // 3) Uses only the Left texture for rendering. eyeFov[0] = FovPort::Max(eyeFov[0], eyeFov[1]); eyeFov[1] = eyeFov[0]; Sizei recommenedTexSize = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Left, eyeFov[0], DesiredPixelDensity); Sizei textureSize = EnsureRendertargetAtLeastThisBig(Rendertarget_Left, recommenedTexSize); EyeRenderSize[0] = Sizei::Min(textureSize, recommenedTexSize); EyeRenderSize[1] = EyeRenderSize[0]; // Store texture pointers that will be passed for rendering. EyeTexture[0] = RenderTargets[Rendertarget_Left].Tex; EyeTexture[0].Header.TextureSize = textureSize; EyeTexture[0].Header.RenderViewport = Recti(EyeRenderSize[0]); // Right eye is the same. EyeTexture[1] = EyeTexture[0]; } else { // Configure Stereo settings. Default pixel density is 1.0f. Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Left, eyeFov[0], DesiredPixelDensity); Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(Hmd, ovrEye_Right, eyeFov[1], DesiredPixelDensity); if (RendertargetIsSharedByBothEyes) { Sizei rtSize(recommenedTex0Size.w + recommenedTex1Size.w, Alg::Max(recommenedTex0Size.h, recommenedTex1Size.h)); // Use returned size as the actual RT size may be different due to HW limits. rtSize = EnsureRendertargetAtLeastThisBig(Rendertarget_BothEyes, rtSize); // Don't draw more then recommended size; this also ensures that resolution reported // in the overlay HUD size is updated correctly for FOV/pixel density change. EyeRenderSize[0] = Sizei::Min(Sizei(rtSize.w/2, rtSize.h), recommenedTex0Size); EyeRenderSize[1] = Sizei::Min(Sizei(rtSize.w/2, rtSize.h), recommenedTex1Size); // Store texture pointers that will be passed for rendering. // Same texture is used, but with different viewports. EyeTexture[0] = RenderTargets[Rendertarget_BothEyes].Tex; EyeTexture[0].Header.TextureSize = rtSize; EyeTexture[0].Header.RenderViewport = Recti(Vector2i(0), EyeRenderSize[0]); EyeTexture[1] = RenderTargets[Rendertarget_BothEyes].Tex; EyeTexture[1].Header.TextureSize = rtSize; EyeTexture[1].Header.RenderViewport = Recti(Vector2i((rtSize.w+1)/2, 0), EyeRenderSize[1]); } else { Sizei tex0Size = EnsureRendertargetAtLeastThisBig(Rendertarget_Left, recommenedTex0Size); Sizei tex1Size = EnsureRendertargetAtLeastThisBig(Rendertarget_Right, recommenedTex1Size); EyeRenderSize[0] = Sizei::Min(tex0Size, recommenedTex0Size); EyeRenderSize[1] = Sizei::Min(tex1Size, recommenedTex1Size); // Store texture pointers and viewports that will be passed for rendering. EyeTexture[0] = RenderTargets[Rendertarget_Left].Tex; EyeTexture[0].Header.TextureSize = tex0Size; EyeTexture[0].Header.RenderViewport = Recti(EyeRenderSize[0]); EyeTexture[1] = RenderTargets[Rendertarget_Right].Tex; EyeTexture[1].Header.TextureSize = tex1Size; EyeTexture[1].Header.RenderViewport = Recti(EyeRenderSize[1]); } } // Hmd caps. unsigned hmdCaps = (VsyncEnabled ? 0 : ovrHmdCap_NoVSync) | ovrHmdCap_LatencyTest; if (IsLowPersistence) hmdCaps |= ovrHmdCap_LowPersistence; if (DynamicPrediction) hmdCaps |= ovrHmdCap_DynamicPrediction; ovrHmd_SetEnabledCaps(Hmd, hmdCaps); ovrRenderAPIConfig config = pRender->Get_ovrRenderAPIConfig(); unsigned distortionCaps = ovrDistortionCap_Chromatic; if (TimewarpEnabled) distortionCaps |= ovrDistortionCap_TimeWarp; if (!ovrHmd_ConfigureRendering( Hmd, &config, distortionCaps, eyeFov, EyeRenderDesc )) { // Fail exit? TBD return; } if (ForceZeroIpd) { // Remove IPD adjust EyeRenderDesc[0].ViewAdjust = Vector3f(0); EyeRenderDesc[1].ViewAdjust = Vector3f(0); } // ovrHmdCap_LatencyTest - enables internal latency feedback unsigned sensorCaps = ovrSensorCap_Orientation|ovrSensorCap_YawCorrection; if (PositionTrackingEnabled) sensorCaps |= ovrSensorCap_Position; if (StartSensorCaps != sensorCaps) { ovrHmd_StartSensor(Hmd, sensorCaps, 0); StartSensorCaps = sensorCaps; } // Calculate projections Projection[0] = ovrMatrix4f_Projection(EyeRenderDesc[0].Fov, 0.01f, 10000.0f, true); Projection[1] = ovrMatrix4f_Projection(EyeRenderDesc[1].Fov, 0.01f, 10000.0f, true); float orthoDistance = 0.8f; // 2D is 0.8 meter from camera Vector2f orthoScale0 = Vector2f(1.0f) / Vector2f(EyeRenderDesc[0].PixelsPerTanAngleAtCenter); Vector2f orthoScale1 = Vector2f(1.0f) / Vector2f(EyeRenderDesc[1].PixelsPerTanAngleAtCenter); OrthoProjection[0] = ovrMatrix4f_OrthoSubProjection(Projection[0], orthoScale0, orthoDistance, EyeRenderDesc[0].ViewAdjust.x); OrthoProjection[1] = ovrMatrix4f_OrthoSubProjection(Projection[1], orthoScale1, orthoDistance, EyeRenderDesc[1].ViewAdjust.x); }
//------------------------------------------------------------------------------------- int Init() { // Initializes LibOVR, and the Rift ovr_Initialize(); if (!HMD) { HMD = ovrHmd_Create(0); if (!HMD) { MessageBoxA(NULL, "Oculus Rift not detected.", "", MB_OK); return(1); } if (HMD->ProductName[0] == '\0') MessageBoxA(NULL, "Rift detected, display not enabled.", "", MB_OK); } //Setup Window and Graphics - use window frame if relying on Oculus driver const int backBufferMultisample = 1; bool UseAppWindowFrame = (HMD->HmdCaps & ovrHmdCap_ExtendDesktop) ? false : true; HWND window = Util_InitWindowAndGraphics(Recti(HMD->WindowsPos, HMD->Resolution), FullScreen, backBufferMultisample, UseAppWindowFrame,&pRender); if (!window) return 1; ovrHmd_AttachToWindow(HMD, window, NULL, NULL); //Configure Stereo settings. Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(HMD, ovrEye_Left, HMD->DefaultEyeFov[0], 1.0f); Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(HMD, ovrEye_Right, HMD->DefaultEyeFov[1], 1.0f); Sizei RenderTargetSize; RenderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w; RenderTargetSize.h = max ( recommenedTex0Size.h, recommenedTex1Size.h ); const int eyeRenderMultisample = 1; pRendertargetTexture = pRender->CreateTexture(Texture_RGBA | Texture_RenderTarget | eyeRenderMultisample, RenderTargetSize.w, RenderTargetSize.h, NULL); // The actual RT size may be different due to HW limits. RenderTargetSize.w = pRendertargetTexture->GetWidth(); RenderTargetSize.h = pRendertargetTexture->GetHeight(); // Initialize eye rendering information. // The viewport sizes are re-computed in case RenderTargetSize changed due to HW limitations. ovrFovPort eyeFov[2] = { HMD->DefaultEyeFov[0], HMD->DefaultEyeFov[1] } ; EyeRenderViewport[0].Pos = Vector2i(0,0); EyeRenderViewport[0].Size = Sizei(RenderTargetSize.w / 2, RenderTargetSize.h); EyeRenderViewport[1].Pos = Vector2i((RenderTargetSize.w + 1) / 2, 0); EyeRenderViewport[1].Size = EyeRenderViewport[0].Size; #if SDK_RENDER // Query OGL texture data. EyeTexture[0].OGL.Header.API = ovrRenderAPI_OpenGL; EyeTexture[0].OGL.Header.TextureSize = RenderTargetSize; EyeTexture[0].OGL.Header.RenderViewport = EyeRenderViewport[0]; EyeTexture[0].OGL.TexId = pRendertargetTexture->TexId; // Right eye uses the same texture, but different rendering viewport. EyeTexture[1] = EyeTexture[0]; EyeTexture[1].OGL.Header.RenderViewport = EyeRenderViewport[1]; // Configure OpenGL. ovrGLConfig oglcfg; oglcfg.OGL.Header.API = ovrRenderAPI_OpenGL; oglcfg.OGL.Header.RTSize = Sizei(HMD->Resolution.w, HMD->Resolution.h); oglcfg.OGL.Header.Multisample = backBufferMultisample; oglcfg.OGL.Window = window; oglcfg.OGL.DC = GetDC(window); if (!ovrHmd_ConfigureRendering(HMD, &oglcfg.Config, ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive, eyeFov, EyeRenderDesc)) return(1); #else //Distortion vertex shader const char* vertexShader = "#version 110 \n" "uniform vec2 EyeToSourceUVScale; \n" "uniform vec2 EyeToSourceUVOffset; \n" "uniform mat4 EyeRotationStart; \n" "uniform mat4 EyeRotationEnd; \n" "attribute vec2 Position; \n" "attribute vec2 inTWLF_V; \n" "attribute vec2 inTexCoord0; \n" "attribute vec2 inTexCoord1; \n" "attribute vec2 inTexCoord2; \n" "varying vec4 oPosition; \n" "varying vec2 oTexCoord0; \n" "varying vec2 oTexCoord1; \n" "varying vec2 oTexCoord2; \n" "varying float oVignette; \n" "vec2 TexCoord0 = vec2(inTexCoord0.x, -inTexCoord0.y); \n" "vec2 TexCoord1 = vec2(inTexCoord1.x, -inTexCoord1.y); \n" "vec2 TexCoord2 = vec2(inTexCoord2.x, -inTexCoord2.y); \n" "float timewarpLerpFactor = inTWLF_V.x; \n" "float Vignette = inTWLF_V.y; \n" "vec2 TimewarpTexCoord( in vec2 TexCoord, in mat4 rotMat ) \n" "{ \n" // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic // aberration and distortion). These are now "real world" vectors in direction (x,y,1) // relative to the eye of the HMD. Apply the 3x3 timewarp rotation to these vectors. " vec3 transformed = vec3( ( rotMat * vec4( TexCoord.xy , 1.00000, 1.00000) ).xyz ); \n" // Project them back onto the Z=1 plane of the rendered images. " vec2 flattened = (transformed.xy / transformed.z ); \n" // Scale them into ([0,0.5],[0,1]) or ([0.5,0],[0,1]) UV lookup space (depending on eye) " return ((EyeToSourceUVScale * flattened) + EyeToSourceUVOffset); \n" "} \n" "mat4 mat4_lerp( in mat4 x, in mat4 y, in mat4 s ) \n" "{ \n" " return mat4(mix(x[0],y[0],s[0]), mix(x[1],y[1],s[1]), mix(x[2],y[2],s[2]), mix(x[3],y[3],s[3]));\n" "} \n" "void main() \n" "{ \n" " mat4 lerpedEyeRot = mat4_lerp( EyeRotationStart, EyeRotationEnd, mat4( timewarpLerpFactor));\n" " oTexCoord0 = TimewarpTexCoord( TexCoord0, lerpedEyeRot); \n" " oTexCoord1 = TimewarpTexCoord( TexCoord1, lerpedEyeRot); \n" " oTexCoord2 = TimewarpTexCoord( TexCoord2, lerpedEyeRot); \n" " oPosition = vec4( Position.xy , 0.500000, 1.00000); \n" " oVignette = Vignette; \n" " gl_Position = oPosition; \n" "}"; //Distortion pixel shader const char* pixelShader = "#version 110 \n" "uniform sampler2D Texture0; \n" "varying vec4 oPosition; \n" "varying vec2 oTexCoord0; \n" "varying vec2 oTexCoord1; \n" "varying vec2 oTexCoord2; \n" "varying float oVignette; \n" "void main() \n" "{ \n" // 3 samples for fixing chromatic aberrations " float R = texture2D(Texture0, oTexCoord0.xy).r; \n" " float G = texture2D(Texture0, oTexCoord1.xy).g; \n" " float B = texture2D(Texture0, oTexCoord2.xy).b; \n" " gl_FragColor = (oVignette*vec4(R,G,B,1)); \n" "}"; pRender->InitShaders(vertexShader, pixelShader, &Shaders); for ( int eyeNum = 0; eyeNum < 2; eyeNum++ ) { // Allocate mesh vertices, registering with renderer using the OVR vertex format. ovrDistortionMesh meshData; ovrHmd_CreateDistortionMesh(HMD, (ovrEyeType) eyeNum, eyeFov[eyeNum], ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp, &meshData); MeshVBs[eyeNum] = *pRender->CreateBuffer(); MeshVBs[eyeNum]->Data(Buffer_Vertex,meshData.pVertexData,sizeof(ovrDistortionVertex)*meshData.VertexCount); MeshIBs[eyeNum] = *pRender->CreateBuffer(); MeshIBs[eyeNum]->Data(Buffer_Index,meshData.pIndexData,sizeof(unsigned short) * meshData.IndexCount); ovrHmd_DestroyDistortionMesh( &meshData ); //Create eye render description for use later EyeRenderDesc[eyeNum] = ovrHmd_GetRenderDesc(HMD, (ovrEyeType) eyeNum, eyeFov[eyeNum]); //Do scale and offset ovrHmd_GetRenderScaleAndOffset(eyeFov[eyeNum],RenderTargetSize, EyeRenderViewport[eyeNum], UVScaleOffset[eyeNum]); } #endif ovrHmd_SetEnabledCaps(HMD, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); // Start the sensor which informs of the Rift's pose and motion ovrHmd_ConfigureTracking(HMD, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, 0); // This creates lights and models. pRoomScene = new Scene; PopulateRoomScene(pRoomScene, pRender); return (0); }
//------------------------------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int) { // Initializes LibOVR, and the Rift ovr_Initialize(); HMD = ovrHmd_Create(0); if (!HMD) { MessageBoxA(NULL,"Oculus Rift not detected.","", MB_OK); return(0); } if (HMD->ProductName[0] == '\0') MessageBoxA(NULL,"Rift detected, display not enabled.", "", MB_OK); // Setup Window and Graphics - use window frame if relying on Oculus driver bool windowed = (HMD->HmdCaps & ovrHmdCap_ExtendDesktop) ? false : true; if (!WND.InitWindowAndDevice(hinst, Recti(HMD->WindowsPos, HMD->Resolution), windowed)) return(0); WND.SetMaxFrameLatency(1); ovrHmd_AttachToWindow(HMD, WND.Window, NULL, NULL); ovrHmd_SetEnabledCaps(HMD, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); // Start the sensor which informs of the Rift's pose and motion ovrHmd_ConfigureTracking(HMD, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, 0); // Make the eye render buffers (caution if actual size < requested due to HW limits). for (int eye=0; eye<2; eye++) { Sizei idealSize = ovrHmd_GetFovTextureSize(HMD, (ovrEyeType)eye, HMD->DefaultEyeFov[eye], 1.0f); pEyeRenderTexture[eye] = new ImageBuffer(true, false, idealSize); pEyeDepthBuffer[eye] = new ImageBuffer(true, true, pEyeRenderTexture[eye]->Size); EyeRenderViewport[eye].Pos = Vector2i(0, 0); EyeRenderViewport[eye].Size = pEyeRenderTexture[eye]->Size; } // Setup VR components #if SDK_RENDER #if RENDER_OPENGL ovrGLConfig oglcfg; oglcfg.OGL.Header.API = ovrRenderAPI_OpenGL; oglcfg.OGL.Header.BackBufferSize = Sizei(HMD->Resolution.w, HMD->Resolution.h); oglcfg.OGL.Header.Multisample = 1; oglcfg.OGL.Window = OGL.Window; oglcfg.OGL.DC = GetDC(OGL.Window); if (!ovrHmd_ConfigureRendering(HMD, &oglcfg.Config, ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive, HMD->DefaultEyeFov, EyeRenderDesc)) return(1); #else ovrD3D11Config d3d11cfg; d3d11cfg.D3D11.Header.API = ovrRenderAPI_D3D11; d3d11cfg.D3D11.Header.BackBufferSize = Sizei(HMD->Resolution.w, HMD->Resolution.h); d3d11cfg.D3D11.Header.Multisample = 1; d3d11cfg.D3D11.pDevice = WND.Device; d3d11cfg.D3D11.pDeviceContext = WND.Context; d3d11cfg.D3D11.pBackBufferRT = WND.BackBufferRT; d3d11cfg.D3D11.pSwapChain = WND.SwapChain; if (!ovrHmd_ConfigureRendering(HMD, &d3d11cfg.Config, ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive, HMD->DefaultEyeFov, EyeRenderDesc)) return(1); #endif #else APP_RENDER_SetupGeometryAndShaders(); #endif // Create the room model Scene roomScene(false); // Can simplify scene further with parameter if required. // Initialize Webcams and threads WebCamManager WebCamMngr(HMD); // MAIN LOOP // ========= while (!(WND.Key['Q'] && WND.Key[VK_CONTROL]) && !WND.Key[VK_ESCAPE]) { WND.HandleMessages(); float speed = 1.0f; // Can adjust the movement speed. int timesToRenderScene = 1; // Can adjust the render burden on the app. ovrVector3f useHmdToEyeViewOffset[2] = {EyeRenderDesc[0].HmdToEyeViewOffset, EyeRenderDesc[1].HmdToEyeViewOffset}; // Start timing #if SDK_RENDER ovrHmd_BeginFrame(HMD, 0); #else ovrHmd_BeginFrameTiming(HMD, 0); #endif // Handle key toggles for re-centering, meshes, FOV, etc. ExampleFeatures1(&speed, ×ToRenderScene, useHmdToEyeViewOffset); // Keyboard inputs to adjust player orientation if (WND.Key[VK_LEFT]) Yaw += 0.02f; if (WND.Key[VK_RIGHT]) Yaw -= 0.02f; // Keyboard inputs to adjust player position if (WND.Key['W']||WND.Key[VK_UP]) Pos+=Matrix4f::RotationY(Yaw).Transform(Vector3f(0,0,-speed*0.05f)); if (WND.Key['S']||WND.Key[VK_DOWN]) Pos+=Matrix4f::RotationY(Yaw).Transform(Vector3f(0,0,+speed*0.05f)); if (WND.Key['D']) Pos+=Matrix4f::RotationY(Yaw).Transform(Vector3f(+speed*0.05f,0,0)); if (WND.Key['A']) Pos+=Matrix4f::RotationY(Yaw).Transform(Vector3f(-speed*0.05f,0,0)); Pos.y = ovrHmd_GetFloat(HMD, OVR_KEY_EYE_HEIGHT, Pos.y); // Animate the cube if (speed) roomScene.Models[0]->Pos = Vector3f(9*sin(0.01f*clock),3,9*cos(0.01f*clock)); // Get both eye poses simultaneously, with IPD offset already included. ovrPosef temp_EyeRenderPose[2]; ovrHmd_GetEyePoses(HMD, 0, useHmdToEyeViewOffset, temp_EyeRenderPose, NULL); // Update textures with WebCams' frames WebCamMngr.Update(); // Render the two undistorted eye views into their render buffers. for (int eye = 0; eye < 2; eye++) { ImageBuffer * useBuffer = pEyeRenderTexture[eye]; ovrPosef * useEyePose = &EyeRenderPose[eye]; float * useYaw = &YawAtRender[eye]; bool clearEyeImage = true; bool updateEyeImage = true; // Handle key toggles for half-frame rendering, buffer resolution, etc. ExampleFeatures2(eye, &useBuffer, &useEyePose, &useYaw, &clearEyeImage, &updateEyeImage); if (clearEyeImage) #if RENDER_OPENGL WND.ClearAndSetRenderTarget(useBuffer, Recti(EyeRenderViewport[eye])); #else WND.ClearAndSetRenderTarget(useBuffer->TexRtv, pEyeDepthBuffer[eye], Recti(EyeRenderViewport[eye])); #endif if (updateEyeImage) { // Write in values actually used (becomes significant in Example features) *useEyePose = temp_EyeRenderPose[eye]; *useYaw = Yaw; // Get view and projection matrices (note near Z to reduce eye strain) Matrix4f rollPitchYaw = Matrix4f::RotationY(Yaw); Matrix4f finalRollPitchYaw = rollPitchYaw * Matrix4f(useEyePose->Orientation); Vector3f finalUp = finalRollPitchYaw.Transform(Vector3f(0, 1, 0)); Vector3f finalForward = finalRollPitchYaw.Transform(Vector3f(0, 0, -1)); Vector3f shiftedEyePos = Pos + rollPitchYaw.Transform(useEyePose->Position); Matrix4f view = Matrix4f::LookAtRH(shiftedEyePos, shiftedEyePos + finalForward, finalUp); Matrix4f proj = ovrMatrix4f_Projection(EyeRenderDesc[eye].Fov, 0.2f, 1000.0f, true); // Keyboard input to switch from "look through" to scene mode static bool bOldLookThrough = false; static bool bLookThrough = true; if (WND.Key['X'] && bOldLookThrough != WND.Key['X']) { bLookThrough = !bLookThrough; } bOldLookThrough = WND.Key['X']; if(!bLookThrough) { // Render the scene for (int t=0; t<timesToRenderScene; t++) roomScene.Render(view, proj.Transposed()); WebCamMngr.DrawBoard(view, proj.Transposed()); } else { WebCamMngr.DrawLookThrough(eye); } } } // Do distortion rendering, Present and flush/sync #if SDK_RENDER #if RENDER_OPENGL ovrGLTexture eyeTexture[2]; // Gather data for eye textures for (int eye = 0; eye<2; eye++) { eyeTexture[eye].OGL.Header.API = ovrRenderAPI_OpenGL; eyeTexture[eye].OGL.Header.TextureSize = pEyeRenderTexture[eye]->Size; eyeTexture[eye].OGL.Header.RenderViewport = EyeRenderViewport[eye]; eyeTexture[eye].OGL.TexId = pEyeRenderTexture[eye]->TexId; } #else ovrD3D11Texture eyeTexture[2]; // Gather data for eye textures for (int eye = 0; eye<2; eye++) { eyeTexture[eye].D3D11.Header.API = ovrRenderAPI_D3D11; eyeTexture[eye].D3D11.Header.TextureSize = pEyeRenderTexture[eye]->Size; eyeTexture[eye].D3D11.Header.RenderViewport = EyeRenderViewport[eye]; eyeTexture[eye].D3D11.pTexture = pEyeRenderTexture[eye]->Tex; eyeTexture[eye].D3D11.pSRView = pEyeRenderTexture[eye]->TexSv; } #endif ovrHmd_EndFrame(HMD, EyeRenderPose, &eyeTexture[0].Texture); #else APP_RENDER_DistortAndPresent(); #endif } WebCamMngr.StopCapture(); // Release and close down ovrHmd_Destroy(HMD); ovr_Shutdown(); WND.ReleaseWindow(hinst); return(0); }
OculusManager& OculusManager::getOculusManager() { static OculusManager* oculusManager = NULL; if (oculusManager == NULL) { oculusManager = new OculusManager(); if (!ovr_Initialize()) { fprintf(stderr, "Failed to initialize the Oculus SDK"); } //= *OculusManager::getHmd(); g_Hmd = ovrHmd_Create(0); if (!g_Hmd) { printf("No Oculus Rift device attached, using virtual version...\n"); g_Hmd = ovrHmd_CreateDebug(ovrHmd_DK2); } printf("initialized HMD: %s - %s\n", g_Hmd->Manufacturer, g_Hmd->ProductName); if (!glfwInit()) exit(EXIT_FAILURE); if (l_MultiSampling) glfwWindowHint(GLFW_SAMPLES, 4); else glfwWindowHint(GLFW_SAMPLES, 0); bool l_DirectMode = ((g_Hmd->HmdCaps & ovrHmdCap_ExtendDesktop) == 0); GLFWmonitor* l_Monitor; ovrSizei l_ClientSize; if (l_DirectMode) { printf("Running in \"Direct\" mode...\n"); l_Monitor = NULL; l_ClientSize.w = g_Hmd->Resolution.w / 2; // Something reasonable, smaller, but maintain aspect ratio... l_ClientSize.h = g_Hmd->Resolution.h / 2; // Something reasonable, smaller, but maintain aspect ratio... } else // Extended Desktop mode... { printf("Running in \"Extended Desktop\" mode...\n"); int l_Count; GLFWmonitor** l_Monitors = glfwGetMonitors(&l_Count); switch (l_Count) { case 0: printf("No monitors found, exiting...\n"); exit(EXIT_FAILURE); break; case 1: printf("Two monitors expected, found only one, using primary...\n"); l_Monitor = glfwGetPrimaryMonitor(); break; case 2: printf("Two monitors found, using second monitor...\n"); l_Monitor = l_Monitors[1]; break; default: printf("More than two monitors found, using second monitor...\n"); l_Monitor = l_Monitors[1]; } l_ClientSize.w = g_Hmd->Resolution.w; // 1920 for DK2... l_ClientSize.h = g_Hmd->Resolution.h; // 1080 for DK2... } l_Window = glfwCreateWindow(l_ClientSize.w, l_ClientSize.h, "GLFW Oculus Rift Test", l_Monitor, NULL); if (!l_Window) { glfwTerminate(); exit(EXIT_FAILURE); } #if defined(_WIN32) if (l_DirectMode) { ovrBool l_AttachResult = ovrHmd_AttachToWindow(g_Hmd, glfwGetWin32Window(l_Window), NULL, NULL); if (!l_AttachResult) { printf("Could not attach to window..."); exit(EXIT_FAILURE); } } #endif glfwMakeContextCurrent(l_Window); glewExperimental = GL_TRUE; GLenum l_GlewResult = glewInit(); if (l_GlewResult != GLEW_OK) { printf("glewInit() error.\n"); exit(EXIT_FAILURE); } int l_Major = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MAJOR); int l_Minor = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MINOR); int l_Profile = glfwGetWindowAttrib(l_Window, GLFW_OPENGL_PROFILE); printf("OpenGL: %d.%d ", l_Major, l_Minor); if (l_Major >= 3) // Profiles introduced in OpenGL 3.0... { if (l_Profile == GLFW_OPENGL_COMPAT_PROFILE) printf("GLFW_OPENGL_COMPAT_PROFILE\n"); else printf("GLFW_OPENGL_CORE_PROFILE\n"); } printf("Vendor: %s\n", (char*)glGetString(GL_VENDOR)); printf("Renderer: %s\n", (char*)glGetString(GL_RENDERER)); ovrSizei l_EyeTextureSizes[2]; l_EyeTextureSizes[ovrEye_Left] = ovrHmd_GetFovTextureSize(g_Hmd, ovrEye_Left, g_Hmd->MaxEyeFov[ovrEye_Left], 1.0f); l_EyeTextureSizes[ovrEye_Right] = ovrHmd_GetFovTextureSize(g_Hmd, ovrEye_Right, g_Hmd->MaxEyeFov[ovrEye_Right], 1.0f); // Combine for one texture for both eyes... g_RenderTargetSize.w = l_EyeTextureSizes[ovrEye_Left].w + l_EyeTextureSizes[ovrEye_Right].w; g_RenderTargetSize.h = (l_EyeTextureSizes[ovrEye_Left].h > l_EyeTextureSizes[ovrEye_Right].h ? l_EyeTextureSizes[ovrEye_Left].h : l_EyeTextureSizes[ovrEye_Right].h); // Create the FBO being a single one for both eyes (this is open for debate)... glGenFramebuffers(1, &l_FBOId); glBindFramebuffer(GL_FRAMEBUFFER, l_FBOId); // The texture we're going to render to... glGenTextures(1, &l_TextureId); // "Bind" the newly created texture : all future texture functions will modify this texture... glBindTexture(GL_TEXTURE_2D, l_TextureId); // Give an empty image to OpenGL (the last "0") glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g_RenderTargetSize.w, g_RenderTargetSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); // Linear filtering... glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Create Depth Buffer... glGenRenderbuffers(1, &l_DepthBufferId); glBindRenderbuffer(GL_RENDERBUFFER, l_DepthBufferId); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, g_RenderTargetSize.w, g_RenderTargetSize.h); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, l_DepthBufferId); // Set the texture as our colour attachment #0... glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, l_TextureId, 0); // Set the list of draw buffers... GLenum l_GLDrawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; glDrawBuffers(1, l_GLDrawBuffers); // "1" is the size of DrawBuffers // Check if everything is OK... GLenum l_Check = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); if (l_Check != GL_FRAMEBUFFER_COMPLETE) { printf("There is a problem with the FBO.\n"); exit(EXIT_FAILURE); } // Unbind... glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); // Setup textures for each eye... // Left eye... g_EyeTextures[ovrEye_Left].Header.API = ovrRenderAPI_OpenGL; g_EyeTextures[ovrEye_Left].Header.TextureSize = g_RenderTargetSize; g_EyeTextures[ovrEye_Left].Header.RenderViewport.Pos.x = 0; g_EyeTextures[ovrEye_Left].Header.RenderViewport.Pos.y = 0; g_EyeTextures[ovrEye_Left].Header.RenderViewport.Size = l_EyeTextureSizes[ovrEye_Left]; ((ovrGLTexture&)(g_EyeTextures[ovrEye_Left])).OGL.TexId = l_TextureId; // Right eye (mostly the same as left but with the viewport on the right side of the texture)... g_EyeTextures[ovrEye_Right] = g_EyeTextures[ovrEye_Left]; g_EyeTextures[ovrEye_Right].Header.RenderViewport.Pos.x = (g_RenderTargetSize.w + 1) / 2; g_EyeTextures[ovrEye_Right].Header.RenderViewport.Pos.y = 0; // Oculus Rift eye configurations... g_Cfg.OGL.Header.API = ovrRenderAPI_OpenGL; g_Cfg.OGL.Header.RTSize.w = l_ClientSize.w; g_Cfg.OGL.Header.RTSize.h = l_ClientSize.h; g_Cfg.OGL.Header.Multisample = (l_MultiSampling ? 1 : 0); #if defined(_WIN32) g_Cfg.OGL.Window = glfwGetWin32Window(l_Window); g_Cfg.OGL.DC = GetDC(g_Cfg.OGL.Window); #elif defined(__linux__) l_Cfg.OGL.Win = glfwGetX11Window(l_Window); l_Cfg.OGL.Disp = glfwGetX11Display(); #endif // Enable capabilities... // ovrHmd_SetEnabledCaps(g_Hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); ovrBool l_ConfigureResult = ovrHmd_ConfigureRendering(g_Hmd, &g_Cfg.Config, g_DistortionCaps, g_Hmd->MaxEyeFov, g_EyeRenderDesc); glUseProgram(0); // Avoid OpenGL state leak in ovrHmd_ConfigureRendering... if (!l_ConfigureResult) { printf("Configure failed.\n"); exit(EXIT_FAILURE); } // Start the sensor which provides the Rift’s pose and motion... uint32_t l_SupportedSensorCaps = ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position; uint32_t l_RequiredTrackingCaps = 0; ovrBool l_TrackingResult = ovrHmd_ConfigureTracking(g_Hmd, l_SupportedSensorCaps, l_RequiredTrackingCaps); if (!l_TrackingResult) { printf("Could not start tracking..."); exit(EXIT_FAILURE); } // Projection matrici for each eye will not change at runtime, we can set them here... g_ProjectionMatrici[ovrEye_Left] = ovrMatrix4f_Projection(g_EyeRenderDesc[ovrEye_Left].Fov, 0.3f, 100.0f, true); g_ProjectionMatrici[ovrEye_Right] = ovrMatrix4f_Projection(g_EyeRenderDesc[ovrEye_Right].Fov, 0.3f, 100.0f, true); // IPD offset values will not change at runtime, we can set them here... g_EyeOffsets[ovrEye_Left] = g_EyeRenderDesc[ovrEye_Left].HmdToEyeViewOffset; g_EyeOffsets[ovrEye_Right] = g_EyeRenderDesc[ovrEye_Right].HmdToEyeViewOffset; ovrHmd_RecenterPose(g_Hmd); return *oculusManager; } }