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);
}
Exemple #2
0
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();
    }
}
Exemple #3
0
    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;
}
Exemple #5
0
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);
}
Exemple #9
0
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;
}
Exemple #10
0
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
}
Exemple #11
0
//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
}
Exemple #13
0
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);
    }
}