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++ {
|
||
|
nrgba := pd.Pix[y*pd.Stride+x]
|
||
|
off := (y*bw + x) * 4
|
||
|
pixels[off+0] = nrgba.R
|
||
|
pixels[off+1] = nrgba.G
|
||
|
pixels[off+2] = nrgba.B
|
||
|
pixels[off+3] = nrgba.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.NRGBA {
|
||
|
if !gp.bounds.Contains(at) {
|
||
|
return pixel.NRGBA{}
|
||
|
}
|
||
|
bx, by, bw, _ := intBounds(gp.bounds)
|
||
|
x, y := int(at.X())-bx, int(at.Y())-by
|
||
|
off := y*bw + x
|
||
|
return pixel.NRGBA{
|
||
|
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,
|
||
|
}
|
||
|
}
|