void RiftAppSkeleton::_drawSceneMono() const { _resetGLState(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); const int w = m_Cfg.OGL.Header.RTSize.w; const int h = m_Cfg.OGL.Header.RTSize.h; const glm::vec3 EyePos(m_chassisPos.x, m_chassisPos.y, m_chassisPos.z); const glm::vec3 LookVec(0.0f, 0.0f, -1.0f); const glm::vec3 up(0.0f, 1.0f, 0.0f); ovrPosef eyePose; eyePose.Orientation = OVR::Quatf(); eyePose.Position = OVR::Vector3f(); const OVR::Matrix4f view = _MakeModelviewMatrix( eyePose, OVR::Vector3f(0.0f), m_chassisYaw, m_chassisPos); const glm::mat4 persp = glm::perspective( 90.0f, static_cast<float>(w)/static_cast<float>(h), 0.004f, 500.0f); ovrRecti rvp = {0,0,w,h}; _DrawScenes(&view.Transposed().M[0][0], glm::value_ptr(persp), rvp); }
void OVRSDK06AppSkeleton::display_sdk() const { ovrHmd hmd = m_Hmd; if (hmd == NULL) return; ovrTrackingState outHmdTrackingState = { 0 }; ovrHmd_GetEyePoses(m_Hmd, m_frameIndex, m_eyeOffsets, m_eyePoses, &outHmdTrackingState); for (ovrEyeType eye = ovrEyeType::ovrEye_Left; eye < ovrEyeType::ovrEye_Count; eye = static_cast<ovrEyeType>(eye + 1)) { const ovrSwapTextureSet& swapSet = *m_pTexSet[eye]; glBindFramebuffer(GL_FRAMEBUFFER, m_swapFBO.id); ovrGLTexture& tex = (ovrGLTexture&)(swapSet.Textures[swapSet.CurrentIndex]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.OGL.TexId, 0); { // Handle render target resolution scaling m_layerEyeFov.Viewport[eye].Size = ovrHmd_GetFovTextureSize(m_Hmd, eye, m_layerEyeFov.Fov[eye], m_fboScale); ovrRecti& vp = m_layerEyeFov.Viewport[eye]; if (m_layerEyeFov.Header.Flags & ovrLayerFlag_TextureOriginAtBottomLeft) { ///@note It seems that the render viewport should be vertically centered within the swapSet texture. /// See also OculusWorldDemo.cpp:1443 - "The usual OpenGL viewports-don't-match-UVs oddness." const int texh = swapSet.Textures[swapSet.CurrentIndex].Header.TextureSize.h; vp.Pos.y = (texh - vp.Size.h) / 2; } glViewport(vp.Pos.x, vp.Pos.y, vp.Size.w, vp.Size.h); glClearColor(0.f, 0.f, 0.f, 0.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Render the scene for the current eye const ovrPosef& eyePose = m_eyePoses[eye]; const glm::mat4 viewLocal = makeMatrixFromPose(eyePose); const glm::mat4 viewWorld = makeWorldToChassisMatrix() * viewLocal; const glm::mat4& proj = m_eyeProjections[eye]; _DrawScenes( glm::value_ptr(glm::inverse(viewWorld)), glm::value_ptr(proj), glm::value_ptr(glm::inverse(viewLocal))); m_layerEyeFov.RenderPose[eye] = eyePose; } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0); } ovrLayerEyeFov& layer = m_layerEyeFov; ovrLayerHeader* layers = &layer.Header; ovrResult result = ovrHmd_SubmitFrame(hmd, m_frameIndex, NULL, &layers, 1); // Increment counters in swap texture set for (ovrEyeType eye = ovrEyeType::ovrEye_Left; eye < ovrEyeType::ovrEye_Count; eye = static_cast<ovrEyeType>(eye + 1)) { ovrSwapTextureSet& swapSet = *m_pTexSet[eye]; ++swapSet.CurrentIndex %= swapSet.TextureCount; } // Blit output to main app window to show something on screen in addition // to what's in the Rift. This could optionally be the distorted texture // from the OVR SDK's mirror texture, or perhaps a single eye's undistorted // view, or even a third-person render(at a performance cost). if (true) { glViewport(0, 0, m_appWindowSize.w, m_appWindowSize.h); glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFBO.id); glBlitFramebuffer( 0, m_mirrorFBO.h, m_mirrorFBO.w, 0, 0, 0, m_appWindowSize.w, m_appWindowSize.h, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); } ++m_frameIndex; }
void RiftAppSkeleton::display_sdk() //const { ovrHmd hmd = m_Hmd; if (hmd == NULL) return; //const ovrFrameTiming hmdFrameTiming = ovrHmd_BeginFrame(m_Hmd, 0); bindFBO(m_renderBuffer); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // For passing to EndFrame once rendering is done ovrPosef renderPose[2]; ovrTexture eyeTexture[2]; for (int eyeIndex=0; eyeIndex<ovrEye_Count; eyeIndex++) { const ovrEyeType eye = hmd->EyeRenderOrder[eyeIndex]; const ovrPosef eyePose = ovrHmd_GetEyePose(m_Hmd, eye); m_eyeOri = eyePose.Orientation; // cache this for movement direction _StoreHmdPose(eyePose); const ovrGLTexture& otex = l_EyeTexture[eye]; const ovrRecti& rvp = otex.OGL.Header.RenderViewport; glViewport( rvp.Pos.x, rvp.Pos.y, rvp.Size.w, rvp.Size.h ); const OVR::Matrix4f proj = ovrMatrix4f_Projection( m_EyeRenderDesc[eye].Fov, 0.01f, 10000.0f, true); const OVR::Matrix4f view = _MakeModelviewMatrix( eyePose, -OVR::Vector3f(m_EyeRenderDesc[eye].ViewAdjust), // not sure why negative... m_chassisYaw, m_chassisPos); const OVR::Matrix4f scaledView = _MakeModelviewMatrix( eyePose, -OVR::Vector3f(m_EyeRenderDesc[eye].ViewAdjust), // not sure why negative... m_chassisYaw, m_chassisPos, m_headSize); _resetGLState(); _DrawScenes(&view.Transposed().M[0][0], &proj.Transposed().M[0][0], rvp, &scaledView.Transposed().M[0][0]); renderPose[eyeIndex] = eyePose; eyeTexture[eyeIndex] = l_EyeTexture[eye].Texture; } unbindFBO(); ovrHmd_EndFrame(m_Hmd, renderPose, eyeTexture); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); glUseProgram(0); }
///@todo Even though this function shares most of its code with client rendering, /// which appears to work fine, it is non-convergable. It appears that the projection /// matrices for each eye are too far apart? Could be modelview... void RiftAppSkeleton::display_stereo_undistorted() //const { ovrHmd hmd = m_Hmd; if (hmd == NULL) return; //ovrFrameTiming hmdFrameTiming = ovrHmd_BeginFrameTiming(hmd, 0); bindFBO(m_renderBuffer, m_fboScale); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { ovrEyeType eye = hmd->EyeRenderOrder[eyeIndex]; ovrPosef eyePose = ovrHmd_GetEyePose(hmd, eye); const ovrGLTexture& otex = l_EyeTexture[eye]; const ovrRecti& rvp = otex.OGL.Header.RenderViewport; const ovrRecti rsc = { static_cast<int>(m_fboScale * rvp.Pos.x), static_cast<int>(m_fboScale * rvp.Pos.y), static_cast<int>(m_fboScale * rvp.Size.w), static_cast<int>(m_fboScale * rvp.Size.h) }; glViewport(rsc.Pos.x, rsc.Pos.y, rsc.Size.w, rsc.Size.h); OVR::Quatf orientation = OVR::Quatf(eyePose.Orientation); OVR::Matrix4f proj = ovrMatrix4f_Projection( m_EyeRenderDesc[eye].Fov, 0.01f, 10000.0f, true); //m_EyeRenderDesc[eye].DistortedViewport; OVR::Vector3f EyePos = m_chassisPos; OVR::Matrix4f view = OVR::Matrix4f(orientation.Inverted()) * OVR::Matrix4f::RotationY(m_chassisYaw) * OVR::Matrix4f::Translation(-EyePos); OVR::Matrix4f eyeview = OVR::Matrix4f::Translation(m_EyeRenderDesc[eye].ViewAdjust) * view; _resetGLState(); _DrawScenes(&eyeview.Transposed().M[0][0], &proj.Transposed().M[0][0], rvp); } unbindFBO(); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); // Present FBO to screen const GLuint prog = m_presentFbo.prog(); glUseProgram(prog); m_presentFbo.bindVAO(); { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_renderBuffer.tex); glUniform1i(m_presentFbo.GetUniLoc("fboTex"), 0); // This is the only uniform that changes per-frame glUniform1f(m_presentFbo.GetUniLoc("fboScale"), m_fboScale); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } glBindVertexArray(0); glUseProgram(0); ovrHmd_EndFrameTiming(hmd); }
void RiftAppSkeleton::display_client() //const { ovrHmd hmd = m_Hmd; if (hmd == NULL) return; //ovrFrameTiming hmdFrameTiming = ovrHmd_BeginFrameTiming(hmd, 0); bindFBO(m_renderBuffer, m_fboScale); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { const ovrEyeType eye = hmd->EyeRenderOrder[eyeIndex]; const ovrPosef eyePose = ovrHmd_GetEyePose(hmd, eye); m_eyeOri = eyePose.Orientation; // cache this for movement direction _StoreHmdPose(eyePose); const ovrGLTexture& otex = l_EyeTexture[eye]; const ovrRecti& rvp = otex.OGL.Header.RenderViewport; const ovrRecti rsc = { static_cast<int>(m_fboScale * rvp.Pos.x), static_cast<int>(m_fboScale * rvp.Pos.y), static_cast<int>(m_fboScale * rvp.Size.w), static_cast<int>(m_fboScale * rvp.Size.h) }; glViewport(rsc.Pos.x, rsc.Pos.y, rsc.Size.w, rsc.Size.h); const OVR::Matrix4f proj = ovrMatrix4f_Projection( m_EyeRenderDesc[eye].Fov, 0.01f, 10000.0f, true); ///@todo Should we be using this variable? //m_EyeRenderDesc[eye].DistortedViewport; const OVR::Matrix4f view = _MakeModelviewMatrix( eyePose, m_EyeRenderDesc[eye].ViewAdjust, m_chassisYaw, m_chassisPos); const OVR::Matrix4f scaledView = _MakeModelviewMatrix( eyePose, m_EyeRenderDesc[eye].ViewAdjust, m_chassisYaw, m_chassisPos, m_headSize); _resetGLState(); _DrawScenes(&view.Transposed().M[0][0], &proj.Transposed().M[0][0], rsc, &scaledView.Transposed().M[0][0]); } unbindFBO(); // Set full viewport...? const int w = m_Cfg.OGL.Header.RTSize.w; const int h = m_Cfg.OGL.Header.RTSize.h; glViewport(0, 0, w, h); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); // Now draw the distortion mesh... for(int eyeNum = 0; eyeNum < 2; eyeNum++) { const ShaderWithVariables& eyeShader = eyeNum == 0 ? m_presentDistMeshL : m_presentDistMeshR; const GLuint prog = eyeShader.prog(); glUseProgram(prog); //glBindVertexArray(eyeShader.m_vao); { const ovrDistortionMesh& mesh = m_DistMeshes[eyeNum]; glBindBuffer(GL_ARRAY_BUFFER, 0); const int a_pos = glGetAttribLocation(prog, "vPosition"); glVertexAttribPointer(a_pos, 4, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), &mesh.pVertexData[0].ScreenPosNDC.x); glEnableVertexAttribArray(a_pos); const int a_texR = glGetAttribLocation(prog, "vTexR"); if (a_texR > -1) { glVertexAttribPointer(a_texR, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), &mesh.pVertexData[0].TanEyeAnglesR); glEnableVertexAttribArray(a_texR); } const int a_texG = glGetAttribLocation(prog, "vTexG"); if (a_texG > -1) { glVertexAttribPointer(a_texG, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), &mesh.pVertexData[0].TanEyeAnglesG); glEnableVertexAttribArray(a_texG); } const int a_texB = glGetAttribLocation(prog, "vTexB"); if (a_texB > -1) { glVertexAttribPointer(a_texB, 2, GL_FLOAT, GL_FALSE, sizeof(ovrDistortionVertex), &mesh.pVertexData[0].TanEyeAnglesB); glEnableVertexAttribArray(a_texB); } ovrVector2f uvoff = m_uvScaleOffsetOut[2*eyeNum + 1]; //DistortionData.UVScaleOffset[eyeNum][0]; ovrVector2f uvscale = m_uvScaleOffsetOut[2*eyeNum + 0]; //DistortionData.UVScaleOffset[eyeNum][1]; glUniform2f(eyeShader.GetUniLoc("EyeToSourceUVOffset"), uvoff.x, uvoff.y); glUniform2f(eyeShader.GetUniLoc("EyeToSourceUVScale"), uvscale.x, uvscale.y); #if 0 // Setup shader constants DistortionData.Shaders->SetUniform2f( "EyeToSourceUVScale", DistortionData.UVScaleOffset[eyeNum][0].x, DistortionData.UVScaleOffset[eyeNum][0].y); DistortionData.Shaders->SetUniform2f( "EyeToSourceUVOffset", DistortionData.UVScaleOffset[eyeNum][1].x, DistortionData.UVScaleOffset[eyeNum][1].y); if (distortionCaps & ovrDistortionCap_TimeWarp) { // TIMEWARP - Additional shader constants required ovrMatrix4f timeWarpMatrices[2]; ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum, eyeRenderPoses[eyeNum], timeWarpMatrices); //WARNING!!! These matrices are transposed in SetUniform4x4f, before being used by the shader. DistortionData.Shaders->SetUniform4x4f("EyeRotationStart", Matrix4f(timeWarpMatrices[0])); DistortionData.Shaders->SetUniform4x4f("EyeRotationEnd", Matrix4f(timeWarpMatrices[1])); } // Perform distortion pRender->Render( &distortionShaderFill, DistortionData.MeshVBs[eyeNum], DistortionData.MeshIBs[eyeNum]); #endif glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_renderBuffer.tex); glUniform1i(eyeShader.GetUniLoc("fboTex"), 0); // This is the only uniform that changes per-frame glUniform1f(eyeShader.GetUniLoc("fboScale"), m_fboScale); glDrawElements( GL_TRIANGLES, mesh.IndexCount, GL_UNSIGNED_SHORT, &mesh.pIndexData[0]); } glBindVertexArray(0); glUseProgram(0); } ovrHmd_EndFrameTiming(hmd); }