package pixelgl import ( "math" "github.com/faiface/glhf" "github.com/faiface/mainthread" "github.com/faiface/pixel" ) // GLPicture is a pixel.PictureColor with a Texture. All OpenGL Targets should implement and accept // this interface, because it enables seamless drawing of one to another. // // Implementing this interface on an OpenGL Target enables other OpenGL Targets to efficiently draw // that Target onto them. type GLPicture interface { pixel.PictureColor Texture() *glhf.Texture } // NewGLPicture creates a new GLPicture with it's own static OpenGL texture. This function always // allocates a new texture that cannot (shouldn't) be further modified. func NewGLPicture(p pixel.Picture) GLPicture { bounds := p.Bounds() bx, by, bw, bh := intBounds(bounds) pixels := make([]uint8, 4*bw*bh) if pd, ok := p.(*pixel.PictureData); ok { // PictureData short path for y := 0; y < bh; y++ { for x := 0; x < bw; x++ { rgba := pd.Pix[y*pd.Stride+x] off := (y*bw + x) * 4 pixels[off+0] = rgba.R pixels[off+1] = rgba.G pixels[off+2] = rgba.B pixels[off+3] = rgba.A } } } else if p, ok := p.(pixel.PictureColor); ok { for y := 0; y < bh; y++ { for x := 0; x < bw; x++ { at := pixel.V( math.Max(float64(bx+x), bounds.Min.X()), math.Max(float64(by+y), bounds.Min.Y()), ) color := p.Color(at) off := (y*bw + x) * 4 pixels[off+0] = uint8(color.R * 255) pixels[off+1] = uint8(color.G * 255) pixels[off+2] = uint8(color.B * 255) pixels[off+3] = uint8(color.A * 255) } } } var tex *glhf.Texture mainthread.Call(func() { tex = glhf.NewTexture(bw, bh, false, pixels) }) gp := &glPicture{ bounds: bounds, tex: tex, pixels: pixels, } return gp } type glPicture struct { bounds pixel.Rect tex *glhf.Texture pixels []uint8 } func (gp *glPicture) Bounds() pixel.Rect { return gp.bounds } func (gp *glPicture) Texture() *glhf.Texture { return gp.tex } func (gp *glPicture) Color(at pixel.Vec) pixel.RGBA { if !gp.bounds.Contains(at) { return pixel.Alpha(0) } bx, by, bw, _ := intBounds(gp.bounds) x, y := int(at.X())-bx, int(at.Y())-by off := y*bw + x return pixel.RGBA{ R: float64(gp.pixels[off*4+0]) / 255, G: float64(gp.pixels[off*4+1]) / 255, B: float64(gp.pixels[off*4+2]) / 255, A: float64(gp.pixels[off*4+3]) / 255, } }