qboolean VR_Enable() { int i; if( ovr_Initialize(NULL) != ovrSuccess ) { Con_Printf("Failed to Initialize Oculus SDK"); return false; } if( ovrHmd_Create(0, &hmd) != ovrSuccess ) { Con_Printf("Failed to get HMD"); return false; } if( !InitOpenGLExtensions() ) { Con_Printf("Failed to initialize OpenGL extensions"); return false; } ovrHmd_CreateMirrorTextureGL(hmd, GL_RGBA, glwidth, glheight, (ovrTexture**)&mirror_texture); glGenFramebuffersEXT(1, &mirror_fbo); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mirror_fbo); glFramebufferTexture2DEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, mirror_texture->OGL.TexId, 0); glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); for( i = 0; i < 2; i++ ) { ovrSizei size = ovrHmd_GetFovTextureSize(hmd, (ovrEyeType)i, hmd->DefaultEyeFov[i], 1); eyes[i].index = i; eyes[i].fbo = CreateFBO(size.w, size.h); eyes[i].render_desc = ovrHmd_GetRenderDesc(hmd, (ovrEyeType)i, hmd->DefaultEyeFov[i]); eyes[i].fov_x = (atan(hmd->DefaultEyeFov[i].LeftTan) + atan(hmd->DefaultEyeFov[i].RightTan)) / M_PI_DIV_180; eyes[i].fov_y = (atan(hmd->DefaultEyeFov[i].UpTan) + atan(hmd->DefaultEyeFov[i].DownTan)) / M_PI_DIV_180; } ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence|ovrHmdCap_DynamicPrediction); ovrHmd_ConfigureTracking(hmd, ovrTrackingCap_Orientation|ovrTrackingCap_MagYawCorrection|ovrTrackingCap_Position, 0); wglSwapIntervalEXT(0); // Disable V-Sync vr_initialized = true; return true; }
///@brief Called once a GL context has been set up. void OVRSDK06AppSkeleton::initVR(bool swapBackBufferDims) { if (m_Hmd == NULL) return; for (int i = 0; i < 2; ++i) { if (m_pTexSet[i]) { ovrHmd_DestroySwapTextureSet(m_Hmd, m_pTexSet[i]); m_pTexSet[i] = nullptr; } } // Set up eye fields of view ovrLayerEyeFov& layer = m_layerEyeFov; layer.Header.Type = ovrLayerType_EyeFov; layer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; // Create eye render target textures and FBOs for (ovrEyeType eye = ovrEyeType::ovrEye_Left; eye < ovrEyeType::ovrEye_Count; eye = static_cast<ovrEyeType>(eye + 1)) { const ovrFovPort& fov = layer.Fov[eye] = m_Hmd->MaxEyeFov[eye]; const ovrSizei& size = layer.Viewport[eye].Size = ovrHmd_GetFovTextureSize(m_Hmd, eye, fov, 1.f); layer.Viewport[eye].Pos = { 0, 0 }; LOG_INFO("Eye %d tex : %dx%d @ (%d,%d)", eye, size.w, size.h, layer.Viewport[eye].Pos.x, layer.Viewport[eye].Pos.y); ovrEyeRenderDesc & erd = m_eyeRenderDescs[eye]; erd = ovrHmd_GetRenderDesc(m_Hmd, eye, m_Hmd->MaxEyeFov[eye]); ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, .1f, 10000.f, ovrProjection_RightHanded); m_eyeProjections[eye] = glm::transpose(glm::make_mat4(&ovrPerspectiveProjection.M[0][0])); m_eyeOffsets[eye] = erd.HmdToEyeViewOffset; // Allocate the frameBuffer that will hold the scene, and then be // re-rendered to the screen with distortion if (!OVR_SUCCESS(ovrHmd_CreateSwapTextureSetGL(m_Hmd, GL_RGBA, size.w, size.h, &m_pTexSet[eye]))) { LOG_ERROR("Unable to create swap textures"); return; } ovrSwapTextureSet& swapSet = *m_pTexSet[eye]; for (int i = 0; i < swapSet.TextureCount; ++i) { const ovrGLTexture& ovrTex = (ovrGLTexture&)swapSet.Textures[i]; glBindTexture(GL_TEXTURE_2D, ovrTex.OGL.TexId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } // Manually assemble swap FBO m_swapFBO.w = size.w; m_swapFBO.h = size.h; glGenFramebuffers(1, &m_swapFBO.id); glBindFramebuffer(GL_FRAMEBUFFER, m_swapFBO.id); const int idx = 0; const ovrGLTextureData* pGLData = reinterpret_cast<ovrGLTextureData*>(&swapSet.Textures[idx]); m_swapFBO.tex = pGLData->TexId; glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_swapFBO.tex, 0); m_swapFBO.depth = 0; glGenRenderbuffers(1, &m_swapFBO.depth); glBindRenderbuffer(GL_RENDERBUFFER, m_swapFBO.depth); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size.w, size.h); glBindRenderbuffer(GL_RENDERBUFFER, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_swapFBO.depth); // Check status { const GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { LOG_ERROR("Framebuffer status incomplete: %d %x", status, status); } } glBindFramebuffer(GL_FRAMEBUFFER, 0); layer.ColorTexture[eye] = m_pTexSet[eye]; } // Mirror texture for displaying to desktop window if (m_pMirrorTex) { ovrHmd_DestroyMirrorTexture(m_Hmd, m_pMirrorTex); } const ovrEyeType eye = ovrEyeType::ovrEye_Left; const ovrFovPort& fov = layer.Fov[eye] = m_Hmd->MaxEyeFov[eye]; const ovrSizei& size = layer.Viewport[eye].Size = ovrHmd_GetFovTextureSize(m_Hmd, eye, fov, 1.f); ovrResult result = ovrHmd_CreateMirrorTextureGL(m_Hmd, GL_RGBA, size.w, size.h, &m_pMirrorTex); if (!OVR_SUCCESS(result)) { LOG_ERROR("Unable to create mirror texture"); return; } // Manually assemble mirror FBO m_mirrorFBO.w = size.w; m_mirrorFBO.h = size.h; glGenFramebuffers(1, &m_mirrorFBO.id); glBindFramebuffer(GL_FRAMEBUFFER, m_mirrorFBO.id); const ovrGLTextureData* pMirrorGLData = reinterpret_cast<ovrGLTextureData*>(m_pMirrorTex); m_mirrorFBO.tex = pMirrorGLData->TexId; glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_mirrorFBO.tex, 0); // Check status { const GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { LOG_ERROR("Framebuffer status incomplete: %d %x", status, status); } } glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); glEnable(GL_DEPTH_TEST); }