我可以使用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);
答案 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);