99 lines
2.3 KiB
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,
|
|
}
|
|
}
|