private boolean initBuffer(GL3 gl3) {

    ShortBuffer elementBuffer = GLBuffers.newDirectShortBuffer(elementData);
    FloatBuffer vertexBuffer = GLBuffers.newDirectFloatBuffer(vertexData);
    IntBuffer uniformBufferOffset = GLBuffers.newDirectIntBuffer(1);

    gl3.glGenBuffers(Buffer.MAX, bufferName);

    gl3.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName.get(Buffer.ELEMENT));
    gl3.glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementSize, elementBuffer, GL_STATIC_DRAW);
    gl3.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    gl3.glBindBuffer(GL_ARRAY_BUFFER, bufferName.get(Buffer.VERTEX));
    gl3.glBufferData(GL_ARRAY_BUFFER, vertexSize, vertexBuffer, GL_STATIC_DRAW);
    gl3.glBindBuffer(GL_ARRAY_BUFFER, 0);

    gl3.glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, uniformBufferOffset);
    int uniformBlockSize = Math.max(Mat4.SIZE, uniformBufferOffset.get(0));

    gl3.glBindBuffer(GL_UNIFORM_BUFFER, bufferName.get(Buffer.TRANSFORM));
    gl3.glBufferData(GL_UNIFORM_BUFFER, uniformBlockSize, null, GL_DYNAMIC_DRAW);
    gl3.glBindBuffer(GL_UNIFORM_BUFFER, 0);

    BufferUtils.destroyDirectBuffer(elementBuffer);
    BufferUtils.destroyDirectBuffer(vertexBuffer);
    BufferUtils.destroyDirectBuffer(uniformBufferOffset);

    return checkError(gl3, "initBuffer");
  }
  private boolean initBuffer(GL4 gl4) {

    boolean validated = true;

    gl4.glGenBuffers(Buffer.MAX, bufferName);

    gl4.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferName.get(Buffer.ELEMENT));
    ShortBuffer elementBuffer = GLBuffers.newDirectShortBuffer(elementData);
    gl4.glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementSize, elementBuffer, GL_STATIC_DRAW);
    BufferUtils.destroyDirectBuffer(elementBuffer);
    gl4.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    gl4.glBindBuffer(GL_ARRAY_BUFFER, bufferName.get(Buffer.VERTEX));
    FloatBuffer vertexBuffer = GLBuffers.newDirectFloatBuffer(vertexData);
    gl4.glBufferData(GL_ARRAY_BUFFER, vertexSize, vertexBuffer, GL_STATIC_DRAW);
    BufferUtils.destroyDirectBuffer(vertexBuffer);
    gl4.glBindBuffer(GL_ARRAY_BUFFER, 0);

    int[] uniformBufferOffset = {0};
    gl4.glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, uniformBufferOffset, 0);
    int uniformBlockSize = Math.max(Mat4.SIZE, uniformBufferOffset[0]);

    gl4.glBindBuffer(GL_UNIFORM_BUFFER, bufferName.get(Buffer.TRANSFORM));
    gl4.glBufferData(GL_UNIFORM_BUFFER, uniformBlockSize, null, GL_DYNAMIC_DRAW);
    gl4.glBindBuffer(GL_UNIFORM_BUFFER, 0);

    return validated;
  }
  @Override
  protected boolean end(GL gl) {

    GL3 gl3 = (GL3) gl;

    gl3.glDeleteBuffers(1, bufferName);
    gl3.glDeleteProgram(programName);
    gl3.glDeleteTextures(1, textureName);
    gl3.glDeleteVertexArrays(1, vertexArrayName);

    BufferUtils.destroyDirectBuffer(bufferName);
    BufferUtils.destroyDirectBuffer(textureName);
    BufferUtils.destroyDirectBuffer(vertexArrayName);

    return checkError(gl3, "end");
  }
  @Override
  protected boolean end(GL gl) {

    GL3 gl3 = (GL3) gl;

    gl3.glDeleteProgram(programName);
    gl3.glDeleteBuffers(Buffer.MAX, bufferName);
    gl3.glDeleteTextures(1, textureName);
    gl3.glDeleteVertexArrays(1, vertexArrayName);

    BufferUtils.destroyDirectBuffer(bufferName);
    BufferUtils.destroyDirectBuffer(textureName);
    BufferUtils.destroyDirectBuffer(vertexArrayName);

    BufferUtils.destroyDirectBuffer(clearColor);

    return true;
  }
  @Override
  protected boolean end(GL gl) {

    GL4 gl4 = (GL4) gl;

    gl4.glDeleteProgramPipelines(1, pipelineName);
    BufferUtils.destroyDirectBuffer(pipelineName);
    gl4.glDeleteProgram(programName[Program.FRAGMENT]);
    gl4.glDeleteProgram(programName[Program.VERTEX]);
    gl4.glDeleteBuffers(Buffer.MAX, bufferName);
    BufferUtils.destroyDirectBuffer(bufferName);
    gl4.glDeleteTextures(1, textureName);
    BufferUtils.destroyDirectBuffer(textureName);
    gl4.glDeleteVertexArrays(1, vertexArrayName);
    BufferUtils.destroyDirectBuffer(vertexArrayName);

    return true;
  }
  private boolean initBuffer(GL3 gl3) {

    FloatBuffer vertexBuffer = GLBuffers.newDirectFloatBuffer(vertexData);

    gl3.glGenBuffers(1, bufferName);

    gl3.glBindBuffer(GL_ARRAY_BUFFER, bufferName.get(0));
    gl3.glBufferData(GL_ARRAY_BUFFER, vertexSize, vertexBuffer, GL_STATIC_DRAW);
    gl3.glBindBuffer(GL_ARRAY_BUFFER, 0);

    BufferUtils.destroyDirectBuffer(vertexBuffer);

    return checkError(gl3, "initBuffer");
  }
  private boolean initTexture(GL3 gl3) {

    IntBuffer textureSize = GLBuffers.newDirectIntBuffer(1);

    try {
      gl3.glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

      gl3.glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, textureSize);

      gl3.glGenTextures(1, textureRectName);

      gl3.glActiveTexture(GL_TEXTURE0);
      gl3.glBindTexture(GL_TEXTURE_RECTANGLE, textureRectName.get(0));
      gl3.glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_BASE_LEVEL, 0);
      gl3.glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAX_LEVEL, 0);
      gl3.glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      gl3.glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

      jgli.Texture2d texture = new Texture2d(jgli.Load.load(TEXTURE_ROOT + "/" + TEXTURE_DIFFUSE));
      jgli.Gl.Format format = jgli.Gl.translate(texture.format());

      assert (texture.dimensions()[0] <= textureSize.get(0)
          && texture.dimensions()[1] <= textureSize.get(0));

      gl3.glTexImage2D(
          GL_TEXTURE_RECTANGLE,
          0,
          format.internal.value,
          texture.dimensions()[0],
          texture.dimensions()[1],
          0,
          format.external.value,
          format.type.value,
          texture.data());

      gl3.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    } catch (IOException ex) {
      Logger.getLogger(Gl_330_texture_rect.class.getName()).log(Level.SEVERE, null, ex);
    }

    BufferUtils.destroyDirectBuffer(textureSize);

    return true;
  }