如何使此OpenGL(QT3D)代码有效



我编写了一个呈现175x175高度图的小程序。渲染是使用QT3D完成的,QT3D基本上是OpenGL周围的一组包装纸。该程序可以正加载并在功能强大的桌面上运行良好。但是,当我在较低的GPU上运行它时,当我开始移动相机时,图像更新非常便宜。即使对于一个小的GPU来说,渲染3D Terrain Mesh确实不应该那么困难,所以我认为我做错了什么。是否有一些明显的方法来优化此代码,或者我只是期望从一个小的GPU中得到太多?

碎片着色器https://github.com/qt/qt3d/blob/5.12/src/extras/shaders/shaders/es2/phong.inc.frag

顶点着色器:https://github.com/qt/qt3d/blob/5.12/src/extras/shaders/shaders/es2/morphphong.vert

int main(int argc, char* argv[])
{
    QGuiApplication app(argc, argv);
    Qt3DExtras::Qt3DWindow view;
    // Scene Root
    Qt3DCore::QEntity *sceneRoot = new Qt3DCore::QEntity();
    // Scene Camera
    Qt3DRender::QCamera *basicCamera = view.camera();
    basicCamera->setProjectionType(Qt3DRender::QCameraLens::PerspectiveProjection);
    basicCamera->setUpVector(QVector3D(0.0f, 1.0f, 0.0f));
    basicCamera->setViewCenter(QVector3D(60.0f, 15.0f, -60.0f));
    basicCamera->setPosition(QVector3D(60.0f, 26.0f, 0.0f));
    // For camera controls
    Qt3DExtras::QFirstPersonCameraController *camController = new Qt3DExtras::QFirstPersonCameraController(sceneRoot);
    camController->setCamera(basicCamera);
    // Material
    Qt3DRender::QMaterial *material= new Qt3DExtras::QPhongMaterial(sceneRoot);
    Qt3DCore::QEntity *customMeshEntity = new Qt3DCore::QEntity(sceneRoot);
    // Transform
    Qt3DCore::QTransform *transform = new Qt3DCore::QTransform;
    Qt3DRender::QGeometryRenderer *customMeshRenderer = new Qt3DRender::QGeometryRenderer;
    Qt3DRender::QGeometry *customGeometry = new Qt3DRender::QGeometry(customMeshRenderer);
    Qt3DRender::QBuffer *vertexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, customGeometry);
    Qt3DRender::QBuffer *indexDataBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::IndexBuffer, customGeometry);
    QImage heightmap("../assets/heightmap.png");
    QByteArray vertexBufferData;
    vertexBufferData.resize(heightmap.width() * heightmap.height() * (3 + 3 + 3) * sizeof(float));
    QVector<QVector3D> vertexPositions;
    for (int row = 0; row < heightmap.height(); row++) {
        for (int column = 0; column < heightmap.width(); column++) {
            vertexPositions.append(QVector3D(row, heightmap.pixelColor(row, column).red()/8.0, -column));
        }
    }
    QVector<QVector3D> vertexNormals;
    for (int row = 0; row < heightmap.height(); row++) {
        for (int column = 0; column < heightmap.width(); column++) {
            int center = (row * heightmap.width()) + column;
            int upper = center - heightmap.width();
            int lower = center + heightmap.width();
            int right = center + 1;
            int left = center -1;
            int lowerLeft = center - 1 + heightmap.width();
            int upperRight = center + 1 - heightmap.width();
            int rightEdge = heightmap.width() - 1;
            int bottomEdge = heightmap.height() -1;
            // Calculate normals for each adjacent face and sum
            // Check for edge conditions
            QVector3D vertexNormal(0, 0, 0);
            if (column != 0 && row != 0 ) {
                vertexNormal += QVector3D::normal(vertexPositions[center], vertexPositions[upper], vertexPositions[left]);
            }
            if (column != rightEdge && row != 0) {
                vertexNormal += QVector3D::normal(vertexPositions[center], vertexPositions[upperRight], vertexPositions[upper]);
                vertexNormal += QVector3D::normal(vertexPositions[center], vertexPositions[right], vertexPositions[upperRight]);
             }
            if (column != rightEdge && row != bottomEdge) {
                vertexNormal += QVector3D::normal(vertexPositions[center], vertexPositions[lower], vertexPositions[right]);
            }
            if (column != 0 && row != bottomEdge) {
                vertexNormal += QVector3D::normal(vertexPositions[center], vertexPositions[lowerLeft], vertexPositions[lower]);
                vertexNormal += QVector3D::normal(vertexPositions[center], vertexPositions[left], vertexPositions[lowerLeft]);
            }
            vertexNormals.append(vertexNormal.normalized());
        }
    }
    // Colors
    QVector3D red(1.0f, 0.0f, 0.0f);
    QVector3D yellow(1.0f, 1.0f, 0.0f);
    QVector3D green(0.0f, 1.0f, 0.0f);
    QVector3D blue(0.0f, 0.0f, 1.0f);
    QVector3D white(1.0f, 1.0f, 1.0f);

    QVector<QVector3D> vertices;
    for (int i = 0; i < vertexPositions.count(); i ++) {
        vertices.append(vertexPositions[i]);
        vertices.append(vertexNormals[i]);
        if (vertexPositions[i].y() > 20.0) {
            vertices.append(red);
        }
        else if (vertexPositions[i].y() > 18.0) {
            vertices.append(yellow);
        }
        else {
            vertices.append(green);
        }
    }
    float *rawVertexArray = reinterpret_cast<float *>(vertexBufferData.data());
    int idx = 0;
    Q_FOREACH (const QVector3D &v, vertices) {
        rawVertexArray[idx++] = v.x();
        rawVertexArray[idx++] = v.y();
        rawVertexArray[idx++] = v.z();
    }
    // Indices
    QByteArray indexBufferData;
    int indicesCount = (heightmap.height() - 1) * (heightmap.width() - 1) * 2 * 3;
    indexBufferData.resize( indicesCount * sizeof(uint));
    uint *rawIndexArray = reinterpret_cast<uint *>(indexBufferData.data());
    int index = 0;
    for (int row = 0; row < heightmap.height()-1; row++) {
        for (int column = 0; column < heightmap.width()-1; column++) {
            //  1 <- 3
            //  |   /
            //  |  /
            //  v /
            //  2
            int vertexBufferIndex = (row * heightmap.width()) + column;
            rawIndexArray[index++] = vertexBufferIndex;
            rawIndexArray[index++] = vertexBufferIndex + heightmap.width(); // down one row
            rawIndexArray[index++] = vertexBufferIndex + 1; // right one column
            //       1
            //     / ^
            //    /  |
            //   /   |
            //  2 -> 3
            rawIndexArray[index++] = vertexBufferIndex + 1; // right one column
            rawIndexArray[index++] = vertexBufferIndex + heightmap.width(); // down one row
            rawIndexArray[index++] = vertexBufferIndex + heightmap.width() + 1; // down one row and right one column
        }
    }
    vertexDataBuffer->setData(vertexBufferData);
    indexDataBuffer->setData(indexBufferData);
    // Attributes
    Qt3DRender::QAttribute *positionAttribute = new  Qt3DRender::QAttribute();
    positionAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute);
    positionAttribute->setBuffer(vertexDataBuffer);
    positionAttribute->setDataType( Qt3DRender::QAttribute::Float);
    positionAttribute->setDataSize(3);
    positionAttribute->setByteOffset(0);
    positionAttribute->setByteStride(9 * sizeof(float));
    positionAttribute->setCount(vertexPositions.count());
    positionAttribute->setName( Qt3DRender::QAttribute::defaultPositionAttributeName());
    Qt3DRender::QAttribute *normalAttribute = new  Qt3DRender::QAttribute();
    normalAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute);
    normalAttribute->setBuffer(vertexDataBuffer);
    normalAttribute->setDataType( Qt3DRender::QAttribute::Float);
    normalAttribute->setDataSize(3);
    normalAttribute->setByteOffset(3 * sizeof(float));
    normalAttribute->setByteStride(9 * sizeof(float));
    normalAttribute->setCount(vertexPositions.count());
    normalAttribute->setName( Qt3DRender::QAttribute::defaultNormalAttributeName());
    Qt3DRender::QAttribute *colorAttribute = new  Qt3DRender::QAttribute();
    colorAttribute->setAttributeType( Qt3DRender::QAttribute::VertexAttribute);
    colorAttribute->setBuffer(vertexDataBuffer);
    colorAttribute->setDataType( Qt3DRender::QAttribute::Float);
    colorAttribute->setDataSize(3);
    colorAttribute->setByteOffset(6 * sizeof(float));
    colorAttribute->setByteStride(9 * sizeof(float));
    colorAttribute->setCount(vertexPositions.count());
    colorAttribute->setName( Qt3DRender::QAttribute::defaultColorAttributeName());
    Qt3DRender::QAttribute *indexAttribute = new  Qt3DRender::QAttribute();
    indexAttribute->setAttributeType( Qt3DRender::QAttribute::IndexAttribute);
    indexAttribute->setBuffer(indexDataBuffer);
    indexAttribute->setDataType( Qt3DRender::QAttribute::UnsignedInt);
    indexAttribute->setDataSize(1);
    indexAttribute->setByteOffset(0);
    indexAttribute->setByteStride(0);
    indexAttribute->setCount(indicesCount);
    customGeometry->addAttribute(positionAttribute);
    customGeometry->addAttribute(normalAttribute);
    customGeometry->addAttribute(colorAttribute);
    customGeometry->addAttribute(indexAttribute);
    customMeshRenderer->setInstanceCount(1);
    customMeshRenderer->setFirstVertex(0);
    customMeshRenderer->setFirstInstance(0);
    customMeshRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::Triangles);
    customMeshRenderer->setGeometry(customGeometry);
    customMeshEntity->addComponent(customMeshRenderer);
    customMeshEntity->addComponent(transform);
    customMeshEntity->addComponent(material);
    view.setRootEntity(sceneRoot);
    view.show();
    return app.exec();
}

QT博客在优化低端硬件的QT3D应用程序时具有很好的文章。

https://blog.qt.io/blog/2019/04/02/optimizing-real time-3d-entry-level-level-hardware/

相关内容

  • 没有找到相关文章