     (GL11/glTexParameteri GL11/GL_TEXTURE_2D GL11/GL_TEXTURE_MIN_FILTER GL11/GL_NEAREST)
     (GL11/glTexParameteri GL11/GL_TEXTURE_2D GL11/GL_TEXTURE_MAG_FILTER GL11/GL_NEAREST)
     (GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL30/GL_RGBA8UI width height 0 GL30/GL_RGBA_INTEGER GL11/GL_INT texture-buffer)
+    (GL11/glBindTexture GL11/GL_TEXTURE_2D 0)
     texture-id))
 
-(defn- get-fields [#^Class static-class]
-  (. static-class getFields))
-
-(defn- gl-enum-name
-  "Takes the numeric value of a gl constant (i.e. GL_LINEAR), and gives the name"
-  [enum-value]
-  (if (= 0 enum-value)
-    "NONE"
-    (.getName #^Field (some
-                       #(if (= enum-value (.get #^Field % nil)) % nil)
-                       (mapcat get-fields [GL11 GL12 GL13 GL15 GL20 GL30])))))
-
-(defn- except-gl-errors
-  [msg]
-  (let [error (GL11/glGetError)
-        error-string (str "OpenGL Error(" error "):"
-                          (gl-enum-name error) ": " msg " - "
-                          (Util/translateGLErrorString error))]
-    (if (not (zero? error))
-      (throw (Exception. error-string)))))
-
+
+(defn- fbo-texture [width height]
+  (let [id (GL30/glGenFramebuffers)]
+    (GL30/glBindFramebuffer GL30/GL_FRAMEBUFFER id)
+    (let [texture-id (GL11/glGenTextures)
+          draw-buffer (BufferUtils/createIntBuffer 1)]
+      (.put draw-buffer GL30/GL_COLOR_ATTACHMENT0)
+      (.flip draw-buffer)
+      ;;(.order texture-buffer (ByteOrder/nativeOrder))
+      (GL11/glBindTexture GL11/GL_TEXTURE_2D texture-id)
+      (GL11/glTexParameteri GL11/GL_TEXTURE_2D GL11/GL_TEXTURE_MIN_FILTER GL11/GL_NEAREST)
+      (GL11/glTexParameteri GL11/GL_TEXTURE_2D GL11/GL_TEXTURE_MAG_FILTER GL11/GL_NEAREST)
+      (GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL11/GL_RGB width height 0 GL11/GL_RGB GL11/GL_UNSIGNED_BYTE nil)
+      (GL32/glFramebufferTexture GL30/GL_FRAMEBUFFER GL30/GL_COLOR_ATTACHMENT0 texture-id 0)
+      (GL20/glDrawBuffers draw-buffer)
+      (GL11/glBindTexture GL11/GL_TEXTURE_2D 0)
+      (except-gl-errors "end of fbo-texture")
+      (when (not= (GL30/glCheckFramebufferStatus GL30/GL_FRAMEBUFFER) GL30/GL_FRAMEBUFFER_COMPLETE)
+        (throw (Exception. "Framebuffer not complete")))
+      [id texture-id])))
+        
 (defn png-bytes [path]
   (let [input-stream (FileInputStream. (str path))
         decoder (PNGDecoder. input-stream)

          ;; We just need one vertex buffer, a texture-mapped quad will suffice for drawing the terminal.
          {:keys [vertices-vbo-id
                  vertices-count
                  texture-coords-vbo-id]} (with-gl-context gl-lock (init-buffers))
          u-MVMatrix                (with-gl-context gl-lock (GL20/glGetUniformLocation pgm-id "uMVMatrix"))
          u-PMatrix                 (with-gl-context gl-lock (GL20/glGetUniformLocation pgm-id "uPMatrix"))
          u-font                    (with-gl-context gl-lock (GL20/glGetUniformLocation pgm-id "uFont"))

     (GL11/glTexParameteri GL11/GL_TEXTURE_2D GL11/GL_TEXTURE_MIN_FILTER GL11/GL_NEAREST)
     (GL11/glTexParameteri GL11/GL_TEXTURE_2D GL11/GL_TEXTURE_MAG_FILTER GL11/GL_NEAREST)
     (GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL11/GL_RGBA width height 0 GL11/GL_RGBA GL11/GL_UNSIGNED_BYTE texture-buffer)
     (GL11/glBindTexture GL11/GL_TEXTURE_2D 0)
     texture-id)))

(defn- xy-texture-id [^long width ^long height ^ByteBuffer texture-buffer]
