Jump to content

  • Log In with Google      Sign In   
  • Create Account

#Actuallaztrezort

Posted 27 January 2013 - 02:49 PM

Just call glBufferSubData once when a batch is ready to be drawn, specifying the count or whatever parameter it is to set the amount of data to upload, and only draw the number of vertices (or indices if using draw elements) you need for the current batch.

The index buffer can be predifined, and will not change.

Here is some C#-ish pseudocode from a project of mine that outlines what I do:
spriteVertex[] vertices = new spriteVertex[BATCHSIZE * 4];
int[] indices = new int[BATCHSIZE * 6];

MakeBuffers(ref vertBufferID, ref indBufferID, ref vaoID);

// fill the buffer with default (0s) on creation
glBufferData(BufferTarget.ArrayBuffer, sizeof(spriteVertex) * vertices.Length, vertices);

// fill index buffer with pre-calc'd values
PreCalcIndexBuffer();

...

class TileBatch
{
  public void Begin(Texture2D texture)
  {
    currentSprite = 0;
    currentTexture = texture;
  }

  public void Draw(Rect dest, Rect src, Color color)
  {
    // if we are out of room, flush (draw) the current batch
    if(currentSprite > BATCHSIZE)
    {
      flush();
      currentSprite = 0;
    }

    // calc all the vertex attributes for this sprite and store them in our CPU array
    int vertStart = currentSprite * 4;
    vertices[vertStart].position.X = dest.X;
    vertices[vertStart].texcoord.X = src.X;
    ...
    vertices[vertStart + 3].position.Y = destRect.Bottom;
    vertices[vertStart + 3].texcoord.Y = src.Bottom;
    
    currentSprite++;
  }

  public void End()
  {
    Flush();
  }

  private void Flush()
  {
    // set program uniforms and state
    shaderProgram.Texture = currentTexture;
    shaderProgram.mvpMatrix = currentMVP;
    ...

    int numberToDraw = currentSprite;

    BindVAO();
    
    // upload our CPU vertex data to GPU
    glBufferSubData(BufferTarget.ArrayBuffer, 0, sizeof(SpriteVertex) * numberToDraw, vertices);
    
    // draw the appropriate number of sprites
    DrawElements(BeginMode.Triangles, numberToDraw);
  }
}

In use:
MyBatch.Begin(myTexture);

MyBatch.Draw(Rect(0,0,32,32), Rect(50,50,32,32), Color.White);
MyBatch.Draw(...)
...

MyBatch.End();

#2laztrezort

Posted 27 January 2013 - 02:46 PM

Just call glBufferSubData once when a batch is ready to be drawn, specifying the count or whatever parameter it is to set the amount of data to upload, and only draw the number of vertices (or indices if using draw elements) you need for the current batch.

The index buffer can be predifined, and will not change.

Here is some C#-ish pseudocode from a project of mine that outlines what I do:
spriteVertex[] vertices = new spriteVertex[BATCHSIZE * 4];
int[] indices = new int[BATCHSIZE * 6];

MakeBuffers(ref vertBufferID, ref indBufferID, ref vaoID);

glBufferData(BufferTarget.ArrayBuffer, sizeof(spriteVertex) * vertices.Length, vertices);
PreCalcIndexBuffer();

...

class TileBatch
{
  public void Begin(Texture2D texture)
  {
    currentSprite = 0;
    currentTexture = texture;
  }

  public void Draw(Rect dest, Rect src, Color color)
  {
    if(currentSprite > BATCHSIZE)
    {
      flush();
      currentSprite = 0;
    }

    int vertStart = currentSprite * 4;
    vertices[vertStart].position.X = dest.X;
    vertices[vertStart].texcoord.X = src.X;
    ...
    vertices[vertStart + 3].position.Y = destRect.Bottom;
    vertices[vertStart + 3].texcoord.Y = src.Bottom;
    
    currentSprite++;
  }

  public void End()
  {
    Flush();
  }

  private void Flush()
  {
    shaderProgram.Texture = currentTexture;
    shader.mvpMatrix = currentMVP;
    
    int numberToDraw = currentSprite;

    BindVAO();

    glBufferSubData(BufferTarget.ArrayBuffer, 0, sizeof(SpriteVertex) * numberToDraw, vertices);
    
    DrawElements(BeginMode.Triangles, numberToDraw);
  }
}

In use:
MyBatch.Begin(myTexture);

MyBatch.Draw(Rect(0,0,32,32), Rect(50,50,32,32), Color.White);
MyBatch.Draw(...)
...

MyBatch.End();

#1laztrezort

Posted 27 January 2013 - 02:45 PM

Just call glBufferSubData once when a batch is ready to be drawn, specifying the count or whatever parameter it is to set the amount of data to upload, and only draw the number of vertices (or indices if using draw elements) you need for the current batch.

The index buffer can be predifined, and will not change.

Here is some C#-ish pseudocode from a project of mine that outlines what I do:
spriteVertex[] vertices = new spriteVertex[BATCHSIZE * 4];
int[] indices = new int[BATCHSIZE * 6];

MakeBuffers(ref vertBufferID, ref indBufferID, vaoID);

glBufferData(BufferTarget.ArrayBuffer, sizeof(spriteVertex) * vertices.Length, vertices);
PreCalcIndexBuffer();

...

class TileBatch
{
  public void Begin(Texture2D texture)
  {
    currentSprite = 0;
    currentTexture = texture;
  }

  public void Draw(Rect dest, Rect src, Color color)
  {
    if(currentSprite > BATCHSIZE)
    {
      flush();
      currentSprite = 0;
    }

    int vertStart = currentSprite * 4;
    vertices[vertStart].position.X = dest.X;
    vertices[vertStart].texcoord.X = src.X;
    ...
    vertices[vertStart + 3].position.Y = destRect.Bottom;
    vertices[vertStart + 3].texcoord.Y = src.Bottom;
    
    currentSprite++;
  }

  public void End()
  {
    Flush();
  }

  private void Flush()
  {
    shaderProgram.Texture = currentTexture;
    shader.mvpMatrix = currentMVP;
    
    int numberToDraw = currentSprite;

    BindVAO();

    glBufferSubData(BufferTarget.ArrayBuffer, 0, sizeof(SpriteVertex) * numberToDraw, vertices);
    
    DrawElements(BeginMode.Triangles, numberToDraw);
  }
}

In use:
MyBatch.Begin(myTexture);

MyBatch.Draw(Rect(0,0,32,32), Rect(50,50,32,32), Color.White);
MyBatch.Draw(...)
...

MyBatch.End();

PARTNERS