title: OpenGL: Draw Multiple Linestrips Efficiently
body: <p>I'm new to openGL and I'm working on an application where I need to draw several linestrips each with several vertices.  All-together, we're talking about 300,000 vertices.</p>
  
  <p>In order to attempt to do this efficiently, I am using a VBO to store the vertex data.  </p>
  
  <p>I am using a single VBO for storing all the vertices for all the lines.   I then use <code>GLDrawElements</code> to draw the entire VBO, passing it an index array which specifies which indices to draw, and leveraging primitiveRestart to designate where Linestrips start/end (see code below).</p>
  
  <p>This does not execute as quickly I would've hoped. I can only render at about 10Hz.  I'm thinking perhaps it's that I'm passing a large array of indices which must get copied to the GPU each render.</p>
  
  <p>I'm having trouble determining the right direction to attempt to improve performance. Would shaders be the right way to go? Is there some way to NOT write the index array to the GPU during rendering (needed by DrawElements).</p>
  
  <p>Any help determinig the right direction to explore would be appreciated.</p>
  
  <p>I'm writing this in C# using openTK.</p>
  
  <pre class="lang-cs prettyprint-override"><code>    //Enabled Primitive Restart
      GL.Enable(EnableCap.PrimitiveRestart);
      GL.PrimitiveRestartIndex(PrimitiveRestartIndex);
  
      //Generate Linestrip data to buffer (array of vertices)
      int[] FrameData = ScanBuffer.getBufferData();
  
      //Create the buffer on the GPU
      ScanBuffer.vbo_id = new int[1];
      GL.GenBuffers(1, ScanBuffer.vbo_id);
  
      //Buffer the data
      GL.BindBuffer(BufferTarget.ArrayBuffer, ScanBuffer.vbo_id[0]);
      GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(sizeof(int) * FrameData.Length), FrameData, BufferUsageHint.StaticDraw);
      GL.VertexPointer(2, VertexPointerType.Int, 0, 0);
      GL.EnableClientState(ArrayCap.VertexArray);
  
      //Generate the vertex index array
      uint[] IndexData = ScanBuffer.getIndexData();
  
      //Draw the VBO
      GL.BindBuffer(BufferTarget.ArrayBuffer, ScanBuffer.vbo_id[0]);
      GL.VertexPointer(2, VertexPointerType.Int, 0, 0);
      GL.DrawElements(BeginMode.LineStrip, IndexData.Length, DrawElementsType.UnsignedInt, IndexData);
  </code></pre>
  
  <h1>UPDATE</h1>
  
  <p>I was able to find a viable solution using array element buffer to store my indicies. I get about 10X performance improvement. The buffer and render commands look as follows.</p>
  
  <h2>Buffer</h2>
  
  <pre class="lang-cs prettyprint-override"><code>    vertexData = generateVertexData();
      indexData = generateIndexData();
  
      //Bind to the VAO
      GL.BindVertexArray(vaoID[0]);
  
      //Bind + Write Index Data to the Buffer
      GL.BindBuffer(BufferTarget.ElementArrayBuffer, veoID[0]);
      GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(sizeof(uint) * IndexData.Count()), IndexData.ToArray(), BufferUsageHint.StaticDraw);
  
      //Bind + Write Scan Vertex Data to the Buffer
      GL.BindBuffer(BufferTarget.ArrayBuffer, vboID[0]);
      GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(sizeof(int) * VertexData.Count()), VertexData.ToArray(), BufferUsageHint.StaticDraw);
      GL.VertexPointer(2, VertexPointerType.Int, 0, 0);
      GL.EnableClientState(ArrayCap.VertexArray);
  
      //Remove Binding
      GL.BindVertexArray(0);
      GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
      GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
  </code></pre>
  
  <h2>RenderLoop</h2>
  
  <pre class="lang-cs prettyprint-override"><code>    //Enabled Primitive Restart
      GL.Enable(EnableCap.PrimitiveRestart);
      GL.PrimitiveRestartIndex(PrimitiveRestartIndex);
  
      GL.LineWidth(1);
      GL.Color3(Color.Red);
      GL.BindBuffer(BufferTarget.ArrayBuffer, vboID[0]);
      GL.VertexPointer(2, VertexPointerType.Int, 0, 0);
  
      //-Draw using a VEO-
      GL.BindBuffer(BufferTarget.ElementArrayBuffer, veoID[0]);
      GL.DrawElements(BeginMode.LineStrip, scanVertexBufferLength, DrawElementsType.UnsignedInt, 0);
      GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
      GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
      GL.BindVertexArray(0);
  
      GL.Disable(EnableCap.PrimitiveRestart);
  </code></pre>