草庐IT

c++ - Qt pointcloud 在 scene3d 中性能缓慢

coder 2024-02-11 原文

我在为在 Scene3d 中显示点云而编写的 QML 应用程序中发现了主要性能问题。 1000 点/秒没问题,但在 10,000 点时它基本上只会让我的整个计算机停止运行。目标是达到数百万点(这是旧应用程序,Qt/VTK 混合物可以在减速之前完成。)

我担心我没有将处理卸载到另一个线程,或者没有正确渲染。 ...这是我的第一个 Qt 项目,对所有这一切都是陌生的。

基本上我构建了一个点的 circular_buffer(每个点是 32 字节),我将其复制到自定义 QGeometryEntity< 上的="">QByteArray/。该实体具有运行顶点和片段着色器的 Material 。

我可以做些什么来提高性能吗?

Material :

import Qt3D.Core 2.0
import Qt3D.Render 2.0

Material {
    effect: Effect {
        techniques: Technique {
            renderPasses: RenderPass {
                shaderProgram: ShaderProgram {
                    vertexShaderCode: loadSource("qrc:/shaders/pointcloud.vert")
                    fragmentShaderCode: loadSource("qrc:/shaders/pointcloud.frag")
                }
                renderStates: [
                    PointSize { sizeMode: PointSize.Programmable } //supported since OpenGL 3.2
                ]
            }
            graphicsApiFilter {
                api: GraphicsApiFilter.OpenGL
                profile: GraphicsApiFilter.CoreProfile
                majorVersion: 4
                minorVersion: 3
            }
        }
    }
        // some parameters...
}

我的着色器非常简单:

顶点:

#version 430

layout(location = 1) in vec3 vertexPosition;

out VertexBlock
{
    flat vec3 col;
    vec3 pos;
    vec3 normal;
} v_out;

uniform mat4 modelView;
uniform mat3 modelViewNormal;
uniform mat4 mvp;
uniform mat4 projectionMatrix;
uniform mat4 viewportMatrix;

uniform float pointSize;
uniform float maxDistance;

void main()
{
    vec3 vertexNormal = vec3(1.0, 1.0, 1.0);
    v_out.normal = normalize(modelViewNormal * vertexNormal);
    v_out.pos    = vec3(modelView * vec4(vertexPosition, 1.0));

    float c      = (vertexPosition[0]*vertexPosition[0] + vertexPosition[1]*vertexPosition[1])*maxDistance;
    v_out.col    = vec3(c,c,0.5);

    gl_Position = mvp * vec4(vertexPosition, 1.0);
    gl_PointSize = viewportMatrix[1][1] * projectionMatrix[1][1] * pointSize / gl_Position.w;
}

片段:

#version 430

in VertexBlock
{
    flat vec3 col;
    vec3 pos;
    vec3 normal;
} frag_in;

out vec4 colour;

void main()
{
    colour = vec4(frag_in.col, 1.0);
}

渲染器:

import Qt3D.Core 2.0
import Qt3D.Render 2.0

import "Cameras"

RenderSettings {
    id: root

    property CameraSet cameraSet: CameraSet {
        id: cameraSet
    }

    property real userViewWidth: 0.79
    property real topOrthoViewHeight: 0.79

    activeFrameGraph: Viewport {
        id: viewport
        normalizedRect: Qt.rect(0.0, 0.0, 1.0, 1.0)

        RenderSurfaceSelector {
            ClearBuffers {
                buffers : ClearBuffers.ColorDepthBuffer
                clearColor: theme.cSceneClear

                NoDraw {}
            }

            Viewport {
                id: userViewport
                normalizedRect: Qt.rect(0, 0, userViewWidth, 1.0)

                CameraSelector {
                    id: userCameraSelectorViewport
                    camera: cameraSet.user.camera
                }
            }
            // Two other viewports...
        }
    }
}

实体

Entity {
    property PointBuffer buffer: PointBuffer {
        id: pointBuffer
    }

    PointsMaterial {
        id: pointsMaterial
        dataBuffer: pointBuffer
    }

    Entity {
        id: particleRenderEntity
        property GeometryRenderer particlesRenderer: GeometryRenderer {
            instanceCount: buffer.count
            primitiveType: GeometryRenderer.Points
            geometry: PointGeometry { buffer: pointBuffer }
        }

        components: [
            particlesRenderer
            , pointsMaterial
        ]
    }
}

最佳答案

找到问题了,我最初发布的信息中没有。

在实体中,我有 instanceCount: buffer.count,但在我的 Geometry 中,我一步写入了整个缓冲区。因此,我有效地平方了缓冲区的大小。

解决方案是设置instanceCount: 1

我之前对这一行感到困惑,甚至将其删除,但我怀疑它默认为该值。我不明白 QML 文档中关于这究竟会做什么的内容。

无论如何,它的真正用途是用于像 SphereGeometry 这样的几何体,它为每个点构建一个缓冲区。因此,给定一个点,它会构建顶点和索引以在该点周围渲染一个球体。 (我不确定他们为什么不在几何着色器中这样做。)

关于c++ - Qt pointcloud 在 scene3d 中性能缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41836095/

有关c++ - Qt pointcloud 在 scene3d 中性能缓慢的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  3. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  4. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  5. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  6. [Vuforia]二.3D物体识别 - 2

    之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶

  7. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  8. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  9. += 的 Ruby 方法 - 2

    有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=

  10. ruby - Sinatra + Heroku + Datamapper 使用 dm-sqlite-adapter 部署问题 - 2

    出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t

随机推荐