func (a *TextureAtlas) Allocate(width, height int) (AtlasRegion, bool) {
	var region AtlasRegion
	region.X = 0
	region.Y = 0
	region.W = width
	region.H = height
	bestIndex := -1
	bestWidth := 1<<31 - 1
	bestHeight := 1<<31 - 1
	for index := range a.nodes {
		y := a.fit(index, width, height)
		if y < 0 {
			continue
		}
		node := a.nodes[index]
		if ((y + height) < bestHeight) || (((y + height) == bestHeight) && (node.z < bestWidth)) {
			bestHeight = y + height
			bestIndex = index
			bestWidth = node.z
			region.X = node.x
			region.Y = y
		}
	}
	if bestIndex == -1 {
		return region, false
	}
	a.nodes = append(a.nodes, atlasNode{})
	copy(a.nodes[bestIndex+1:], a.nodes[bestIndex:])
	a.nodes[bestIndex] = atlasNode{region.X, region.Y + height, width}
	for i := bestIndex + 1; i < len(a.nodes); i++ {
		curr := &a.nodes[i]
		prev := &a.nodes[i-1]
		if curr.x >= prev.x+prev.z {
			break
		}
		shrink := prev.x + prev.z - curr.x
		curr.x += shrink
		curr.z -= shrink
		if curr.z > 0 {
			break
		}
		copy(a.nodes[i:], a.nodes[i+1:])
		a.nodes = a.nodes[:len(a.nodes)-1]
		i--
	}
	a.merge()
	a.used += uint(width * height)
	return region, true
}
Allocate allocates a new region of the given dimensions in the atlas.
It returns false if the allocation failed. This can happen when the
specified dimensions exceed atlas bounds, or the atlas is full.
package glh
import (
	"github.com/go-gl/gl"
	"image"
	"image/png"
	"os"
)
type atlasNode struct {
	x int  
	y int  
	z int  
}
type AtlasRegion struct {
	X int
	Y int
	W int
	H int
}
type TextureAtlas struct {
	nodes   []atlasNode  
	data    []byte       
	used    uint         
	width   int          
	height  int          
	depth   int          
	texture gl.Texture   
}
func NewTextureAtlas(width, height, depth int) *TextureAtlas {
	switch depth {
	case 1, 3, 4:
	default:
		panic("Invalid depth value")
	}
	a := new(TextureAtlas)
	a.width = width
	a.height = height
	a.depth = depth
	a.used = 0
	a.data = make([]byte, width*height*depth)
	a.nodes = append(a.nodes, atlasNode{1, 1, width - 2})
	a.texture = gl.GenTexture()
	return a
}
func (a *TextureAtlas) Release() {
	a.data = nil
	a.nodes = nil
	a.texture.Delete()
	a.texture = 0
	a.width = 0
	a.height = 0
	a.depth = 0
	a.used = 0
}
func (a *TextureAtlas) Clear() {
	a.used = 0
	a.nodes = a.nodes[:1]
	a.nodes[0].x = 1
	a.nodes[0].y = 1
	a.nodes[0].z = a.width - 2
	pix := a.data
	for i := range pix {
		pix[i] = 0
	}
}
func (a *TextureAtlas) Bind(target gl.GLenum) { a.texture.Bind(target) }
func (a *TextureAtlas) Unbind(target gl.GLenum) { a.texture.Unbind(target) }
func (a *TextureAtlas) Commit(target gl.GLenum) {
	gl.PushAttrib(gl.CURRENT_BIT | gl.ENABLE_BIT)
	gl.Enable(target)
	a.texture.Bind(target)
	gl.TexParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(target, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(target, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	switch a.depth {
	case 4:
		gl.TexImage2D(target, 0, gl.RGBA, a.width, a.height,
			0, gl.RGBA, gl.UNSIGNED_BYTE, a.data)
	case 3:
		gl.TexImage2D(target, 0, gl.RGB, a.width, a.height,
			0, gl.RGB, gl.UNSIGNED_BYTE, a.data)
	case 1:
		gl.TexImage2D(target, 0, gl.ALPHA, a.width, a.height,
			0, gl.ALPHA, gl.UNSIGNED_BYTE, a.data)
	}
	gl.PopAttrib()
}