title: OpenGl c#: Is this speed acceptable?
body: <p>I'm making a 2d engine in OpenGl c# using opentk. i draw 36500 sprites @ 45 fps and 50000 sprites @ 30 fps. Im on a laptop, but with good specs. it can run crysis3 on very high smooth. specs: i7 4810mq quad core @ 3.8 ghz 6mb cache, gtx 870m, 8gb ram. now i think my program is being slow... i use vbo's. each sprite is made out of 6 vertices, 2 triangles. they are textured. indexing doesn't seem to improve the speed. the class vbo contains integers that stre the vbo id. vbodata contains arrays of vertex,texture and indices data. the renderer class contains more renderercores rendercore code:</p>
  
  <pre><code>using OpenTK.Graphics.OpenGL;
  using System;
  using System.Threading;
  
  namespace TortoiseEngineBuilder
  {
  public class RendererCore
  {
      private VBO vbos;
      private VBOData data;
      private int verCount;
      private int texCount;
      private int indCount;
  
      public RendererCore()
      {
          vbos = new VBO();
          data = new VBOData();
          Console.WriteLine("init renderer");
      }
  
      public void AddData(Sprite sprite, bool debug = false, int dVBO = 0, int dStart = 0, int dEnd = 100)
      {
          //vertices + indices
          for (int i = 0; i &lt; sprite.VertexData.Length; i++)
          {
              data.VertexData[verCount + i] = sprite.VertexData[i];
          }
          for (int i = 0; i &lt; sprite.IndicesData.Length; i++)
          {
              data.IndicesData[indCount + i] = (uint)((indCount) + sprite.IndicesData[i]);
          }
          //textures
          for (int i = 0; i &lt; sprite.TextureData.Length; i++)
          {
              data.TextureData[texCount + i] = sprite.TextureData[i];
          }
          texCount += sprite.TextureData.Length;
          verCount += sprite.VertexData.Length;
          indCount += sprite.IndicesData.Length;
          if (debug) OutPutArraysVbo(dStart, dEnd);
      }
  
      public void ClearData()
      {
          data = new VBOData();
      }
  
      public void SetVBOFromData()
      {
          VBOData d = new VBOData(verCount, texCount, indCount);
          for (int i = 0; i &lt; verCount; i++)
          {
              d.VertexData[i] = data.VertexData[i];
          }
          for (int i = 0; i &lt; texCount; i++)
          {
              d.TextureData[i] = data.TextureData[i];
          }
          for (int i = 0; i &lt; indCount; i++)
          {
              d.IndicesData[i] = data.IndicesData[i];
          }
          SetVBO(ref d);
          System.GC.Collect();
      }
  
      public void CreateVBO()
      {
          GL.GenBuffers(1, out vbos.textureBufferID);
          GL.GenBuffers(1, out vbos.vertexBufferID);
          GL.GenBuffers(1, out vbos.indiciesBufferID);
          Console.WriteLine(vbos.textureBufferID + ":" + vbos.textureBufferID + ":" + vbos.indiciesBufferID);
      }
  
      public void SetVBO(ref VBOData vboData)
      {
          // TexCoord Array Buffer
          {
              GL.BindBuffer(BufferTarget.ArrayBuffer, vbos.textureBufferID);
              GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vboData.TextureData.Length * sizeof(float)), vboData.TextureData, BufferUsageHint.StaticDraw);
              GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
          }
          // Vertex Array Buffer
          {
              GL.BindBuffer(BufferTarget.ArrayBuffer, vbos.vertexBufferID);
              GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(vboData.VertexData.Length * sizeof(float)), vboData.VertexData, BufferUsageHint.StaticDraw);
              GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
          }
          // Element Array Buffer
          {
              GL.BindBuffer(BufferTarget.ElementArrayBuffer, vbos.indiciesBufferID);
              GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(vboData.IndicesData.Length * sizeof(int)), vboData.IndicesData, BufferUsageHint.StaticDraw);
              GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
          }
          vbos.elementCount = vboData.IndicesData.Length - 6;
      }
  
      public void DrawVBO(int textureID)
      {
          GL.EnableVertexAttribArray(0);
          // Texture Data Buffer Binding
          {
              GL.EnableClientState(ArrayCap.TextureCoordArray);
              GL.BindBuffer(BufferTarget.ArrayBuffer, vbos.textureBufferID);
              GL.TexCoordPointer(2, TexCoordPointerType.Float, sizeof(float) * 2, IntPtr.Zero);
              GL.BindTexture(TextureTarget.Texture2D, textureID);
          }
          // Vertex Array Buffer
          {
              GL.EnableClientState(ArrayCap.VertexArray);
              GL.BindBuffer(BufferTarget.ArrayBuffer, vbos.vertexBufferID);
              GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, sizeof(float)*3, 0);
          }
          // Element Array Buffer
          {
              GL.Enable(EnableCap.IndexArray);
              GL.IndexPointer(IndexPointerType.Int, sizeof(uint), IntPtr.Zero);
              GL.BindBuffer(BufferTarget.ElementArrayBuffer, vbos.indiciesBufferID);
          }
          //draw
          {
              GL.DrawElements(PrimitiveType.Triangles, indCount, DrawElementsType.UnsignedInt, vbos.indiciesBufferID);
              GL.DisableClientState(ArrayCap.VertexArray);
              GL.DisableVertexAttribArray(0);
          }
      }
  
      public void OutPutArraysVbo(int begin, int end, bool vertex = true, bool textures = false, bool indices = false)
      {
          for (int i = begin; i &lt; end; i++)
          {
              if (vertex) Console.WriteLine("VertexData[" + i + "]= " + data.VertexData[i]);
          }
          Console.WriteLine("---------------------------------");
          for (int i = begin; i &lt; end; i++)
          {
              if (textures) Console.WriteLine("TextureData[" + i + "]= " + data.TextureData[i]);
          }
          Console.WriteLine("---------------------------------");
          for (int i = begin; i &lt; end; i++)
          {
              if (indices) Console.WriteLine("IndicesData[" + i + "]= " + data.IndicesData[i]);
          }
          Console.WriteLine("===================================");
      }
  
      public void OutPutArraysData(VBOData data, int begin, int end, bool vertex = true, bool textures = false, bool indices = false)
      {
          for (int i = begin; i &lt; end; i++)
          {
              if (vertex) Console.WriteLine("VertexData[" + i + "]= " + data.VertexData[i]);
          }
          Console.WriteLine("---------------------------------");
          for (int i = begin; i &lt; end; i++)
          {
              if (textures) Console.WriteLine("TextureData[" + i + "]= " + data.TextureData[i]);
          }
          Console.WriteLine("---------------------------------");
          for (int i = begin; i &lt; end; i++)
          {
              if (indices) Console.WriteLine("IndicesData[" + i + "]= " + data.IndicesData[i]);
          }
          Console.WriteLine("===================================");
      }
  }
  </code></pre>
  
  <p>}</p>
  
  <p>main program code:</p>
  
  <pre><code>using System;
  using System.Drawing;
  using System.Drawing.Imaging;
  using System.Runtime.InteropServices;
  using System.Xml.Serialization;
  
  using OpenTK;
  using OpenTK.Graphics.OpenGL;
  using System.Threading;
  </code></pre>
  
  <p>namespace TortoiseEngineBuilder
     {
      public class MainThread : GameWindow
      {<br>
          FPS FpsCounter;
          Random r;
          Renderer renderer;
          TextureManager textureLoader;</p>
  
  <pre><code>    int WWidth = 1920;
      int WHeight = 1080;
      string WTitle = "TortoiseEngine3";
  
      int sprites_vbo = 36500;
      int sprites;
      ThreadTask t;
  
      public MainThread()
      {
          Console.WriteLine("init display BEGIN");
          //init console
          Console.WriteLine("Constructor Called Succesful!");
          Console.WriteLine("Press a Key to proceed running the constructor");
          Console.ReadKey();
          Console.Title = WTitle;
          Console.ForegroundColor = ConsoleColor.Green;
          //init display
          Title = WTitle;
          Width = WWidth;
          Height = WHeight;
          //init obj's that are always needed
          FpsCounter = new FPS();
          renderer = new Renderer();
          textureLoader = new TextureManager();
          renderer.Init(WWidth, WHeight, WWidth, WHeight);
          //set some GL.{}
          GL.ClearColor(Color.Black);
          Console.WriteLine("init display COMPLETE");
          //instantiate game obj's
          r = new Random();
          //feed the GPU
          for (int i = 0; i &lt; sprites_vbo; i++)
          {
              renderer.AddData(0, new Sprite(r.Next(1920), r.Next(1080), r.Next(50, 100), r.Next(50, 100)));
              renderer.AddData(10,new Sprite(r.Next(1920), r.Next(1080), r.Next(50,100), r.Next(50,100)));
          }
          renderer.AddData(0,new Sprite(0,0,0,0));
          renderer.AddData(10,new Sprite(0,0,0,0));
          renderer.Create(0);
          renderer.Set(0);
          //renderer.Create(10);
          //renderer.Set(10);
          renderer.GetArrayData(0,0,200,false,false,true);
          sprites = sprites_vbo;
      }
  
      protected override void OnLoad(EventArgs e)
      {
          Console.WriteLine("init textures BEGIN");
          textureLoader.SaveTexture("assets/smile_blue.png", "smileBlue");
          textureLoader.SaveTexture("assets/smile_red.png", "smileRed");
          Console.WriteLine("init textures COMPLETE");
      }
  
      protected override void OnUpdateFrame(FrameEventArgs e)
      {
          base.OnUpdateFrame(e);
          //renderer.AddData(0, new Sprite(r.Next(1920/2),r.Next(1080),r.Next(50,100),r.Next(50,100)));
          //renderer.AddData(10, new Sprite(r.Next(1920/2,1920), r.Next(1080), r.Next(50, 100), r.Next(50, 100)));
          //renderer.AddData(0, new Sprite(r.Next(1920 / 2), r.Next(1080), r.Next(50, 100), r.Next(50, 100)));
          //renderer.AddData(10, new Sprite(r.Next(1920 / 2, 1920), r.Next(1080), r.Next(50, 100), r.Next(50, 100)));
          renderer.Set(0);
          //renderer.Set(10);
  
          //sprites += 4;
          Title = "sprites: " + sprites + " FPS: " + FpsCounter.GetFPS();
      }
  
      protected override void OnRenderFrame(FrameEventArgs e)
      {
          base.OnRenderFrame(e);
          renderer.Init(Width,Height,WWidth,WHeight);
          renderer.Start(Width, Height);
          {
              renderer.Draw(0,textureLoader.getTexture("smileBlue"));
              //renderer.Draw(10, textureLoader.getTexture("smileRed"));
          }
          renderer.End(this);
          renderer.CheckError();
      }
      public static void Main(string[] args)
      {
          using (MainThread p = new MainThread())
          {
              Console.WriteLine("RUN");
              p.Run();
          }
      }
  }
  </code></pre>
  
  <p>}</p>
  
  <p>is this code slow?(when compared)<br/>
  if it is: what is the expected performance if it would run efficient?<br/>
  if it is: what can i do to improve the speed?<br/></p>