QRenderPassFilter скрывает плоскую сетку, даже если QFilterKey соответствует - PullRequest
2 голосов
/ 15 октября 2019

Мы стремимся заменить наш предыдущий 3D-движок на Qt3D. В качестве последнего препятствия нам нужно правильно реализовать пиксельную корректную прозрачность. Сейчас мы пытаемся реализовать глубинный пилинг как возможный подход, чтобы сделать пиксельно-корректную прозрачность работоспособной. Для этого алгоритма необходимо выполнить отложенный (многопроходный) рендеринг, который может быть достигнут с помощью QRenderPassFilter и QFilterKey внутри эффекта.

Теперь у меня уже были большие проблемы, чтобы заставить комбинацию QRenderPassFilter и QFilterKey вместе с материалом QDiffuseSpecularMaterial работать правильно. Даже если есть только один проход.

Это мой исходный код:

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QFrame>
#include <Qt3DCore/QTransform>
#include <Qt3DRender/QSortPolicy>
#include <Qt3DRender/QRenderSettings>
#include <Qt3DRender/QRenderSurfaceSelector>
#include <Qt3DRender/QViewport>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QCameraSelector>
#include <Qt3DRender/QClearBuffers>
#include <Qt3DRender/QDirectionalLight>
#include <Qt3DRender/QTexture>
#include <Qt3DExtras/QPlaneMesh>
#include <Qt3DExtras/QDiffuseSpecularMaterial>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DRender/QFilterKey>
#include <Qt3DRender/QParameter>
#include <Qt3DRender/QRenderPass>
#include <Qt3DRender/QRenderPassFilter>
#include <Qt3DRender/QTechnique>
#include <QDebug>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);

    auto view = new Qt3DExtras::Qt3DWindow();
    auto mClearBuffers = new Qt3DRender::QClearBuffers;
    auto mMainCameraSelector = new Qt3DRender::QCameraSelector;
    mMainCameraSelector->setCamera(view->camera());
    auto mRenderSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector;
    auto mMainViewport = new Qt3DRender::QViewport;

    auto renderPassFilter = new Qt3DRender::QRenderPassFilter;
    {
        auto filterKey = new Qt3DRender::QFilterKey(renderPassFilter);
        filterKey->setName(QStringLiteral("renderingStyle"));
        filterKey->setValue(QStringLiteral("forward"));
        // Adding the filterKey to the renderPassFilter hides the plane
        // Name and Value of filterKey matches the FilterKey inside the QDiffuseSpecularMaterial
        renderPassFilter->addMatch(filterKey); // Removing this lines shows the plane mesh

        mClearBuffers->setClearColor(Qt::lightGray);
        mClearBuffers->setBuffers(Qt3DRender::QClearBuffers::BufferType::ColorDepthBuffer);
        mMainCameraSelector->setParent(mClearBuffers);
        mClearBuffers->setParent(renderPassFilter);
    }
    renderPassFilter->setParent(mRenderSurfaceSelector);

    mRenderSurfaceSelector->setParent(mMainViewport);

    view->setActiveFrameGraph(mMainViewport);
    view->activeFrameGraph()->dumpObjectTree();

    auto rootEntity = new Qt3DCore::QEntity();
    view->setRootEntity(rootEntity);

    view->camera()->lens()->setPerspectiveProjection(45.0f, 1., 0.1f, 10000.0f);
    view->camera()->setPosition(QVector3D(0, 2, 0));
    view->camera()->setUpVector(QVector3D(0, 1, 0));
    view->camera()->setViewCenter(QVector3D(0, 0, 0));

    auto planeEntity = new Qt3DCore::QEntity(rootEntity);

    auto meshMaterial = new Qt3DExtras::QDiffuseSpecularMaterial;
    meshMaterial->setDiffuse(QColor("#ff00ff"));
    planeEntity->addComponent(meshMaterial);

    auto mesh = new Qt3DExtras::QPlaneMesh;
    mesh->setWidth(0.3);
    mesh->setHeight(0.3);
    planeEntity->addComponent(mesh);

    auto container = QWidget::createWindowContainer(view);
    QFrame frame;
    frame.setLayout(new QVBoxLayout);
    frame.layout()->addWidget(container);
    frame.resize(QSize(400, 300));

    frame.show();
    return a.exec();
}

Консоль выводит мой framegraph как:

Qt3DRender::QViewport::
    Qt3DRender::QRenderSurfaceSelector::
        Qt3DRender::QRenderPassFilter::
            Qt3DRender::QFilterKey::
            Qt3DRender::QClearBuffers::
                Qt3DRender::QCameraSelector::

Теперь, если я удалюлиния

renderPassFilter->addMatch(filterKey);

все работает, как ожидалось, и я вижу свою простую плоскую сетку.

Однако добавление линии, которая не должна фильтровать все, что плоская сетка больше не отображается.

У меня действительно заканчиваются идеи, что я, возможно, делаю здесь неправильно. Как я могу заставить мою маленькую программу работать с renderPassFilter и в чем мои ошибки?

Я тоже не очень понял, для чего нужны настройки name и value в QFilterKey, что из того и другого необходимо для фильтрации определенных эффектов?

1 Ответ

2 голосов
/ 15 октября 2019

После тщательного изучения моего приложения и, в частности, QDiffuseSpecularMaterial я выяснил, что QFilterKey внутри QDiffuseSpecularMaterial не добавляется к объекту QRenderPass, а, кроме того, добавляется к QTechnique, который я нашел довольно непонятным,

Теперь, добавив QTechniqueFilter вместо QRenderPassFilter, программа работала так, как ожидалось. Изменение строки forward на что-то другое, например xxx скрывает плоскость, как и ожидалось.

Добавление строки

meshMaterial->dumpObjectTree();

действительно дало мне подсказку

Qt3DExtras::QDiffuseSpecularMaterial::
    Qt3DRender::QShaderProgramBuilder::
        Qt3DRender::QShaderProgram::
    Qt3DRender::QShaderProgramBuilder::
        Qt3DRender::QShaderProgram::
    Qt3DRender::QFilterKey::
    Qt3DRender::QEffect::
        Qt3DRender::QTechnique::
            Qt3DRender::QRenderPass::
                Qt3DRender::QNoDepthMask::
                Qt3DRender::QBlendEquationArguments::
                Qt3DRender::QBlendEquation::
        Qt3DRender::QTechnique::
            Qt3DRender::QRenderPass::
        Qt3DRender::QTechnique::
            Qt3DRender::QRenderPass::
        Qt3DRender::QParameter::
        Qt3DRender::QParameter::
        Qt3DRender::QParameter::
        Qt3DRender::QParameter::
        Qt3DRender::QParameter::

Так что dumpObjectTree() кажется хорошим инструментом отладки на полке, когда речь идет о Qt3D и Qt в целом.

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QFrame>
#include <Qt3DCore/QTransform>
#include <Qt3DRender/QSortPolicy>
#include <Qt3DRender/QRenderSettings>
#include <Qt3DRender/QRenderSurfaceSelector>
#include <Qt3DRender/QViewport>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QCameraSelector>
#include <Qt3DRender/QClearBuffers>
#include <Qt3DRender/QTechniqueFilter>
#include <Qt3DRender/QDirectionalLight>
#include <Qt3DRender/QTexture>
#include <Qt3DExtras/QPlaneMesh>
#include <Qt3DExtras/QDiffuseSpecularMaterial>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DRender/QFilterKey>
#include <Qt3DRender/QParameter>
#include <Qt3DRender/QRenderPass>
#include <Qt3DRender/QRenderPassFilter>
#include <Qt3DRender/QTechnique>
#include <QDebug>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);

    auto view = new Qt3DExtras::Qt3DWindow();
    auto mClearBuffers = new Qt3DRender::QClearBuffers;
    auto mMainCameraSelector = new Qt3DRender::QCameraSelector;
    mMainCameraSelector->setCamera(view->camera());
    auto mRenderSurfaceSelector = new Qt3DRender::QRenderSurfaceSelector;
    auto mMainViewport = new Qt3DRender::QViewport;
    auto renderPassFilter = new Qt3DRender::QTechniqueFilter;
    {
        auto filterKey = new Qt3DRender::QFilterKey(renderPassFilter);
        filterKey->setName(QStringLiteral("renderingStyle"));
        filterKey->setValue(QStringLiteral("forward"));
        // Adding the filterKey to the renderPassFilter hides the plane
        // Name and Value of filterKey matches the FilterKey inside the QDiffuseSpecularMaterial
        renderPassFilter->addMatch(filterKey); // Removing this lines shows the plane mesh

        mClearBuffers->setClearColor(Qt::lightGray);
        mClearBuffers->setBuffers(Qt3DRender::QClearBuffers::BufferType::ColorDepthBuffer);
        mMainCameraSelector->setParent(mClearBuffers);
        mClearBuffers->setParent(renderPassFilter);
    }
    renderPassFilter->setParent(mRenderSurfaceSelector);

    mRenderSurfaceSelector->setParent(mMainViewport);

    view->setActiveFrameGraph(mMainViewport);
    view->activeFrameGraph()->dumpObjectTree();

    auto rootEntity = new Qt3DCore::QEntity();
    view->setRootEntity(rootEntity);

    view->camera()->lens()->setPerspectiveProjection(45.0f, 1., 0.1f, 10000.0f);
    view->camera()->setPosition(QVector3D(0, 2, 0));
    view->camera()->setUpVector(QVector3D(0, 1, 0));
    view->camera()->setViewCenter(QVector3D(0, 0, 0));

    auto planeEntity = new Qt3DCore::QEntity(rootEntity);

    auto meshMaterial = new Qt3DExtras::QDiffuseSpecularMaterial;
    meshMaterial->setDiffuse(QColor("#ff00ff"));
    planeEntity->addComponent(meshMaterial);

    auto mesh = new Qt3DExtras::QPlaneMesh;
    mesh->setWidth(0.3);
    mesh->setHeight(0.3);
    planeEntity->addComponent(mesh);

    auto container = QWidget::createWindowContainer(view);
    QFrame frame;
    frame.setLayout(new QVBoxLayout);
    frame.layout()->addWidget(container);
    frame.resize(QSize(400, 300));

    frame.show();
    return a.exec();
}
...