2013-10-25 02:30:39 +02:00
|
|
|
package texture
|
|
|
|
|
|
|
|
import (
|
2013-10-25 21:15:27 +02:00
|
|
|
"github.com/hajimehoshi/go-ebiten/graphics"
|
2013-10-25 02:30:39 +02:00
|
|
|
"image"
|
|
|
|
"image/draw"
|
|
|
|
)
|
|
|
|
|
|
|
|
func nextPowerOf2(x uint64) uint64 {
|
|
|
|
x -= 1
|
|
|
|
x |= (x >> 1)
|
|
|
|
x |= (x >> 2)
|
|
|
|
x |= (x >> 4)
|
|
|
|
x |= (x >> 8)
|
|
|
|
x |= (x >> 16)
|
|
|
|
x |= (x >> 32)
|
|
|
|
return x + 1
|
|
|
|
}
|
|
|
|
|
|
|
|
type Texture struct {
|
|
|
|
native interface{}
|
|
|
|
width int
|
|
|
|
height int
|
|
|
|
}
|
|
|
|
|
2013-11-25 17:08:12 +01:00
|
|
|
func AdjustImage(img image.Image, width, height int) *image.NRGBA {
|
|
|
|
adjustedImageBounds := image.Rectangle{
|
|
|
|
image.ZP,
|
|
|
|
image.Point{width, height},
|
|
|
|
}
|
|
|
|
if nrgba := img.(*image.NRGBA); nrgba != nil &&
|
|
|
|
img.Bounds() == adjustedImageBounds {
|
|
|
|
return nrgba
|
|
|
|
}
|
|
|
|
|
|
|
|
adjustedImage := image.NewNRGBA(adjustedImageBounds)
|
|
|
|
dstBounds := image.Rectangle{
|
|
|
|
image.ZP,
|
|
|
|
img.Bounds().Size(),
|
|
|
|
}
|
|
|
|
draw.Draw(adjustedImage, dstBounds, img, image.ZP, draw.Src)
|
|
|
|
return adjustedImage
|
|
|
|
}
|
|
|
|
|
2013-10-27 13:27:16 +01:00
|
|
|
func New(width, height int, create func(textureWidth, textureHeight int) (
|
|
|
|
interface{}, error)) (*Texture, error) {
|
2013-10-25 02:30:39 +02:00
|
|
|
texture := &Texture{
|
|
|
|
width: width,
|
|
|
|
height: height,
|
|
|
|
}
|
|
|
|
var err error
|
2013-10-27 13:27:16 +01:00
|
|
|
texture.native, err = create(texture.textureWidth(),
|
|
|
|
texture.textureHeight())
|
2013-10-25 02:30:39 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return texture, nil
|
|
|
|
}
|
|
|
|
|
2013-10-27 13:27:16 +01:00
|
|
|
func NewFromImage(img image.Image, create func(img *image.NRGBA) (
|
|
|
|
interface{}, error)) (*Texture, error) {
|
2013-10-25 02:30:39 +02:00
|
|
|
size := img.Bounds().Size()
|
|
|
|
width, height := size.X, size.Y
|
|
|
|
texture := &Texture{
|
|
|
|
width: width,
|
|
|
|
height: height,
|
|
|
|
}
|
2013-11-25 17:08:12 +01:00
|
|
|
adjustedImage := AdjustImage(img, texture.textureWidth(), texture.textureHeight())
|
2013-10-25 02:30:39 +02:00
|
|
|
var err error
|
2013-10-26 16:18:23 +02:00
|
|
|
texture.native, err = create(adjustedImage)
|
2013-10-25 02:30:39 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return texture, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (texture *Texture) textureWidth() int {
|
|
|
|
return int(nextPowerOf2(uint64(texture.width)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (texture *Texture) textureHeight() int {
|
|
|
|
return int(nextPowerOf2(uint64(texture.height)))
|
|
|
|
}
|
|
|
|
|
2013-10-25 21:15:27 +02:00
|
|
|
func (texture *Texture) u(x int) float32 {
|
|
|
|
return float32(x) / float32(texture.textureWidth())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (texture *Texture) v(y int) float32 {
|
|
|
|
return float32(y) / float32(texture.textureHeight())
|
2013-10-25 02:30:39 +02:00
|
|
|
}
|
|
|
|
|
2013-10-25 21:15:27 +02:00
|
|
|
func (texture *Texture) SetAsViewport(setter func(x, y, width, height int)) {
|
|
|
|
setter(0, 0, texture.textureWidth(), texture.textureHeight())
|
2013-10-25 02:30:39 +02:00
|
|
|
}
|
|
|
|
|
2013-10-25 21:15:27 +02:00
|
|
|
type Quad struct {
|
|
|
|
VertexX1 float32
|
|
|
|
VertexX2 float32
|
|
|
|
VertexY1 float32
|
|
|
|
VertexY2 float32
|
|
|
|
TextureCoordU1 float32
|
|
|
|
TextureCoordU2 float32
|
|
|
|
TextureCoordV1 float32
|
|
|
|
TextureCoordV2 float32
|
|
|
|
}
|
|
|
|
|
|
|
|
func (texture *Texture) Draw(draw func(native interface{}, quads []Quad)) {
|
|
|
|
x1 := float32(0)
|
|
|
|
x2 := float32(texture.width)
|
|
|
|
y1 := float32(0)
|
|
|
|
y2 := float32(texture.height)
|
|
|
|
u1 := texture.u(0)
|
|
|
|
u2 := texture.u(texture.width)
|
|
|
|
v1 := texture.v(0)
|
|
|
|
v2 := texture.v(texture.height)
|
|
|
|
quad := Quad{x1, x2, y1, y2, u1, u2, v1, v2}
|
|
|
|
draw(texture.native, []Quad{quad})
|
|
|
|
}
|
|
|
|
|
2013-10-27 13:27:16 +01:00
|
|
|
func (texture *Texture) DrawParts(parts []graphics.TexturePart,
|
|
|
|
draw func(native interface{}, quads []Quad)) {
|
2013-10-25 21:15:27 +02:00
|
|
|
quads := []Quad{}
|
|
|
|
for _, part := range parts {
|
|
|
|
x1 := float32(part.LocationX)
|
|
|
|
x2 := float32(part.LocationX + part.Source.Width)
|
|
|
|
y1 := float32(part.LocationY)
|
|
|
|
y2 := float32(part.LocationY + part.Source.Height)
|
|
|
|
u1 := texture.u(part.Source.X)
|
|
|
|
u2 := texture.u(part.Source.X + part.Source.Width)
|
|
|
|
v1 := texture.v(part.Source.Y)
|
|
|
|
v2 := texture.v(part.Source.Y + part.Source.Height)
|
|
|
|
quad := Quad{x1, x2, y1, y2, u1, u2, v1, v2}
|
|
|
|
quads = append(quads, quad)
|
|
|
|
}
|
|
|
|
draw(texture.native, quads)
|
2013-10-25 02:30:39 +02:00
|
|
|
}
|
2013-10-27 13:27:16 +01:00
|
|
|
|
2013-10-27 13:29:39 +01:00
|
|
|
func (texture *Texture) CreateFramebuffer(
|
|
|
|
create func(native interface{}) interface{}) interface{} {
|
|
|
|
return create(texture.native)
|
2013-10-27 13:27:16 +01:00
|
|
|
}
|