love::image::ImageData * Canvas::getImageData(love::image::Image * image) { int row = 4 * width; int size = row * height; GLubyte* pixels = new GLubyte[size]; GLubyte* screenshot = new GLubyte[size]; bindFBO( fbo ); glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); if (current) bindFBO( current->fbo ); else bindFBO( 0 ); GLubyte * src = pixels - row; // second line of source image GLubyte * dst = screenshot + size; // last row of destination image for (int i = 0; i < height; ++i) memcpy(dst -= row, src += row, row); love::image::ImageData* img = image->newImageData(width, height, (void*)screenshot); delete[] screenshot; delete[] pixels; return img; }
void Renderer::renderReflections(float camNear, float camFar) { if (!m_shaderRLR) init(m_windowWidth, m_windowHeight); bindFBO(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shaderRLR->bind(); m_shaderRLR->sendSampler2D("positionTexture", m_gBuffer->getColorTexture(0), 0); m_shaderRLR->sendSampler2D("normalTexture", m_gBuffer->getColorTexture(1), 1); m_shaderRLR->sendSampler2D("colorTexture", getLastFBO()->getColorTexture(2), 2); m_shaderRLR->sendSampler2D("depthBuffer", m_gBuffer->getDepthTexture(), 3); m_shaderRLR->sendMat4("projectionMatrix", m_currentProjectionMatrix); m_shaderRLR->sendInt("screenWidth", m_windowWidth); m_shaderRLR->sendInt("screenHeight", m_windowHeight); m_shaderRLR->sendFloat("zNear", camNear); m_shaderRLR->sendFloat("zFar", camFar); m_shaderRLR->sendFloat("reflectivity", *m_screenSpaceReflectionsStrength); m_sfq.renderGeometry(); m_shaderRLR->unbind(); unbindFBO(); }
void RiftAppSkeleton::display_buffered(bool setViewport) const { bindFBO(m_renderBuffer, m_fboScale); _drawSceneMono(); unbindFBO(); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); if (setViewport) { const int w = m_Cfg.OGL.Header.RTSize.w; const int h = m_Cfg.OGL.Header.RTSize.h; glViewport(0, 0, w, h); } // 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); }
void Renderer::renderDeferredShading() { if (!m_shaderDSLighting || !m_shaderDSCompositing) init(m_windowWidth, m_windowHeight); if (!m_dsLightColor || !m_dsLightRootNode) throw std::string("Error in renderDeferredShading - Light Color or Light Root Node was not set"); FBO *a = new FBO(m_windowWidth,m_windowHeight,3,false,false); a->bind(); glCullFace(GL_FRONT); glEnable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shaderDSLighting->bind(); m_shaderDSLighting->sendMat4("viewMatrix", m_currentViewMatrix); m_shaderDSLighting->sendMat4("projectionMatrix", m_currentProjectionMatrix); m_shaderDSLighting->sendSampler2D("positionMap", m_gBuffer->getColorTexture(0), 0); m_shaderDSLighting->sendSampler2D("normalMap", m_gBuffer->getColorTexture(1), 1); m_shaderDSLighting->sendInt("windowWidth", m_windowWidth); m_shaderDSLighting->sendInt("windowHeight", m_windowHeight); m_shaderDSLighting->sendVec3("lightColor", *m_dsLightColor); m_dsLightRootNode->render(*m_shaderDSLighting); glDisable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); glClearColor(1.0, 1.0, 1.0, 0.0); m_shaderDSLighting->unbind(); a->unbind(); //COMPOSITING TEIL =============================== bindFBO(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shaderDSCompositing->bind(); m_shaderDSCompositing->sendSampler2D("colorMap", getLastFBO()->getColorTexture(2), 0); m_shaderDSCompositing->sendSampler2D("lightMap", a->getColorTexture(2), 1); m_sfq.renderGeometry(); m_shaderDSCompositing->unbind(); unbindFBO(); delete a; }
void Canvas::clear(const Color& c) { Context *ctx = getContext(); GLuint previous = ctx->getDefaultFramebuffer(); if (current != NULL) previous = current->fbo; bindFBO(fbo); Color defaultcolor = ctx->getClearColor(); ctx->setClearColor(c); glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // preserve the background color of the default framebuffer ctx->setClearColor(defaultcolor); bindFBO(previous); }
void FrameBuffer::initColorAttachments() { if(fbo != 0 && attachments.size() != 0) { bindFBO(); glAssert(glDrawBuffers(attachments.size(), attachments.data())); } else glAssert(glDrawBuffer(GL_NONE)); check(); }
void RiftAppSkeleton::RenderThumbnails() { std::vector<Pane*>& panes = m_paneScene.m_panes; for (std::vector<Pane*>::iterator it = panes.begin(); it != panes.end(); ++it) { ShaderPane* pP = reinterpret_cast<ShaderPane*>(*it); if (pP == NULL) continue; ShaderToy* pSt = pP->m_pShadertoy; // Render a view of the shader to the FBO // We must keep the previously bound FBO and restore GLint bound_fbo = 0; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &bound_fbo); bindFBO(pP->m_paneRenderBuffer); //pP->DrawToFBO(); { const glm::vec3 hp = pSt->GetHeadPos(); 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), static_cast<float>(M_PI), OVR::Vector3f(hp.x, hp.y, hp.z)); const glm::mat4 persp = glm::perspective( 90.0f, static_cast<float>(pP->m_paneRenderBuffer.w) / static_cast<float>(pP->m_paneRenderBuffer.h), 0.004f, 500.0f); const bool wasDrawing = m_shaderToyScene.m_bDraw; m_shaderToyScene.m_bDraw = true; m_shaderToyScene.SetShaderToy(pSt); m_shaderToyScene.RenderForOneEye(&view.Transposed().M[0][0], glm::value_ptr(persp)); m_shaderToyScene.m_bDraw = wasDrawing; m_shaderToyScene.SetShaderToy(NULL); } unbindFBO(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bound_fbo); } }
void fillRect(const IntRect &rect, const Vec4 &color) { bindFBO(); glState.scissorTest.pushSet(true); glState.scissorBox.pushSet(rect); glState.clearColor.pushSet(color); FBO::clear(); glState.clearColor.pop(); glState.scissorBox.pop(); glState.scissorTest.pop(); }
void Renderer::renderBlur() { if (!m_shaderBlur) init(m_windowWidth, m_windowHeight); bindFBO(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shaderBlur->bind(); m_shaderBlur->sendSampler2D("image", getLastFBO()->getColorTexture(2), 2); m_shaderBlur->sendFloat("blurstrength", *m_blurStrength); m_sfq.renderGeometry(); m_shaderBlur->unbind(); unbindFBO(); }
void PaneScene::RenderPrePass() const { // We must keep the previously bound FBO and restore GLint bound_fbo = 0; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &bound_fbo); for (std::vector<Pane*>::const_iterator it = m_panes.begin(); it != m_panes.end(); ++it) { const Pane* pP = *it; if (pP == NULL) continue; bindFBO(pP->m_paneRenderBuffer); pP->DrawToFBO(); unbindFBO(); } glBindFramebuffer(GL_FRAMEBUFFER, bound_fbo); }
void Renderer::renderAntiAliasing() { if (!m_shaderFXAA) init(m_windowWidth, m_windowHeight); bindFBO(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shaderFXAA->bind(); m_shaderFXAA->sendSampler2D("colorTexture", getLastFBO()->getColorTexture(2), 2); m_shaderFXAA->sendInt("fboWidth", m_windowWidth); m_shaderFXAA->sendInt("fboHeight", m_windowHeight); m_sfq.renderGeometry(); m_shaderFXAA->unbind(); unbindFBO(); }
void flushPoints() { if (pointArray.count() == 0) return; SimpleColorShader &shader = shState->shaders().simpleColor; shader.bind(); shader.setTranslation(Vec2i()); bindFBO(); pushSetViewport(shader); glState.blendMode.pushSet(BlendNone); pointArray.commit(); pointArray.draw(); pointArray.reset(); glState.blendMode.pop(); popViewport(); }
void FrameBuffer::addTexture(Texture* tex, GLenum attachment) { if(fbo != 0) { textures.push_back(tex); bindFBO(); if(tex->isCubeMap()) { // TODO // http://cg.siomax.ru/index.php/computer-graphics/10-one-pass-rendering-to-cube-map } else { glAssert(glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, tex->getTarget(), tex->getId(), 0)); if(attachment != GL_DEPTH_ATTACHMENT) // TODO stencil attachment must be tested too attachments.push_back(attachment); } } }
void Canvas::stopGrab() { // i am not grabbing. leave me alone if (current != this) return; Context *ctx = getContext(); // bind default bindFBO(ctx->getDefaultFramebuffer()); // Restore previous orthographic projection matrix if (ctx->projectionStack.size() > 1) ctx->projectionStack.pop(); // Restore the previous framebuffer's viewport ctx->popViewport(); current = NULL; }
void Renderer::renderDoF(Scene& scene) { if (!m_shaderDepth || !m_shaderDoF) init(m_windowWidth, m_windowHeight); m_smFBO->bind(); //Clear Shadow Map glClear(GL_DEPTH_BUFFER_BIT); //Set the shader for the light pass. This shader is highly optimized because the scene depth is the only thing that matters here! m_shaderDepth->bind(); m_shaderDepth->sendMat4("viewMatrix", m_currentViewMatrix); m_shaderDepth->sendMat4("projectionMatrix", m_currentProjectionMatrix); //Render the scene scene.render(*m_shaderDepth); //Restore the default framebuffer m_shaderDepth->unbind(); m_smFBO->unbind(); bindFBO(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shaderDoF->bind(); m_shaderDoF->sendSampler2D("tex", getLastFBO()->getColorTexture(2), 2); m_shaderDoF->sendSampler2D("depth", m_smFBO->getDepthTexture(), 1); m_shaderDoF->sendFloat("focus_depth", *m_focusDepth); m_sfq.renderGeometry(); m_shaderDoF->unbind(); unbindFBO(); }
void Canvas::startGrab() { // already grabbing if (current == this) return; Context *ctx = getContext(); // cleanup after previous fbo if (current != NULL) current->stopGrab(); // bind buffer and clear screen bindFBO(fbo); ctx->pushViewport(0, 0, width, height); // Set the orthographic projection matrix to this canvas' dimensions Matrix ortho = Matrix::ortho(0.0f, width, height, 0.0f); ctx->projectionStack.push(ortho); // indicate we are using this fbo current = this; }
void Renderer::renderSSAO() { if (!m_shaderSSAOcalc || !m_shaderSSAOblur || !m_shaderSSAOfinal) init(m_windowWidth, m_windowHeight); FBO *a = new FBO(m_windowWidth, m_windowHeight, 3, false, false); FBO *b = new FBO(m_windowWidth, m_windowHeight, 3, false, false); a->bind(); glClearColor(1, 1, 1, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shaderSSAOcalc->bind(); m_shaderSSAOcalc->sendSampler2D("positionMap", m_gBuffer->getColorTexture(0), 0); m_shaderSSAOcalc->sendSampler2D("normalMap", m_gBuffer->getColorTexture(1), 1); m_shaderSSAOcalc->sendMat4("sceneProjectionMatrix", m_currentProjectionMatrix); m_shaderSSAOcalc->sendFloat("radius", *m_ssaoRadius); m_shaderSSAOcalc->sendFloat("quality", *m_ssaoQuality); m_sfq.renderGeometry(); m_shaderSSAOcalc->unbind(); a->unbind(); //Blur #1 SSAO calculation b->bind(); //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shaderSSAOblur->bind(); m_shaderSSAOblur->sendSampler2D("colortexture", a->getColorTexture(2), 0); m_shaderSSAOblur->sendInt("secondPass", 0); m_sfq.renderGeometry(); m_shaderSSAOblur->unbind(); b->unbind(); //Blur #2 SSAO calculation a->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shaderSSAOblur->bind(); m_shaderSSAOblur->sendSampler2D("colortexture", b->getColorTexture(2), 0); m_shaderSSAOblur->sendFloat("secondPass", 1); m_sfq.renderGeometry(); m_shaderSSAOblur->unbind(); a->unbind(); glClearColor(0, 0, 0, 0); //COLOR COMPOSITING bindFBO(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_shaderSSAOfinal->bind(); m_shaderSSAOfinal->sendSampler2D("colorMap", getLastFBO()->getColorTexture(2), 0); m_shaderSSAOfinal->sendSampler2D("ssaoMap", a->getColorTexture(2), 1); m_sfq.renderGeometry(); m_shaderSSAOfinal->unbind(); unbindFBO(); delete a; delete b; }
///@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_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); }
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); }