public void renderAnimationFrame(
      Transform transform, int frame, Texture tex, boolean horizontalFlip) {
    GL20.glUseProgram(animSpriteShaderProgram.getProgramId());

    spriteVAO.bind();
    // GL30.glBindVertexArray(flatPlane.getVaoId());

    Matrix4f finalMatrix =
        rs.getCamera()
            .getProjectionMatrix()
            .multiply(rs.getCamera().getWorldMatrix().multiply(transform.toMatrix()));

    // Diffuse Texture
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL30.GL_TEXTURE_2D_ARRAY, tex.getTextureId());

    GL20.glUniformMatrix4fv(
        animSpriteShaderProgram.getUniform("mvpMatrix").getLocation(),
        false,
        finalMatrix.toBuffer());
    GL20.glUniform1i(animSpriteShaderProgram.getUniform("diffuseTextureAtlas").getLocation(), 0);
    GL20.glUniform1i(animSpriteShaderProgram.getUniform("currentFrame").getLocation(), frame);
    GL20.glUniform1i(
        animSpriteShaderProgram.getUniform("horizontalFlip").getLocation(),
        (horizontalFlip) ? GL11.GL_TRUE : GL11.GL_FALSE);

    GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, SPRITE_NUM_VERTICES);
  }
  public void renderSprite(Transform transform, Texture texture, boolean hFlip, boolean vFlip) {
    GL20.glUseProgram(spriteShaderProgram.getProgramId());

    spriteVAO.bind();

    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getTextureId());

    Matrix4f finalMatrix =
        rs.getCamera()
            .getProjectionMatrix()
            .multiply(rs.getCamera().getWorldMatrix().multiply(transform.toMatrix()));

    GL20.glUniformMatrix4fv(
        spriteShaderProgram.getUniform("mvpMatrix").getLocation(), false, finalMatrix.toBuffer());
    GL20.glUniform1i(
        spriteShaderProgram.getUniform("horizontalFlip").getLocation(),
        (hFlip) ? GL11.GL_TRUE : GL11.GL_FALSE);
    GL20.glUniform1i(
        spriteShaderProgram.getUniform("verticalFlip").getLocation(),
        (vFlip) ? GL11.GL_TRUE : GL11.GL_FALSE);
    GL20.glUniform1i(spriteShaderProgram.getUniform("sprite").getLocation(), 0);

    GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, SPRITE_NUM_VERTICES);
  }
  @Deprecated
  public void renderUISprite(Rectangle rect, Texture image, boolean hFlip, boolean vFlip) {
    GL20.glUseProgram(spriteShaderProgram.getProgramId());

    // Remember to change this calculation when I change the size of the flatplane
    Matrix4f modelMatrix =
        Matrix4f.translation(rect.getX(), rect.getY(), 0)
            .multiply(Matrix4f.scale(rect.getWidth(), rect.getHeight(), 1f));

    spriteVAO.bind();

    image.bind();
    // GL30.glBindVertexArray(flatPlane.getVaoId());

    GL20.glUniformMatrix4fv(
        spriteShaderProgram.getUniform("mvpMatrix").getLocation(), false, modelMatrix.toBuffer());
    GL20.glUniform1i(
        spriteShaderProgram.getUniform("horizontalFlip").getLocation(),
        (hFlip) ? GL11.GL_TRUE : GL11.GL_FALSE);
    GL20.glUniform1i(
        spriteShaderProgram.getUniform("verticalFlip").getLocation(),
        (vFlip) ? GL11.GL_TRUE : GL11.GL_FALSE);
    GL20.glUniform1i(spriteShaderProgram.getUniform("sprite").getLocation(), 0);

    GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, SPRITE_NUM_VERTICES);
  }
  public SpriteRenderer(RenderSystem rs) {
    this.rs = rs;

    spriteShaderProgram =
        new ShaderProgram(
            Resources.loadText("shader/default_vert.shader"),
            Resources.loadText("shader/sprite_frag.shader"));
    animSpriteShaderProgram =
        new ShaderProgram(
            Resources.loadText("shader/default_vert.shader"),
            Resources.loadText("shader/animsprite_frag.shader"));

    spriteVAO = new VertexArrayObject();
    spriteVAO.bind();
    spriteVAO.addArrayBuffer(0, Game.toBuffer(SPRITE_VERTS), 2, GL11.GL_FLOAT, Buffer.STATIC_DRAW);
    spriteVAO.addArrayBuffer(1, Game.toBuffer(SPRITE_UV), 2, GL11.GL_FLOAT, Buffer.STATIC_DRAW);
    spriteVAO.unbind();
  }
  public void destroy() {
    spriteShaderProgram.destroy();
    animSpriteShaderProgram.destroy();

    spriteVAO.destroy();
  }