go-opengl-pixel/pixelgl/glpicture.go

99 lines
2.3 KiB
Go

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,
}
}