在OpenGL中绘制大量像素

7

我一直在处理一些声音处理代码,现在正在进行一些可视化工作。我已经完成了一个频谱图,但是绘制速度太慢了。

我使用OpenGL进行2D绘图,这使得寻求帮助更加困难。并且我对OpenGL非常陌生,所以不知道标准的操作方式。

我在一个大型矩阵中存储每个像素点的红、绿、蓝值。每当我获得一个小的声音片段,我就将其处理并转换为一列像素。每次向左移动1个像素,新行放置在最后。

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

有没有更好的方法来解决这个问题?有没有一种方法可以简单地将一堆像素移动过去?


7
为什么不从你的频谱图构建一个位图,然后将该位图用作GL四边形的纹理? - Matthieu N.
4个回答

4

提高绘图速度的方法有很多种。 其中最简单的方法是分配一个RGB纹理,通过屏幕对齐的纹理四边形进行绘制。 每次想要绘制新线条时,可以使用glTexSubImage2d加载纹理的新子集,然后重新绘制四边形。


好的,我解决了,并且有点这样做了。我忘了提到一件事,我的像素值存储在循环缓冲区中,这使得事情稍微有些棘手,但可以处理。每次添加一行时,我从所有像素创建一个纹理,然后使用四边形适当地映射它。我可以轻松处理四边形中来自循环缓冲区的偏移量,只需使用几个额外的映射即可。这远非最佳选择,但比我之前的方法快得多。 - MattRS

2

您是否将比像素更多的数据传递给了显卡?如果您的FFT大小远大于绘图区域的高度或者谱线数量远大于其宽度,则可能会发生这种情况。如果是这样,瓶颈可能是通过总线传输过多的数据。尝试通过对谱线进行平均或选择(对一组连续线中的每个箱取最大值)来减少谱线数量。


好的建议,但我已经处理了。那个问题是我的绘图方法极其低效。 - MattRS

1

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

使用循环缓冲区来存储像素,然后只需使用适当的偏移量两次调用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);
}

1

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