【问题标题】:Fast line drawing in OpenGLOpenGL中的快速线条绘制
【发布时间】:2014-04-16 04:59:19
【问题描述】:

我正在开展一个项目,该项目需要绘制大量数据,因为这些数据是由 ADC 获取的……在 1600 像素宽的监视器上每帧 50,000 行。它在配备 2007-ish Quadro FX 570 的系统上运行良好,但基本上无法跟上配备 Intel HD 4000 级芯片的机器上的数据。数据负载是 32 个通道的 200 Hz 数据,每通道每秒 40 次分批接收 5 个样本。因此,换句话说,该卡只需要达到每秒 40 帧或更好。

我对所有 32 个通道使用单个 VBO,每个通道有 10,000 个顶点。 VBO 本质上被视为每个通道的一系列环形缓冲区。当数据进来时,我会根据使用的时间尺度来抽取它。因此,基本上,它跟踪每个通道的最小值/最大值。当为单个像素列接收到足够的数据时,它会为每个通道设置 VBO 中接下来的两个顶点并渲染一个新帧。

我使用 glMapBuffer() 访问数据一次,更新所有通道,使用 glUnmapBuffer,然后根据需要进行渲染。

我提前手动计算了变换矩阵(使用以非通用方式计算的正交变换来减少乘法),顶点着色器看起来像:

#version 120

varying vec4 _outColor;

uniform vec4 _lBound=vec4(-1.0);
uniform vec4 _uBound=vec4(1.0);
uniform mat4 _xform=mat4(1.0);

attribute vec2 _inPos;
attribute vec4 _inColor;

void main()
{
    gl_Position=clamp(_xform*vec4(_inPos, 0.0, 1.0), _lBound, _uBound);
    _outColor=_inColor;
}

_lBound_uBound_xform 制服每个频道更新一次。因此,每帧 32 次。钳位用于将某些通道限制在屏幕上的 y 坐标范围内。

片段着色器很简单:

#version 120

varying vec4 _outColor;

void main()
{
    gl_FragColor=_outColor;
}

还有其他东西正在渲染到屏幕上;通道标签,例如,使用四边形和纹理图集;但是 gDEBugger 中的分析似乎表明线渲染占用了每帧绝大多数时间。

不过,50,000 行对我来说似乎并不是一个可怕的数字。

所以,毕竟,问题是:有什么技巧可以加快线条绘制速度?我尝试将它们渲染到模板缓冲区,然后剪裁单个四边形,但速度较慢。我想把线条画到纹理上,用纹理画一个四边形。但是,由于不断上传大型纹理,这似乎无法扩展甚至更快。我看到了一种将 y 值存储在单行纹理中的技术,但这似乎更像是内存优化而不是速度优化。

【问题讨论】:

  • 致投票结束这个问题的人:这完全是关于 opengl 标记内 StackOverflow 的主题。
  • 啊。最大纹理大小是个问题。
  • 不确定这是否可行,但我将尝试使用多个帧缓冲区和 glBlitFramebuffer()。基本上,将渲染数据从 Framebuffer A 复制到 Framebuffer B 移动一个,渲染新行,然后输出 Framebuffer B。有点像 FBO 中的纹理概念,但绕过了纹理大小限制。
  • 您发出多少个 OpenGL 绘图调用来渲染所有线条?加速 OpenGL 性能的一个好方法是在 /very/ 大的顶点缓冲区中构建线条几何图形,然后在一次绘制调用中将其全部提交给显卡。您可以轻松预测必要的顶点缓冲区大小,因此这应该不是问题。通常的限制确实是绘制调用的数量,而不是实际的数据带宽。
  • 我是否理解正确,您基本上是在尝试渲染像 this 这样的东西,只有 32 个轨道?如果是这种情况,不要画线,每个通道画一个四边形并使用像素着色器。

标签: c++ performance opengl


【解决方案1】:

映射 VBO 可能会减慢您的速度,因为驱动程序可能需要将 GPU 与 CPU 同步。一种更高效的方法是将数据放到 GPU 上,这样 CPU 和 GPU 可以更独立地运行。

  • 每次都重新创建 VBO,务必使用 STATIC_DRAW 创建它
  • 如果您需要映射数据,请不要映射为可读 (GL_WRITE_ONLY)

【讨论】:

    【解决方案2】:

    如果您只是滚动折线图(GDI 样式),只需在 CPU 上绘制新列并使用 glTexSubImage2D 更新纹理中的单个列。将其绘制为一对四边形并更新 st 坐标以处理滚动/换行。

    如果您需要一直更新所有行,请使用使用 GL_DYNAMIC_DRAW 创建的 VBO 并使用 glBufferSubData 更新缓冲区。

    【讨论】:

      【解决方案3】:

      谢谢大家。我最终决定在渲染缓冲区支持的帧缓冲区之间进行 blitting。工作得很好。许多人建议使用纹理,如果我最终需要在数据背后绘制,我可能会走这条路。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多