【问题标题】:Using VBO/IBOs to draw a large graph使用 VBO/IBO 绘制大图
【发布时间】:2014-10-21 00:58:46
【问题描述】:

我正在尝试使用 OpenTK 绘制一个大图(~3,000,000 个顶点,~5,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 块绘制边缘,并且它们都正确绘制。

有人可以指出我是如何滥用 VBO 的吗?

【问题讨论】:

    标签: c# opengl vbo opentk


    【解决方案1】:

    DrawElements() 调用的最后一个参数是错误的:

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

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

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

    您可能还想删除此调用:

    GL.EnableClientState(ArrayCap.IndexArray);
    

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

    【讨论】:

    • 哇,这完全是错误的。我在doco里错过了!多谢了。并感谢您指出 IndexArray。
    猜你喜欢
    • 2020-07-21
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 2012-01-22
    • 2012-07-24
    • 1970-01-01
    相关资源
    最近更新 更多