在 OpenGL 中绘制大量像素

Posted

技术标签:

【中文标题】在 OpenGL 中绘制大量像素【英文标题】:Drawing large numbers of pixels in OpenGL 【发布时间】:2010-11-06 01:52:43 【问题描述】:

我一直在编写一些声音处理代码,现在我正在做一些可视化。我完成了spectrogram 频谱图,但是我绘制它的速度太慢了。

我正在使用 OpenGL 进行 2D 绘图,这使得寻求帮助变得更加困难。另外我对 OpenGL 很陌生,所以我不知道事情的标准完成方式。

我将每个像素的 r,g,b 值存储在一个大矩阵中。 每次我得到一个小的声音片段时,我都会对其进行处理并将其转换为像素列。一切都向左移动 1 个像素,新行放在最后。

每次重绘时,我都会循环设置颜色并单独绘制每个像素,这似乎是一种非常低效的方法。

有没有更好的方法来做到这一点?有什么方法可以简单地移动一堆像素吗?

【问题讨论】:

为什么不从你的频谱图中构建一个位图,然后将位图用作 gl quad 的纹理? 【参考方案1】:

它们是提高绘图速度的多种方法。 最简单的方法是分配一个 RGB 纹理,您将使用屏幕对齐的纹理四边形绘制该纹理。 每次你想画一条新线时,你可以使用 glTexSubImage2d 加载纹理的新子集,然后重画四边形。

【讨论】:

好吧,我想通了,然后就这么做了。我忘记提到的一件事是我的像素值存储在一个循环缓冲区中,这使事情变得更具挑战性,但可以处理。每次添加一条线时,我都会从所有像素创建一个纹理,然后将其与四边形适当地映射。我可以使用四边形中的几个额外映射轻松处理循环缓冲区的偏移量。它远非最佳,但比我以前的要快得多。【参考方案2】:

您向显卡传递的数据是否可能比像素多得多?如果您的 FFT 尺寸远大于绘图区域的高度,或者谱线的数量远大于其宽度,则可能会发生这种情况。如果是这样,瓶颈可能会通过总线传递太多数据。尝试通过对它们进行平均或挑选来减少光谱线的数量(对一组连续的线在每个 bin 中取最大值)。

【讨论】:

好建议,但我已经在处理了。这个问题是我非常低效的绘图方法。【参考方案3】:

GL_POINTS、VBO、GL_STREAM_DRAW

【讨论】:

【参考方案4】:

我知道这是一个老问题,但是 . . .

使用循环缓冲区来存储像素,然后使用适当的偏移量调用 glDrawPixels 两次。像这样未经测试的C:

#define SIZE_X 800
#define SIZE_Y 600
unsigned char pixels[SIZE_Y][SIZE_X*2][3];
int start = 0;

void add_line(const unsigned char line[SIZE_Y][1][3]) 
    int i,j,coord=(start+SIZE_X)%(2*SIZE_X);
    for (i=0;i<SIZE_Y;++i) for (j=0;j<3;++j) pixels[i][coord][j] = line[i][0][j];
    start = (start+1) % (2*SIZE_X);

void draw(void) 
    int w;
    w = 2*SIZE_X-start;
    if (w!=0) glDrawPixels(w,SIZE_Y,GL_RGB,GL_UNSIGNED_BYTE,3*sizeof(unsigned char)*SIZE_Y*start+pixels);
    w = SIZE_X - w;
    if (w!=0) glDrawPixels(SIZE_X,SIZE_Y,GL_RGB,GL_UNSIGNED_BYTE,pixels);

【讨论】:

以上是关于在 OpenGL 中绘制大量像素的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL - 将像素绘制到屏幕上?

如何在OpenGL中将像素作为纹理绘制到多边形?

使用 glDrawPixels() 在 OpenGL 上绘制像素

OpenGL 中的 2D 绘图:在原始尺寸下具有像素精度的线性过滤

Opengl像素完美2D绘图

OpenGL:基本图形绘画二