package pixelgl import ( "github.com/faiface/glhf" "github.com/faiface/mainthread" "github.com/faiface/pixel" ) // GLFrame is a type that helps implementing OpenGL Targets. It implements most common methods to // avoid code redundancy. It contains an glhf.Frame that you can draw on. type GLFrame struct { frame *glhf.Frame bounds pixel.Rect pixels []uint8 dirty bool } // NewGLFrame creates a new GLFrame with the given bounds. func NewGLFrame(bounds pixel.Rect) *GLFrame { gf := new(GLFrame) gf.SetBounds(bounds) return gf } // SetBounds resizes the GLFrame to the new bounds. func (gf *GLFrame) SetBounds(bounds pixel.Rect) { if bounds == gf.Bounds() { return } mainthread.Call(func() { oldF := gf.frame _, _, w, h := intBounds(bounds) if w <= 0 { w = 1 } if h <= 0 { h = 1 } gf.frame = glhf.NewFrame(w, h, false) // preserve old content if oldF != nil { ox, oy, ow, oh := intBounds(bounds) oldF.Blit( gf.frame, ox, oy, ox+ow, oy+oh, ox, oy, ox+ow, oy+oh, ) } }) gf.bounds = bounds gf.pixels = nil gf.dirty = true } // Bounds returns the current GLFrame's bounds. func (gf *GLFrame) Bounds() pixel.Rect { return gf.bounds } // Color returns the color of the pixel under the specified position. func (gf *GLFrame) Color(at pixel.Vec) pixel.RGBA { if gf.dirty { mainthread.Call(func() { tex := gf.frame.Texture() tex.Begin() gf.pixels = tex.Pixels(0, 0, tex.Width(), tex.Height()) tex.End() }) gf.dirty = false } if !gf.bounds.Contains(at) { return pixel.Alpha(0) } bx, by, bw, _ := intBounds(gf.bounds) x, y := int(at.X)-bx, int(at.Y)-by off := y*bw + x return pixel.RGBA{ R: float64(gf.pixels[off*4+0]) / 255, G: float64(gf.pixels[off*4+1]) / 255, B: float64(gf.pixels[off*4+2]) / 255, A: float64(gf.pixels[off*4+3]) / 255, } } // Frame returns the GLFrame's Frame that you can draw on. func (gf *GLFrame) Frame() *glhf.Frame { return gf.frame } // Texture returns the underlying Texture of the GLFrame's Frame. // // Implements GLPicture interface. func (gf *GLFrame) Texture() *glhf.Texture { return gf.frame.Texture() } // Dirty marks the GLFrame as changed. Always call this method when you draw onto the GLFrame's // Frame. func (gf *GLFrame) Dirty() { gf.dirty = true }