使用VBO / IBO绘制一个大图

时间:2014-10-21 00:58:47

标签: c# opengl vbo opentk

我试图使用OpenTK绘制一个大图(~3,000,000个顶点,~3,000,000个边)。

但我似乎无法让它发挥作用。

我创建一个包含所有顶点位置的VBO,如此

// build the coords list
float[] coords = new float[vertices.Length * 3];
Dictionary<int, int> vertexIndexMap = new Dictioanry<int, int>();
int count = 0, i = 0;
foreach (Vertex v in vertices) {
    vertexIndexMap[v.Id] = i++;
    coords[count++] = v.x;
    coords[count++] = v.y;
    coords[count++] = v.z;
}

// build the index list
int[] indices = new int[edges.Length * 2];
count = 0;
foreach (Edge e in edges) {
    indices[count++] = vertexIndexMap[e.First.Id];
    indices[count++] = vertexIndexMap[e.Second.Id];
}

// bind the buffers
int[] bufferPtrs = new int[2];
GL.GenBuffers(2, bufferPtrs);

GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.IndexArray);

// buffer the vertex data
GL.BindBuffer(BufferTarget.ArrayBuffer, bufferPtrs[0]);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(coords.Length * sizeof(float)), coords, BufferUsageHint.StaticDraw);
GL.VertexPointer(3, VertexPointerType.Float, 0, IntPtr.Zero); // tell opengl we have a closely packed vertex array
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

// buffer the index data
GL.BindBuffer(BufferTarget.ElementArrayBuffer, bufferPtrs[1]);
GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(int)), indices, BufferUsageHint.StaticDraw);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);

我试图像这样绘制缓冲区:

// draw the vertices
GL.BindBuffer(BufferTarget.ArrayBuffer, bufferPtrs[0]);
GL.Color3(Color.Blue);
GL.DrawArrays(PrimitiveType.Points, 0, coords.Length);

// draw the edges
GL.BindBuffer(BufferTarget.ElementArrayBuffer, bufferPtrs[1]);
GL.Color3(Color.Red);
GL.DrawElements(PrimitiveType.Lines, indices.Length, DrawElementsType.UnsignedInt, bufferPtrs[1]);

当我运行它时,所有顶点都按预期在所有正确位置绘制,
但是,大约一半的边缘被绘制为将顶点连接到原点。

为了进行健全性检查,我尝试使用Begin / End块绘制边缘,并且它们都正确绘制。

有人可以指出我是如何滥用维也纳国际组织的吗?

1 个答案:

答案 0 :(得分:3)

DrawElements()来电的最后一个参数是错误的:

GL.DrawElements(PrimitiveType.Lines, indices.Length, DrawElementsType.UnsignedInt,
                bufferPtrs[1]);

没有元素数组缓冲区外,DrawElements()的最后一个参数是指向索引的指针。如果绑定了元素数组缓冲区(在代码中就是这种情况),则最后一个参数是缓冲区的偏移量。要使用整个缓冲区,偏移量为0:

GL.DrawElements(PrimitiveType.Lines, indices.Length, DrawElementsType.UnsignedInt, 0);

您可能还想删除此电话:

GL.EnableClientState(ArrayCap.IndexArray);

这不是用于启用顶点索引,而是用于颜色索引。这将是颜色索引模式,这是一个非常过时的功能。