4

I am trying to use layer filtering as shown in this answer. For this I wrote a simple test (see below). This is a continuation of the question.

At a certain position of the red sphere, an artifact appears, which looks like display from the another camera in coordinates (0.0, 0.0, 0.0).

See screen: enter image description here

In my example, the red sphere can be moved with the WSAD buttons. See (-7, 0, -14) red sphere position. How to remove these artifacts? The full test project can be viewed here.

main.cpp

int main(int argc, char *argv[])
{
    QGuiApplication application(argc, argv);
        My3DWindow window;

        auto sphere1 = new Qt3DCore::QEntity(window.Scene());
        auto sphere2 = new Qt3DCore::QEntity(window.Scene());

        // material, transform, mesh initialisation

        sphere1->addComponent(material1);
        sphere1->addComponent(spheremesh1);
        sphere1->addComponent(transform1);
        sphere1->addComponent(window.OpaqueLayer());

        sphere2->addComponent(material2);
        sphere2->addComponent(spheremesh2);
        sphere2->addComponent(transform2);
        sphere2->addComponent(window.TransparentLayer());

        window.show();
        return application.exec();
    }

My3DWindow class:

My3DWindow::My3DWindow(QScreen *screen):
    Qt3DExtras::Qt3DWindow(screen)
{
    m_Scene = new Qt3DCore::QEntity;
    setRootEntity(m_Scene);

    auto renderSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector(m_Scene);
    renderSurfaceSelector->setSurface(this);
    auto clearBuffers = new Qt3DRender::QClearBuffers(renderSurfaceSelector);
    clearBuffers->setBuffers(Qt3DRender::QClearBuffers::AllBuffers);
    clearBuffers->setClearColor(Qt::gray);

    auto viewport = new Qt3DRender::QViewport(renderSurfaceSelector);
    auto cameraSelector = new Qt3DRender::QCameraSelector(viewport);

    m_Camera = new Qt3DRender::QCamera(cameraSelector);
    m_Camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
    m_Camera->setPosition(QVector3D(0.0f, 0.0f, 100.0f));
    m_Camera->setViewCenter(QVector3D(0.0f, 0.0f, 0.0f));

    cameraSelector->setCamera(m_Camera);

    auto cameraController = new Qt3DExtras::QFirstPersonCameraController(m_Scene);
    cameraController->setCamera(m_Camera);

    m_OpaqueLayer = new Qt3DRender::QLayer;
    auto opaqueFilter = new Qt3DRender::QLayerFilter(m_Camera);
    opaqueFilter->addLayer(m_OpaqueLayer);

    m_TransparentLayer = new Qt3DRender::QLayer;
    auto transparentFilter = new Qt3DRender::QLayerFilter(m_Camera);
    transparentFilter->addLayer(m_TransparentLayer);

    setActiveFrameGraph(renderSurfaceSelector);
}

avttrue
  • 387
  • 2
  • 12
  • I can't figure out if it's a bug or not. Created a [bugreport](https://bugreports.qt.io/browse/QTBUG-81009), let's see. – avttrue Dec 30 '19 at 13:35
  • Just a hint: you don't need to create a new camera and make it a child of `cameraSelector`. A `QCamera` is not a `QFrameGraphNode`, so it doesn't have to be part of the frame graph. You can use the default camera from your `Qt3DWindow`, and branch the filters directly from `cameraSelector`. – Urbano Lugrís Jul 11 '20 at 09:43

2 Answers2

3

You can fix that by adding a QNoDraw node as a child of clearBuffers, as shown in this answer. The "artifact" is not caused by the layer filters, it is a problem of QClearBuffers itself.

Making clearBuffers a child of cameraSelector may seem to work on the surface, but what's actually happening is that everything is being rendered twice, so the transparent sphere will appear darker. You can verify this by commenting out either one of the filters: the objects in the corresponding layer will get rendered anyway.

By leaving clearBuffers as a child of renderSurfaceSelector and adding the QNoDraw, you don't get undesired stuff drawn on top of your viewport, and the filters behave as expected.

Urbano Lugrís
  • 108
  • 1
  • 9
0

Fixed. In the original example, an error found. I don't fully understand why it's the right thing to do:

auto clearBuffers = new Qt3DRender::QClearBuffers(cameraSelector);

insted

auto clearBuffers = new Qt3DRender::QClearBuffers(renderSurfaceSelector);
avttrue
  • 387
  • 2
  • 12