使用VBO绘制线串

时间:2015-08-19 09:40:39

标签: opengl vector shader vbo polyline

我可以使用OpenGL 4.x中的VBO和着色器渲染以下点。

    typedef struct Point
    {
        double x,y,z,w;
    }Point;

    std::vector<Point>vPoints;

    glBufferData(GL_ARRAY_BUFFER,  vPoints.size()* sizeof(Point),  &vPoints[0], GL_STATIC_DRAW);
    glVertexAttribPointer(0, 4, GL_DOUBLE, GL_FALSE, vPoints.size()*sizeof(GLdouble), (GLvoid*)0)

我们如何指定VBO使用以下变量绘制线串

    typedef struct LineString
    {
     vector<Point> vPointList;

    }LineString;
    vector<LineString> vLines;
    glBufferData(GL_ARRAY_BUFFER,  ????,  ????, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 4, GL_DOUBLE, GL_FALSE, ????, (GLvoid*)0)

我尝试了下面的设置,它似乎无法正常工作

   glBufferData(GL_ARRAY_BUFFER,  vLines.size()* sizeof(LineString)*sizeof(Point),  &vLines[0].vPointList[0], GL_STATIC_DRAW);
   glVertexAttribPointer(0, 4, GL_DOUBLE, GL_FALSE, vLines.size()*sizeof(GLdouble), (GLvoid*)0);   

我以为我差不多用下面的代码来创建VBO

         for(int i=0;i< vLines.size();i++)
           pt_count += vLines[i].vPointList.size();

  fprintf( stdout, "Total point Count: %d\n", pt_count);    
  glBufferData(GL_ARRAY_BUFFER, pt_count * sizeof(Point), nullptr, GL_STATIC_DRAW);

size_t start = 0;
for(int i=0;i< vLines.size();i++)
{
    size_t v_size =vLines[i].vPointList.size() * sizeof(Point);
    glBufferSubData(GL_ARRAY_BUFFER, start, v_size, &vLines[i].vPointList[0]);
    start += v_size;
}

if(start == pt_count * sizeof(Point) )
{
    fprintf( stdout, "INFO: %s\n", "Same count");   

}

glVertexAttribPointer(0,4,GL_DOUBLE,GL_FALSE,4 * sizeof(GLdouble),(GLvoid *)0);

和绘图调用。我注意到第一行的最后一点是连接到该行的第一个点。

    glDrawArrays(GL_LINE_STRIP, 0,pt_count);

2 个答案:

答案 0 :(得分:2)

<强> glBufferData

对于glBufferData,需要以字节为单位的数据总大小。此外,还需要一个连续的内存段,vector<vector<T>>不提供。从技术上讲,每个内部向量都有自己的存储器段,存储数据,这使得无法一次上传数据。我想到的唯一方法是首先计算这样的总大小:

size_t pt_count = 0;
for (auto& v : vLines)
    pt_count += v.vPointList.size();

分配GPU内存,但不上传任何数据

glBufferData(GL_ARRAY_BUFFER, pt_count * sizeof(Point), nullptr, GL_STATIC_DRAW);

最后一步是逐步上传所有要点:

size_t start = 0;
for (auto& v : vLines)
{
    size_t v_size = v.vPointList.size() * sizeof(Point);
    glBufferSubData(GL_ARRAY_BUFFER, start, v_size, &v.vPointList[0]);
    start += v_size;
}

但是,如果您可以更改C ++代码中的数据布局,我强烈建议您首先将所有点存储在连续的内存段中。

glVertexAttribPointer

glVertexAttribPointer的第五个参数告诉OpenGL缓冲区中连续顶点之间的偏移量。所以想想这样的缓冲区:

        | x | y | z | w | x | y | z | w |
stride  |-------------->|-------------->|

这是必要的,因为可能的是,在两个顶点条目之间存储附加数据。在您的情况下,偏移量必须是4 * sizeof(GLdouble),或者由于数据紧密打包,0:

  

指定连续通用顶点属性之间的字节偏移量。如果stride为0,则通用顶点属性被理解为紧密打包在数组中。初始值为0。   reference

答案 1 :(得分:0)

可以通过使用glMultiDrawArrays()来解决这个问题。通过正确指定索引位置找到解决方案。修复后的代码如下所示。

//globals
size_t pt_count = 0;
GLint  *startIndices;
GLint *endIndices;
GLint nLineCount;


//create the VBO
for(int i=0;i< vLines.size();i++)
    pt_count += vLines[i].vPointList.size();


  startIndices= new GLint[vLines.size()];
  endIndices= new GLint[vLines.size()];


  fprintf( stdout, "Total point Count: %d\n", pt_count);    
  glBufferData(GL_ARRAY_BUFFER, pt_count * sizeof(POINT), nullptr, GL_STATIC_DRAW);

    size_t start = 0;
    size_t firsts=0;
    for(int i=0;i< vLines.size();i++)
    {


        size_t v_size =vLines[i].vPointList.size() * sizeof(POINT);

        glBufferSubData(GL_ARRAY_BUFFER, start, v_size, &vLines[i].vPointList[0]);
        start += v_size;

        startIndices[i]=firsts;
        endIndices[i]=vLines[i].vPointList.size();
        firsts+=endIndices[i];
        fprintf( stdout, "start: %d\n",startIndices[i]);
        fprintf( stdout, "size: %d\n", endIndices[i] );

    } 


    if(start == pt_count * sizeof(POINT) )
    {
        fprintf( stdout, "INFO: %s\n", "Same count");   

    }

  glVertexAttribPointer(0, 4, GL_DOUBLE, GL_FALSE,  4 * sizeof(GLdouble), (GLvoid*)0);

  nLineCount=vLines.size();
  vLines.clear();
 //Draw the lines
 glMultiDrawArrays(GL_LINE_STRIP, startIndices,endIndices,nLineCount);