QT3D中的2D网格

5
我觉得Qt3D不能很好地渲染2D网格。要了解我的意思,请打开shadow map QML example,将摄像机控制器从FirstPersonCameraController更改为OrbitCameraController。运行程序并尝试从下方查看地面平面,您会发现它消失了。因此,QT3D只从一侧渲染2D网格,并使它们从另一侧变成透明。
如何解决这个问题?即如何从两侧渲染2D网格?
编辑:现在我知道我必须禁用剔除才能使渲染正常工作。我到达了这个点:
//'this' refers to Qt3DWindow
rootEntity->addComponent(this->renderSettings());
QCullFace *face = new QCullFace();
QRenderStateSet *stateSet = new QRenderStateSet(this->renderSettings()->activeFrameGraph());
QRenderSurfaceSelector *selector = new QRenderSurfaceSelector(this->renderSettings());
face->setMode(QCullFace::NoCulling);
stateSet->addRenderState(face);
selector->setSurface(this);

但是这似乎仍然没有改变任何事情。我有什么遗漏的吗?

1
这听起来像是背面剔除。我没有使用过Qt3D,但看看是否有一种方法可以禁用该网格的剔除,并尝试查看是否可以解决问题。https://en.wikipedia.org/wiki/Back-face_culling - Banex
或者您可以创建自己的QGeometry并为背面添加面。对于平面网格来说,这应该不太困难(或者当然可以创建第二个平面网格并翻转它)。这可能更合适,因为如果禁用背面剔除,则整个场景都将被禁用。 - Florian Blume
谢谢大家提供的有用信息!我已经更新了我的问题。 - Mariam
现在,你要进入Qt3D中棘手的部分(尤其是文档不完善的部分)。你需要将这部分添加到你的帧图中。你可以通过添加一个QRenderStateSet来实现,然后将QCullFace添加到其中(在这种情况下,省略QRenderPass)。但是,你还需要添加一个QRenderSurfaceSelector,并将Qt3DWindow(我假设你正在使用)设置为表面。你需要将表面选择器设置为Qt3DWindow的QRenderSettings的子项。渲染设置还必须作为根节点上的组件进行设置。 - Florian Blume
或者您可以查看我的Qt3D离屏渲染器存储库(这个存储库花费了我很多精力才创建):https://github.com/Sonnentierchen/Qt3D-OffscreenRenderer。如果您查看OffscreenSurfaceFramegraph类,您可以将一个设置了剔除的QRenderState作为相机选择器的子项添加进去。这就是它应该存在的地方。然后您就可以“逆向工程”出在您的情况下应该在哪里添加剔除面。 - Florian Blume
显示剩余14条评论
1个回答

8
这里是一个最小化的工作示例: < p >< code > main.cpp :

#include <QApplication>
#include "clickwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    GraphicsWindow graphicsWindow;
    graphicsWindow.show();
    return a.exec();
}

graphicswindow.h:

#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QTransform>

class GraphicsWindow : public Qt3DExtras::Qt3DWindow {
public:
    GraphicsWindow();
    void wheelEvent ( QWheelEvent * event ) override;

private:
    Qt3DCore::QEntity *createScene();
    Qt3DCore::QTransform *planeTransform;
};

graphicswindow.cpp:

#include "graphicswindow.h"
#include <QMouseEvent>
#include <Qt3DRender/QViewport>
#include <Qt3DRender/QClearBuffers>
#include <Qt3DRender/QRenderSurfaceSelector>
#include <Qt3DRender/QRenderStateSet>
#include <Qt3DRender/QCullFace>
#include <Qt3DRender/QCameraSelector>
#include <Qt3DRender/QCamera>
#include <Qt3DRender/QMaterial>
#include <Qt3DExtras/QGoochMaterial>
#include <Qt3DExtras/QPlaneMesh>
#include <Qt3DRender/QDepthTest>

GraphicsWindow::GraphicsWindow() : Qt3DExtras::Qt3DWindow() {
    Qt3DRender::QCamera *camera = this->camera();
    camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
    camera->setPosition(QVector3D(20.0, 20.0, 20.0f));
    camera->setViewCenter(QVector3D(0, 0, 0));

    Qt3DRender::QRenderSurfaceSelector *surfaceSelector = new Qt3DRender::QRenderSurfaceSelector;
    surfaceSelector->setSurface(this);
    Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(surfaceSelector);
    viewport->setNormalizedRect(QRectF(0, 0, 1.0, 1.0));
    Qt3DRender::QCameraSelector *cameraSelector = new Qt3DRender::QCameraSelector(viewport);
    cameraSelector->setCamera(camera);
    Qt3DRender::QClearBuffers *clearBuffers = new Qt3DRender::QClearBuffers(cameraSelector);
    clearBuffers->setBuffers(Qt3DRender::QClearBuffers::ColorDepthBuffer);
    clearBuffers->setClearColor(Qt::white);
    Qt3DRender::QRenderStateSet *renderStateSet = new Qt3DRender::QRenderStateSet(clearBuffers);
    Qt3DRender::QCullFace *cullFace = new Qt3DRender::QCullFace(renderStateSet);
    cullFace->setMode(Qt3DRender::QCullFace::NoCulling);
    renderStateSet->addRenderState(cullFace);
    Qt3DRender::QDepthTest *depthTest = new Qt3DRender::QDepthTest;
    depthTest->setDepthFunction(Qt3DRender::QDepthTest::Less);
    renderStateSet->addRenderState(depthTest);
    setActiveFrameGraph(surfaceSelector);

    Qt3DCore::QEntity *root = createScene();
    setRootEntity(root);
}

void GraphicsWindow::wheelEvent(QWheelEvent *event) {
    planeTransform->setRotationZ(planeTransform->rotationZ() + event->delta() / 40.f);
}


Qt3DCore::QEntity* GraphicsWindow::createScene() { // Root entity
    Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity;

    Qt3DCore::QEntity *planeEntity = new Qt3DCore::QEntity(rootEntity);
    Qt3DRender::QMaterial *meshMaterial = new Qt3DExtras::QGoochMaterial;
    Qt3DExtras::QPlaneMesh *planeMesh = new Qt3DExtras::QPlaneMesh;
    planeMesh->setHeight(10);
    planeMesh->setWidth(10);
    planeTransform = new Qt3DCore::QTransform;

    planeEntity->addComponent(planeTransform);
    planeEntity->addComponent(planeMesh);
    planeEntity->addComponent(meshMaterial);

    return rootEntity;
}

记住,Qt3DWindowsetActiveFramegraph函数会自动将renderSettings()函数返回的QRenderSettings添加到你设置为活动帧图的帧图节点上。如果你正在实现自己的3D窗口或创建离屏渲染器,你必须使用QRenderSettings作为你的帧图的根节点(窗口将其渲染设置设置为您设置的根帧图节点的父节点),并将渲染设置添加到实际的根节点,即框架图和场景图的父节点。请注意不要修改html标签。

非常感谢您的回答!它确实回答了问题并在2D平面上起作用!但是,禁用剔除会以某种方式搞乱3D对象:/如果您在场景中插入一个3D球体网格,则渲染器会从某些角度显示黑色条纹。而对于更复杂的网格,一些部分变得透明之类的事情也会发生。这很奇怪...也许我需要考虑其他方法来同时显示2D和3D。 - Mariam
您需要添加深度测试,因为它还不是帧图的一部分。我已经编辑了我的答案。 - Florian Blume
你是最棒的!非常感谢你花时间和耐心与我交流! - Mariam
3
不用谢 :) 我在使用这个框架时遇到了许多问题,所以我很乐意帮助别人。 - Florian Blume
这是伟大的精神!我肯定还有很多要学习的。 - Mariam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接