void tst_QOpenGL::fboHandleNulledAfterContextDestroyed() { QWindow window; window.setSurfaceType(QWindow::OpenGLSurface); window.setGeometry(0, 0, 10, 10); window.create(); QOpenGLFramebufferObject *fbo = 0; { QOpenGLContext ctx; ctx.create(); ctx.makeCurrent(&window); if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QOpenGLFramebufferObject not supported on this platform"); fbo = new QOpenGLFramebufferObject(128, 128); QVERIFY(fbo->handle() != 0); } QCOMPARE(fbo->handle(), 0U); }
void QtVLCWidget::paintGL() { QOpenGLFramebufferObject *fbo = mVLC->getVideoFrame(); if (fbo != NULL) { m_program->bind(); glClearColor(1.0, 0.5, 0.0, 1.0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, fbo->takeTexture()); vertexBuffer.bind(); m_program->setAttributeArray("position", (const QVector2D *)nullptr, sizeof(GLfloat)*2); //vertexBuffer.release(); m_program->enableAttributeArray("position"); vertexIndexBuffer.bind(); glDrawElements( GL_TRIANGLE_STRIP, /* mode */ 4, /* count */ GL_UNSIGNED_SHORT, /* type */ (void*)0 /* element array buffer offset */ ); //vertexIndexBuffer.release(); m_program->disableAttributeArray("position"); //m_program->release(); } }
void render() { obj->window()->resetOpenGLState(); QOpenGLFramebufferObject *fbo = framebufferObject(); mpv_opengl_fbo mpfbo{.fbo = static_cast<int>(fbo->handle()), .w = fbo->width(), .h = fbo->height(), .internal_format = 0}; int flip_y{0}; mpv_render_param params[] = { // Specify the default framebuffer (0) as target. This will // render onto the entire screen. If you want to show the video // in a smaller rectangle or apply fancy transformations, you'll // need to render into a separate FBO and draw it manually. {MPV_RENDER_PARAM_OPENGL_FBO, &mpfbo}, // Flip rendering (needed due to flipped GL coordinate system). {MPV_RENDER_PARAM_FLIP_Y, &flip_y}, {MPV_RENDER_PARAM_INVALID, nullptr} }; // See render_gl.h on what OpenGL environment mpv expects, and // other API details. mpv_render_context_render(obj->mpv_gl, params); obj->window()->resetOpenGLState(); } };
void tst_QOpenGL::fboSimpleRendering() { QFETCH(int, surfaceClass); QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext ctx; ctx.create(); ctx.makeCurrent(surface.data()); if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QOpenGLFramebufferObject not supported on this platform"); // No multisample with combined depth/stencil attachment: QOpenGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QOpenGLFramebufferObject::NoAttachment); QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(200, 100, fboFormat); fbo->bind(); glClearColor(1.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glFinish(); QImage fb = fbo->toImage().convertToFormat(QImage::Format_RGB32); QImage reference(fb.size(), QImage::Format_RGB32); reference.fill(0xffff0000); QFUZZY_COMPARE_IMAGES(fb, reference); delete fbo; }
QOpenGLFramebufferObject* TextureCache::createFramebufferObject() { QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size()); Application::getInstance()->getGLWidget()->installEventFilter(this); glBindTexture(GL_TEXTURE_2D, fbo->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); return fbo; }
QOpenGLFramebufferObject* FboCache::getReadyFbo() { QOpenGLFramebufferObject* result = nullptr; withLock(_lock, [&] { // Delete any FBOs queued for deletion _destroyFboQueue.clear(); if (_readyFboQueue.empty()) { qDebug() << "Building new offscreen FBO number " << _fboMap.size() + 1; result = new QOpenGLFramebufferObject(_size, QOpenGLFramebufferObject::CombinedDepthStencil); _fboMap[result->texture()] = QSharedPointer<QOpenGLFramebufferObject>(result); _readyFboQueue.push_back(result); } else { result = _readyFboQueue.front(); } }); return result; }
void tst_QOpenGL::fboTextureOwnership() { QFETCH(int, surfaceClass); QScopedPointer<QSurface> surface(createSurface(surfaceClass)); QOpenGLContext ctx; QVERIFY(ctx.create()); ctx.makeCurrent(surface.data()); if (!QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QOpenGLFramebufferObject not supported on this platform"); QOpenGLFramebufferObjectFormat fboFormat; fboFormat.setAttachment(QOpenGLFramebufferObject::NoAttachment); QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(200, 100, fboFormat); QVERIFY(fbo->texture() != 0); fbo->bind(); // pull out the texture GLuint texture = fbo->takeTexture(); QVERIFY(texture != 0); QVERIFY(fbo->texture() == 0); // verify that the next bind() creates a new texture fbo->bind(); QVERIFY(fbo->texture() != 0 && fbo->texture() != texture); glClearColor(1.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glFinish(); QImage fb = fbo->toImage().convertToFormat(QImage::Format_RGB32); QImage reference(fb.size(), QImage::Format_RGB32); reference.fill(0xffff0000); QFUZZY_COMPARE_IMAGES(fb, reference); glDeleteTextures(1, &texture); delete fbo; }
void AmbientOcclusionEffect::render() { glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID()); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, _rotationTextureID); // render with the occlusion shader to the secondary/tertiary buffer QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject(); freeFBO->bind(); float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; Application::getInstance()->getViewFrustum()->computeOffAxisFrustum( left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); _occlusionProgram->bind(); _occlusionProgram->setUniformValue(_nearLocation, nearVal); _occlusionProgram->setUniformValue(_farLocation, farVal); _occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom); _occlusionProgram->setUniformValue(_rightTopLocation, right, top); QSize widgetSize = Application::getInstance()->getGLWidget()->size(); _occlusionProgram->setUniformValue(_noiseScaleLocation, widgetSize.width() / (float)ROTATION_WIDTH, widgetSize.height() / (float)ROTATION_HEIGHT); int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); const int VIEWPORT_X_INDEX = 0; const int VIEWPORT_WIDTH_INDEX = 2; float sMin = viewport[VIEWPORT_X_INDEX] / (float)widgetSize.width(); float sMax = (viewport[VIEWPORT_X_INDEX] + viewport[VIEWPORT_WIDTH_INDEX]) / (float)widgetSize.width(); renderFullscreenQuad(sMin, sMax); _occlusionProgram->release(); freeFBO->release(); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); // now render secondary to primary with 4x4 blur Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); glEnable(GL_BLEND); glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE); glBindTexture(GL_TEXTURE_2D, freeFBO->texture()); _blurProgram->bind(); _blurProgram->setUniformValue(_blurScaleLocation, 1.0f / widgetSize.width(), 1.0f / widgetSize.height()); renderFullscreenQuad(sMin, sMax); _blurProgram->release(); glBindTexture(GL_TEXTURE_2D, 0); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); }
QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); primaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); QOpenGLFramebufferObject* destFBO = toTexture ? Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject() : NULL; if (_isEmpty && _renderMode != DIFFUSE_ADD_MODE) { // copy the primary to the screen if (QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO); } else { maybeBind(destFBO); glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glColor3f(1.0f, 1.0f, 1.0f); renderFullscreenQuad(); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); maybeRelease(destFBO); } } else if (_renderMode == ADD_MODE) { maybeBind(destFBO); _addProgram->bind(); renderFullscreenQuad(); _addProgram->release(); maybeRelease(destFBO); } else if (_renderMode == DIFFUSE_ADD_MODE) { // diffuse into the secondary/tertiary (alternating between frames) QOpenGLFramebufferObject* oldDiffusedFBO = Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject(); QOpenGLFramebufferObject* newDiffusedFBO = Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject(); if (_isOddFrame) { qSwap(oldDiffusedFBO, newDiffusedFBO); } newDiffusedFBO->bind(); if (_isFirstFrame) { glClear(GL_COLOR_BUFFER_BIT); } else { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, oldDiffusedFBO->texture()); _diffuseProgram->bind(); QSize size = Application::getInstance()->getGLWidget()->size(); _diffuseProgram->setUniformValue(_diffusionScaleLocation, 1.0f / size.width(), 1.0f / size.height()); renderFullscreenQuad(); _diffuseProgram->release(); } newDiffusedFBO->release(); // add diffused texture to the primary glBindTexture(GL_TEXTURE_2D, newDiffusedFBO->texture()); if (toTexture) { destFBO = oldDiffusedFBO; } maybeBind(destFBO); _addSeparateProgram->bind(); renderFullscreenQuad(); _addSeparateProgram->release(); maybeRelease(destFBO); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); } else { // _renderMode == BLUR_ADD_MODE || _renderMode == BLUR_PERSIST_ADD_MODE // render the primary to the secondary with the horizontal blur QOpenGLFramebufferObject* secondaryFBO = Application::getInstance()->getTextureCache()->getSecondaryFramebufferObject(); secondaryFBO->bind(); _horizontalBlurProgram->bind(); renderFullscreenQuad(); _horizontalBlurProgram->release(); secondaryFBO->release(); if (_renderMode == BLUR_ADD_MODE) { // render the secondary to the screen with the vertical blur glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture()); if (toTexture) { destFBO = Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject(); } maybeBind(destFBO); _verticalBlurAddProgram->bind(); renderFullscreenQuad(); _verticalBlurAddProgram->release(); maybeRelease(destFBO); } else { // _renderMode == BLUR_PERSIST_ADD_MODE // render the secondary to the tertiary with vertical blur and persistence QOpenGLFramebufferObject* tertiaryFBO = Application::getInstance()->getTextureCache()->getTertiaryFramebufferObject(); tertiaryFBO->bind(); glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_CONSTANT_ALPHA, GL_CONSTANT_ALPHA); const float PERSISTENCE_SMOOTHING = 0.9f; glBlendColor(0.0f, 0.0f, 0.0f, _isFirstFrame ? 0.0f : PERSISTENCE_SMOOTHING); glBindTexture(GL_TEXTURE_2D, secondaryFBO->texture()); _verticalBlurProgram->bind(); renderFullscreenQuad(); _verticalBlurProgram->release(); glBlendColor(0.0f, 0.0f, 0.0f, 0.0f); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glDisable(GL_BLEND); // now add the tertiary to the primary buffer tertiaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, tertiaryFBO->texture()); maybeBind(destFBO); _addSeparateProgram->bind(); renderFullscreenQuad(); _addSeparateProgram->release(); maybeRelease(destFBO); } glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); } glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glEnable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glBindTexture(GL_TEXTURE_2D, 0); _isFirstFrame = false; return destFBO; }
void OculusManager::display(Camera& whichCamera) { #ifdef HAVE_LIBOVR ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay(); // We only need to render the overlays to a texture once, then we just render the texture as a quad // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() applicationOverlay.renderOverlay(true); const bool displayOverlays = false; Application::getInstance()->getGlowEffect()->prepare(); // render the left eye view to the left side of the screen const StereoEyeParams& leftEyeParams = _stereoConfig.GetEyeRenderParams(StereoEye_Left); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glTranslatef(_stereoConfig.GetProjectionCenterOffset(), 0, 0); gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(), whichCamera.getNearClip(), whichCamera.getFarClip()); glViewport(leftEyeParams.VP.x, leftEyeParams.VP.y, leftEyeParams.VP.w, leftEyeParams.VP.h); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glTranslatef(_stereoConfig.GetIPD() * 0.5f, 0, 0); Application::getInstance()->displaySide(whichCamera); if (displayOverlays) { applicationOverlay.displayOverlayTextureOculus(whichCamera); } // and the right eye to the right side const StereoEyeParams& rightEyeParams = _stereoConfig.GetEyeRenderParams(StereoEye_Right); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glTranslatef(-_stereoConfig.GetProjectionCenterOffset(), 0, 0); gluPerspective(whichCamera.getFieldOfView(), whichCamera.getAspectRatio(), whichCamera.getNearClip(), whichCamera.getFarClip()); glViewport(rightEyeParams.VP.x, rightEyeParams.VP.y, rightEyeParams.VP.w, rightEyeParams.VP.h); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(_stereoConfig.GetIPD() * -0.5f, 0, 0); Application::getInstance()->displaySide(whichCamera); if (displayOverlays) { applicationOverlay.displayOverlayTextureOculus(whichCamera); } glPopMatrix(); // restore our normal viewport const Viewport& fullViewport = _stereoConfig.GetFullViewport(); glViewport(fullViewport.x, fullViewport.y, fullViewport.w, fullViewport.h); QOpenGLFramebufferObject* fbo = Application::getInstance()->getGlowEffect()->render(true); glBindTexture(GL_TEXTURE_2D, fbo->texture()); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(fullViewport.x, fullViewport.x + fullViewport.w, fullViewport.y, fullViewport.y + fullViewport.h); glDisable(GL_DEPTH_TEST); // for reference on setting these values, see SDK file Samples/OculusRoomTiny/RenderTiny_Device.cpp float scaleFactor = 1.0 / _stereoConfig.GetDistortionScale(); float aspectRatio = _stereoConfig.GetAspect(); glDisable(GL_BLEND); _program.bind(); _program.setUniformValue(_textureLocation, 0); const DistortionConfig& distortionConfig = _stereoConfig.GetDistortionConfig(); _program.setUniformValue(_lensCenterLocation, (0.5 + distortionConfig.XCenterOffset * 0.5) * 0.5, 0.5); _program.setUniformValue(_screenCenterLocation, 0.25, 0.5); _program.setUniformValue(_scaleLocation, 0.25 * scaleFactor, 0.5 * scaleFactor * aspectRatio); _program.setUniformValue(_scaleInLocation, 4, 2 / aspectRatio); _program.setUniformValue(_hmdWarpParamLocation, distortionConfig.K[0], distortionConfig.K[1], distortionConfig.K[2], distortionConfig.K[3]); glColor3f(1, 0, 1); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(0.5, 0); glVertex2f(leftEyeParams.VP.w, 0); glTexCoord2f(0.5, 1); glVertex2f(leftEyeParams.VP.w, leftEyeParams.VP.h); glTexCoord2f(0, 1); glVertex2f(0, leftEyeParams.VP.h); glEnd(); _program.setUniformValue(_lensCenterLocation, 0.5 + (0.5 - distortionConfig.XCenterOffset * 0.5) * 0.5, 0.5); _program.setUniformValue(_screenCenterLocation, 0.75, 0.5); glBegin(GL_QUADS); glTexCoord2f(0.5, 0); glVertex2f(leftEyeParams.VP.w, 0); glTexCoord2f(1, 0); glVertex2f(fullViewport.w, 0); glTexCoord2f(1, 1); glVertex2f(fullViewport.w, leftEyeParams.VP.h); glTexCoord2f(0.5, 1); glVertex2f(leftEyeParams.VP.w, leftEyeParams.VP.h); glEnd(); glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, 0); _program.release(); glPopMatrix(); #endif }
//Displays everything for the oculus, frame timing must be active void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera) { #ifdef HAVE_LIBOVR //beginFrameTiming must be called before display if (!_frameTimingActive) { printf("WARNING: Called OculusManager::display() without calling OculusManager::beginFrameTiming() first."); return; } ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay(); // We only need to render the overlays to a texture once, then we just render the texture on the hemisphere // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() applicationOverlay.renderOverlay(true); //Bind our framebuffer object. If we are rendering the glow effect, we let the glow effect shader take care of it if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { Application::getInstance()->getGlowEffect()->prepare(); } else { Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } ovrPosef eyeRenderPose[ovrEye_Count]; glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glm::quat orientation; glm::vec3 trackerPosition; #if defined(__APPLE__) || defined(_WIN32) ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds()); ovrVector3f ovrHeadPosition = ts.HeadPose.ThePose.Position; trackerPosition = glm::vec3(ovrHeadPosition.x, ovrHeadPosition.y, ovrHeadPosition.z); if (_calibrationState != CALIBRATED) { ovrQuatf ovrHeadOrientation = ts.HeadPose.ThePose.Orientation; orientation = glm::quat(ovrHeadOrientation.w, ovrHeadOrientation.x, ovrHeadOrientation.y, ovrHeadOrientation.z); calibrate(trackerPosition, orientation); } trackerPosition = bodyOrientation * trackerPosition; #endif //Render each eye into an fbo for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { _activeEyeIndex = eyeIndex; #if defined(__APPLE__) || defined(_WIN32) ovrEyeType eye = _ovrHmd->EyeRenderOrder[eyeIndex]; #else ovrEyeType eye = _ovrHmdDesc.EyeRenderOrder[eyeIndex]; #endif // Set the camera rotation for this eye eyeRenderPose[eye] = ovrHmd_GetEyePose(_ovrHmd, eye); orientation.x = eyeRenderPose[eye].Orientation.x; orientation.y = eyeRenderPose[eye].Orientation.y; orientation.z = eyeRenderPose[eye].Orientation.z; orientation.w = eyeRenderPose[eye].Orientation.w; // Update the application camera with the latest HMD position whichCamera.setHmdPosition(trackerPosition); whichCamera.setHmdRotation(orientation); // Update our camera to what the application camera is doing _camera->setRotation(whichCamera.getRotation()); _camera->setPosition(whichCamera.getPosition()); // Store the latest left and right eye render locations for things that need to know glm::vec3 thisEyePosition = position + trackerPosition + (bodyOrientation * glm::quat(orientation.x, orientation.y, orientation.z, orientation.w) * glm::vec3(_eyeRenderDesc[eye].ViewAdjust.x, _eyeRenderDesc[eye].ViewAdjust.y, _eyeRenderDesc[eye].ViewAdjust.z)); if (eyeIndex == 0) { _leftEyePosition = thisEyePosition; } else { _rightEyePosition = thisEyePosition; } _camera->update(1.0f / Application::getInstance()->getFps()); Matrix4f proj = ovrMatrix4f_Projection(_eyeRenderDesc[eye].Fov, whichCamera.getNearClip(), whichCamera.getFarClip(), true); proj.Transpose(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glLoadMatrixf((GLfloat *)proj.M); glViewport(_eyeRenderViewport[eye].Pos.x, _eyeRenderViewport[eye].Pos.y, _eyeRenderViewport[eye].Size.w, _eyeRenderViewport[eye].Size.h); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(_eyeRenderDesc[eye].ViewAdjust.x, _eyeRenderDesc[eye].ViewAdjust.y, _eyeRenderDesc[eye].ViewAdjust.z); Application::getInstance()->displaySide(*_camera); applicationOverlay.displayOverlayTextureOculus(*_camera); _activeEyeIndex = -1; } //Wait till time-warp to reduce latency ovr_WaitTillTime(_hmdFrameTiming.TimewarpPointSeconds); glPopMatrix(); //Full texture viewport for glow effect glViewport(0, 0, _renderTargetSize.w, _renderTargetSize.h); //Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { QOpenGLFramebufferObject* fbo = Application::getInstance()->getGlowEffect()->render(true); glBindTexture(GL_TEXTURE_2D, fbo->texture()); } else { Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->release(); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->texture()); } // restore our normal viewport glViewport(0, 0, Application::getInstance()->getGLWidget()->getDeviceWidth(), Application::getInstance()->getGLWidget()->getDeviceHeight()); glMatrixMode(GL_PROJECTION); glPopMatrix(); //Renders the distorted mesh onto the screen renderDistortionMesh(eyeRenderPose); glBindTexture(GL_TEXTURE_2D, 0); #endif }
//Displays everything for the oculus, frame timing must be active void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &position, Camera& whichCamera) { #ifdef HAVE_LIBOVR //beginFrameTiming must be called before display if (!_frameTimingActive) { printf("WARNING: Called OculusManager::display() without calling OculusManager::beginFrameTiming() first."); return; } ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay(); // We only need to render the overlays to a texture once, then we just render the texture on the hemisphere // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() applicationOverlay.renderOverlay(true); //Bind our framebuffer object. If we are rendering the glow effect, we let the glow effect shader take care of it if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { Application::getInstance()->getGlowEffect()->prepare(); } else { Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } ovrPosef eyeRenderPose[ovrEye_Count]; _camera->setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay _camera->setDistance(0.0f); _camera->setUpShift(0.0f); glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glm::quat orientation; //Render each eye into an fbo for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) { ovrEyeType eye = _ovrHmdDesc.EyeRenderOrder[eyeIndex]; //Set the camera rotation for this eye eyeRenderPose[eye] = ovrHmd_GetEyePose(_ovrHmd, eye); orientation.x = eyeRenderPose[eye].Orientation.x; orientation.y = eyeRenderPose[eye].Orientation.y; orientation.z = eyeRenderPose[eye].Orientation.z; orientation.w = eyeRenderPose[eye].Orientation.w; _camera->setTargetRotation(bodyOrientation * orientation); _camera->setTargetPosition(position); _camera->update(1.0f / Application::getInstance()->getFps()); Matrix4f proj = ovrMatrix4f_Projection(_eyeRenderDesc[eye].Fov, whichCamera.getNearClip(), whichCamera.getFarClip(), true); proj.Transpose(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glLoadMatrixf((GLfloat *)proj.M); glViewport(_eyeRenderViewport[eye].Pos.x, _eyeRenderViewport[eye].Pos.y, _eyeRenderViewport[eye].Size.w, _eyeRenderViewport[eye].Size.h); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(_eyeRenderDesc[eye].ViewAdjust.x, _eyeRenderDesc[eye].ViewAdjust.y, _eyeRenderDesc[eye].ViewAdjust.z); Application::getInstance()->displaySide(*_camera); applicationOverlay.displayOverlayTextureOculus(*_camera); } //Wait till time-warp to reduce latency ovr_WaitTillTime(_hmdFrameTiming.TimewarpPointSeconds); glPopMatrix(); //Full texture viewport for glow effect glViewport(0, 0, _renderTargetSize.w, _renderTargetSize.h); //Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { QOpenGLFramebufferObject* fbo = Application::getInstance()->getGlowEffect()->render(true); glBindTexture(GL_TEXTURE_2D, fbo->texture()); } else { Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->release(); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject()->texture()); } // restore our normal viewport glViewport(0, 0, Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height()); glMatrixMode(GL_PROJECTION); glPopMatrix(); //Renders the distorted mesh onto the screen renderDistortionMesh(eyeRenderPose); glBindTexture(GL_TEXTURE_2D, 0); #endif }
QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { PerformanceTimer perfTimer("glowEffect"); TextureCache* textureCache = DependencyManager::get<TextureCache>(); QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); primaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); QOpenGLFramebufferObject* destFBO = toTexture ? textureCache->getSecondaryFramebufferObject() : NULL; if (!Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect) || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO); } else { maybeBind(destFBO); if (!destFBO) { glViewport(0, 0, Application::getInstance()->getGLWidget()->getDeviceWidth(), Application::getInstance()->getGLWidget()->getDeviceHeight()); } glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glColor3f(1.0f, 1.0f, 1.0f); renderFullscreenQuad(); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); maybeRelease(destFBO); } } else { // diffuse into the secondary/tertiary (alternating between frames) QOpenGLFramebufferObject* oldDiffusedFBO = textureCache->getSecondaryFramebufferObject(); QOpenGLFramebufferObject* newDiffusedFBO = textureCache->getTertiaryFramebufferObject(); if (_isOddFrame) { qSwap(oldDiffusedFBO, newDiffusedFBO); } newDiffusedFBO->bind(); if (_isFirstFrame) { glClear(GL_COLOR_BUFFER_BIT); } else { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, oldDiffusedFBO->texture()); _diffuseProgram->bind(); QSize size = primaryFBO->size(); _diffuseProgram->setUniformValue(_diffusionScaleLocation, 1.0f / size.width(), 1.0f / size.height()); renderFullscreenQuad(); _diffuseProgram->release(); } newDiffusedFBO->release(); // add diffused texture to the primary glBindTexture(GL_TEXTURE_2D, newDiffusedFBO->texture()); if (toTexture) { destFBO = oldDiffusedFBO; } maybeBind(destFBO); if (!destFBO) { glViewport(0, 0, Application::getInstance()->getGLWidget()->getDeviceWidth(), Application::getInstance()->getGLWidget()->getDeviceHeight()); } _addSeparateProgram->bind(); renderFullscreenQuad(); _addSeparateProgram->release(); maybeRelease(destFBO); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); } glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glEnable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glBindTexture(GL_TEXTURE_2D, 0); _isFirstFrame = false; return destFBO; }
void DeferredLightingEffect::render() { // perform deferred lighting, rendering to free fbo glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glDisable(GL_BLEND); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDisable(GL_COLOR_MATERIAL); glDepthMask(false); QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject(); primaryFBO->release(); QOpenGLFramebufferObject* freeFBO = Application::getInstance()->getGlowEffect()->getFreeFramebufferObject(); freeFBO->bind(); glClear(GL_COLOR_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryNormalTextureID()); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimarySpecularTextureID()); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getPrimaryDepthTextureID()); // get the viewport side (left, right, both) int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); const int VIEWPORT_X_INDEX = 0; const int VIEWPORT_Y_INDEX = 1; const int VIEWPORT_WIDTH_INDEX = 2; const int VIEWPORT_HEIGHT_INDEX = 3; float sMin = viewport[VIEWPORT_X_INDEX] / (float)primaryFBO->width(); float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)primaryFBO->width(); float tMin = viewport[VIEWPORT_Y_INDEX] / (float)primaryFBO->height(); float tHeight = viewport[VIEWPORT_HEIGHT_INDEX] / (float)primaryFBO->height(); ProgramObject* program = &_directionalLight; const LightLocations* locations = &_directionalLightLocations; bool shadowsEnabled = Menu::getInstance()->getShadowsEnabled(); if (shadowsEnabled) { glActiveTexture(GL_TEXTURE4); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); program = &_directionalLightShadowMap; locations = &_directionalLightShadowMapLocations; if (Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows)) { program = &_directionalLightCascadedShadowMap; locations = &_directionalLightCascadedShadowMapLocations; _directionalLightCascadedShadowMap.bind(); _directionalLightCascadedShadowMap.setUniform(locations->shadowDistances, Application::getInstance()->getShadowDistances()); } else { program->bind(); } program->setUniformValue(locations->shadowScale, 1.0f / Application::getInstance()->getTextureCache()->getShadowFramebufferObject()->width()); } else { program->bind(); } float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; Application::getInstance()->computeOffAxisFrustum( left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); program->setUniformValue(locations->nearLocation, nearVal); float depthScale = (farVal - nearVal) / farVal; program->setUniformValue(locations->depthScale, depthScale); float nearScale = -1.0f / nearVal; float depthTexCoordScaleS = (right - left) * nearScale / sWidth; float depthTexCoordScaleT = (top - bottom) * nearScale / tHeight; float depthTexCoordOffsetS = left * nearScale - sMin * depthTexCoordScaleS; float depthTexCoordOffsetT = bottom * nearScale - tMin * depthTexCoordScaleT; program->setUniformValue(locations->depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); program->setUniformValue(locations->depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); renderFullscreenQuad(sMin, sMin + sWidth, tMin, tMin + tHeight); program->release(); if (shadowsEnabled) { glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE3); } // additive blending glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_CULL_FACE); glm::vec4 sCoefficients(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f); glm::vec4 tCoefficients(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f); glTexGenfv(GL_S, GL_OBJECT_PLANE, (const GLfloat*)&sCoefficients); glTexGenfv(GL_T, GL_OBJECT_PLANE, (const GLfloat*)&tCoefficients); // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft()); if (!_pointLights.isEmpty()) { _pointLight.bind(); _pointLight.setUniformValue(_pointLightLocations.nearLocation, nearVal); _pointLight.setUniformValue(_pointLightLocations.depthScale, depthScale); _pointLight.setUniformValue(_pointLightLocations.depthTexCoordOffset, depthTexCoordOffsetS, depthTexCoordOffsetT); _pointLight.setUniformValue(_pointLightLocations.depthTexCoordScale, depthTexCoordScaleS, depthTexCoordScaleT); foreach (const PointLight& light, _pointLights) { _pointLight.setUniformValue(_pointLightLocations.radius, light.radius); glLightfv(GL_LIGHT1, GL_AMBIENT, (const GLfloat*)&light.ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular); glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position); glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.0f ? light.constantAttenuation : 0.0f)); glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.0f ? light.linearAttenuation : 0.0f)); glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.0f ? light.quadraticAttenuation : 0.0f)); glPushMatrix(); float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION); if (glm::distance(eyePoint, glm::vec3(light.position)) < expandedRadius + nearRadius) { glLoadIdentity(); glTranslatef(0.0f, 0.0f, -1.0f); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); renderFullscreenQuad(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } else { glTranslatef(light.position.x, light.position.y, light.position.z); Application::getInstance()->getGeometryCache()->renderSphere(expandedRadius, 32, 32); } glPopMatrix(); }
void PerspectiveView::glPass(GLResourceContext &ctx) { glEnable(GL_DEPTH_TEST); QMatrix4x4 cameraProjM = _camera->getProjMatrix(width(), height()); QMatrix4x4 cameraViewM = _camera->getViewMatrix(width(), height()); QMatrix4x4 cameraProjViewM = cameraProjM * cameraViewM; QMatrix4x4 objToWorld; Scene* scene = Scene::activeScene(); // render each mesh QHashIterator<QString,Mesh*> meshes = scene->meshes(); while (meshes.hasNext()) { meshes.next(); Mesh* mesh = meshes.value(); // make sure a texture exists for this mesh if (!hasMeshTexture(mesh)) { std::cout << "creating mesh texture" << std::endl; QOpenGLFramebufferObject* transferFbo = ctx.transferFbo(); transferFbo->bind(); GLuint textureId; glGenTextures(1, &textureId); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureId); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glClearColor(.5,.5,.5,1); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,1,0,1,-1,1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glViewport(0, 0, 256, 256); glColor3f(.8,.8,.8); glBegin(GL_QUADS); { glVertex2f(.25,.25); glVertex2f(.75,.25); glVertex2f(.75,.75); glVertex2f(.25,.75); } glEnd(); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 256, 256, 0); transferFbo->release(); //glActiveTexture(GL_TEXTURE0); //QImage img("/tmp/lena.jpg"); //QImage image = QGLWidget::convertToGLFormat(img); //glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0 , image.width(), image.height(), GL_RGB, GL_UNSIGNED_BYTE, image.bits() ); glViewport(0, 0, width(), height()); setMeshTexture(mesh, textureId); } QOpenGLFramebufferObject* paintFbo = ctx.paintFbo(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, meshTexture(mesh)); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, paintFbo->texture()); glActiveTexture(GL_TEXTURE0); QGLShaderProgram* meshShader = ctx.meshShader(); meshShader->bind(); meshShader->setUniformValue("objToWorld", objToWorld); meshShader->setUniformValue("cameraPV", cameraProjViewM); meshShader->setUniformValue("paintFboWidth", PAINT_FBO_WIDTH); meshShader->setUniformValue("brushColor", _brushColor.redF(), _brushColor.greenF(), _brushColor.blueF(), 1); meshShader->setUniformValue("meshTexture", 0); meshShader->setUniformValue("paintTexture", 1); renderMesh(mesh); meshShader->release(); } glMatrixMode(GL_PROJECTION); glLoadIdentity(); glLoadMatrixf(cameraProjM.data()); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadMatrixf(cameraViewM.data()); glBegin(GL_LINES); for (int i = -10; i <= 10; i++) { glVertex3f(-10, 0, i); glVertex3f(10, 0, i); } glEnd(); glDisable(GL_DEPTH_TEST); drawPaintStrokes(ctx); if (_bakePaintLayer) { bakePaintLayer(ctx); } }