【问题标题】:Use index as coordinate in OpenGL在OpenGL中使用索引作为坐标
【发布时间】:2011-02-09 17:39:35
【问题描述】:

我想实现一个允许用户缩放和平滑平移的时间序列查看器。

我以前做过一些即时模式 opengl,但现在不赞成使用 VBO。我能找到的所有 VBO 示例都存储了每个点的 XYZ 坐标。

我怀疑我需要将所有数据保存在 VRAM 中,以便在平移期间获得可以称为“平滑”的帧速率,但我只有 Y 数据(因变量)。 X 是一个自变量,可以从指数中计算出来,Z 是常数。如果我必须存储 X 和 Z,那么我的内存需求(缓冲区大小和 CPU->GPU 块传输)将增加三倍。而且我有 数千万 个数据点供用户平移,因此内存使用量将不小。

是否有一些技术可以绘制一维顶点数组,其中索引用作另一个坐标,或者存储一维数组(可能在纹理中?)并使用着色器程序生成 XYZ ?我的印象是在新的无固定特征管道模型下无论如何我都需要一个简单的着色器来实现缩放和平移,所以如果我可以结合 X 和 Z 坐标的生成以及 Y 的缩放/平移,那将是理想。

这甚至可能吗?您知道执行此操作的任何示例代码吗?或者您至少能给我一些伪代码,说明以什么顺序调用哪些 GL 函数?

谢谢!

编辑:为确保清楚,这是等效的立即模式代码和顶点数组代码:

// immediate
glBegin(GL_LINE_STRIP);
for( int i = 0; i < N; ++i )
    glVertex2(i, y[i]);
glEnd();

// vertex array
struct { float x, y; } v[N];
for( int i = 0; i < N; ++i ) {
    v[i].x = i;
    v[i].y = y[i];
}
glVertexPointer(2, GL_FLOAT, 0, v);
glDrawArrays(GL_LINE_STRIP, 0, N);

注意v[] 的大小是y[] 的两倍。

【问题讨论】:

    标签: opengl shader plot vbo opengl-3


    【解决方案1】:

    这对 OpenGL 来说非常好。

    顶点缓冲区对象 (VBO) 可以以一种 GL 支持的格式存储您想要的任何信息。您可以只用一个坐标填充 VBO:

    glGenBuffers( 1, &buf_id);
    glBindBuffer( GL_ARRAY_BUFFER, buf_id );
    glBufferData( GL_ARRAY_BUFFER, N*sizeof(float), data_ptr, GL_STATIC_DRAW );
    

    然后为绘制绑定合适的顶点属性格式:

    glBindBuffer( GL_ARRAY_BUFFER, buf_id );
    glEnableVertexAttribArray(0);  // hard-coded here for the sake of example
    glVertexAttribPointer(0, 1, GL_FLOAT, false, 0, NULL);
    

    为了使用它,您需要一个简单的着色器程序。顶点着色器可能如下所示:

    #version 130
    in float at_coord_Y;
    
    void main() {
        float coord_X = float(gl_VertexID);
        gl_Position = vec4(coord_X,at_coord_Y,0.0,1.0);
    }
    

    在链接着色器程序之前,您应该将它的 at_coord_Y 绑定到您将使用的属性索引(在我的代码中为 =0):

    glBindAttribLocation(program_id,0,"at_coord_Y");
    

    或者,您可以在链接后询问程序自动分配此属性的索引,然后使用它:

    const int attrib_pos = glGetAttribLocation(program_id,"at_coord_Y");
    

    祝你好运!

    【讨论】:

    • 谢谢。我想我不清楚 OpenGL 是如何知道我想要 coord_X 表示顶点的索引的。
    • @Ben Voigt:我最初错过了,抱歉 :) 答案现在已修复(使用 gl_VertexID)。
    • 谢谢,现在更有意义了。我可以使用glDrawArrays 来渲染这个整体吗?我问是因为the manpage for glDrawArrays 说“如果未启用 GL_VERTEX_ARRAY,则不会生成几何图元。”这不适用于由着色器生成顶点位置的 OpenGL 3 世界吗?
    • @Ben Voigt。是的你可以。在 GL-3 世界中,您通过 glDraw* 调用绘制所有内容。您确实会在着色器中生成顶点位置(和其他变量),但必须有顶点属性作为数据源(至少必须启用一个),提供位置、法线、颜色、tex 坐标等。跨度>
    • 几乎成功了。但我仍然必须打开 GL_VERTEX_ARRAY 才能获得任何输出。我将开始一个新问题。
    【解决方案2】:

    你会在 VRAM 中存储一千万个 XY 坐标吗?

    我建议您在 CPU 上计算这些坐标,并将它们作为制服传递给着色器管道(因为坐标固定到平移图像)。

    保持简单。

    【讨论】:

    • 当我平移时,我需要从显示器中移除一些移出屏幕的线段,添加一些已显示的线段,并将其余部分偏移一个常数。在 CPU 上为几千个坐标添加一个常数很快,但是我必须再次将所有数据传输到 GPU,并且在平移时我必须在每一帧上执行此操作。好吧,即使是 60 FPS,这也不会占 PCIe 带宽的那么大,但为什么要浪费它呢?如果我简单地将要绘制的新的最左侧索引和新的翻译发送给它,GPU 可以很容易地进行数学运算,并且可以并行进行。
    • 抱歉,我无法理解您的做法。平移图像应通过平移纹理四边形(大于视口)来实现。纹理(可能)是常驻的,唯一的数据是用于平移纹理四边形的 X/Y 偏移量。多个四边形可用于显示多个图像。
    猜你喜欢
    • 1970-01-01
    • 2020-08-01
    • 2011-11-21
    • 2014-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多