No depth value write to frame buffer object in qtopenglwidget.

I have followed this example to bridge Opencascade and QOpenGLWidget. A small difference is that I made some changes to the OpenGl_FrameBufferand used my own FBO (built around QOpenGLFrameBuffer).

Because the purpose is to interop with native OpenGL stuff, the depth value is essential to mix different scenes (my own and opencascade). However, as shown below, the FBO from a box (built as below) in opencascade does not have depth values, all of them are 1 (white values). But the colors are correct.

        TopoDS_Shape aBox = BRepPrimAPI_MakeBox(box.CornerMin(), box.CornerMax()).Shape();
        occt_bounds_ = new AIS_Shape(aBox);
        occt_context_->Display(occt_bounds_, AIS_Shaded, 0, false);

The point clouds are bounded by the box, so they should be occluded as the figure.

How can I enable the writing of depth values for AIS_InteractiveObject? Thanks.

Kirill Gavrilov's picture

TKOpenGl is a multi-pass renderer that clears Depth buffer multiple times. To incorporate other 3D renderer you should perform custom rendering by subclassing OpenGl_Element or OpenGl_View classes (also refered as "UserDraw" in OCCT documentation).

Han Hu's picture

Seems much more complicated than V3d_View. Currently, because my occt scene is relatively lightweight (similar polygon and bounding box primitives as this tool), I have found a workaround by setting all the AIS_InteractiveObject to Graphic3d_ZLayerId_Topmost and this z layer has depth recorded in my fbo (the same as AIS_ViewCube).

Maybe when I am more familiar with occt, I will refactor the rendering pipelines.

Han Hu's picture

I have found a relatively perfect walkaround for this issue. I have created two FBOs to record color and depths independently. I draw the scene first normally using all the default settings. In this way, I get a perfect color texture from occt. Then I set the clear depth property of the TopMost z layer to false and use raytracing render mode, in this way I get a perfect depth texture from occt. Finally, I use a passthrough shader to combine my own FBO and the two FBOs. The code structure is like the below.

{
        fbo_occt_color_->bind();
        occt_view_->ChangeRenderingParams().Method = Graphic3d_RM_RASTERIZATION;
        Graphic3d_ZLayerSettings settings = occt_viewer_->ZLayerSettings(Graphic3d_ZLayerId_Topmost);
        settings.SetClearDepth(true);
        occt_viewer_->SetZLayerSettings(Graphic3d_ZLayerId_Topmost, settings);

        // wrap FBO created by QOpenGLWidget
        Handle(OpenGl_GraphicDriver) driver =
            Handle(OpenGl_GraphicDriver)::DownCast(occt_context_->CurrentViewer()->Driver());
        const Handle(OpenGl_Context) &glctx = driver->GetSharedContext();
        Handle(OpenGl_FrameBuffer) default_fbo = glctx->DefaultFrameBuffer();
        CHECK(!default_fbo.IsNull());

        if (!default_fbo->InitWrapper(glctx)) {
            default_fbo.Nullify();
            Message::DefaultMessenger()->Send("Default FBO wrapper creation failed", Message_Fail);
            QMessageBox::critical(0, "Failure", "Default FBO wrapper creation failed");
            QApplication::exit(1);
            return;
        }

        // flush pending input events and redraw the viewer
        FlushViewEvents(occt_context_, occt_view_, true);
        fbo_occt_color_->release();
    }
    {
        fbo_occt_depth_->bind();
        // ray tracing will record depth in most scenarios
        occt_view_->ChangeRenderingParams().Method = Graphic3d_RM_RAYTRACING;
        Graphic3d_ZLayerSettings settings = occt_viewer_->ZLayerSettings(Graphic3d_ZLayerId_Topmost);
        settings.SetClearDepth(false); // to preserve depth
        occt_viewer_->SetZLayerSettings(Graphic3d_ZLayerId_Topmost, settings);

        // wrap FBO created by QOpenGLWidget
        Handle(OpenGl_GraphicDriver) driver =
            Handle(OpenGl_GraphicDriver)::DownCast(occt_context_->CurrentViewer()->Driver());
        const Handle(OpenGl_Context) &glctx = driver->GetSharedContext();
        Handle(OpenGl_FrameBuffer) default_fbo = glctx->DefaultFrameBuffer();
        CHECK(!default_fbo.IsNull());

        if (!default_fbo->InitWrapper(glctx)) {
            default_fbo.Nullify();
            Message::DefaultMessenger()->Send("Default FBO wrapper creation failed", Message_Fail);
            QMessageBox::critical(0, "Failure", "Default FBO wrapper creation failed");
            QApplication::exit(1);
            return;
        }

        // Redraw will get depth
        occt_view_->Redraw();
        fbo_occt_depth_->release();
    }