mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
Add graphics.Texture
This commit is contained in:
parent
532b52d389
commit
eda572d03e
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
type Game interface {
|
type Game interface {
|
||||||
Update()
|
Update()
|
||||||
Draw(g graphics.GraphicsContext, offscreen graphics.Texture)
|
Draw(g graphics.GraphicsContext, offscreen *graphics.Texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UI interface {
|
type UI interface {
|
||||||
@ -22,7 +22,7 @@ func OpenGLRun(game Game, ui UI) {
|
|||||||
ch := make(chan bool, 1)
|
ch := make(chan bool, 1)
|
||||||
device := opengl.NewDevice(
|
device := opengl.NewDevice(
|
||||||
ui.ScreenWidth(), ui.ScreenHeight(), ui.ScreenScale(),
|
ui.ScreenWidth(), ui.ScreenHeight(), ui.ScreenScale(),
|
||||||
func(g graphics.GraphicsContext, offscreen graphics.Texture) {
|
func(g graphics.GraphicsContext, offscreen *graphics.Texture) {
|
||||||
ticket := <-ch
|
ticket := <-ch
|
||||||
game.Draw(g, offscreen)
|
game.Draw(g, offscreen)
|
||||||
ch<- ticket
|
ch<- ticket
|
||||||
|
@ -91,7 +91,7 @@ func (ui *GlutUI) Run(device graphics.Device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DemoGame struct {
|
type DemoGame struct {
|
||||||
ebitenTexture graphics.Texture
|
ebitenTexture *graphics.Texture
|
||||||
x int
|
x int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,13 +108,12 @@ func (game *DemoGame) Update() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: It looks strange to get a texture from the device.
|
game.ebitenTexture = graphics.NewTextureFromImage(img)
|
||||||
game.ebitenTexture = currentUI.device.NewTextureFromImage(img)
|
|
||||||
}
|
}
|
||||||
game.x++
|
game.x++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (game *DemoGame) Draw(g graphics.GraphicsContext, offscreen graphics.Texture) {
|
func (game *DemoGame) Draw(g graphics.GraphicsContext, offscreen *graphics.Texture) {
|
||||||
g.Fill(&color.RGBA{R: 128, G: 128, B: 255, A: 255})
|
g.Fill(&color.RGBA{R: 128, G: 128, B: 255, A: 255})
|
||||||
if game.ebitenTexture == nil {
|
if game.ebitenTexture == nil {
|
||||||
return
|
return
|
||||||
@ -123,7 +122,7 @@ func (game *DemoGame) Draw(g graphics.GraphicsContext, offscreen graphics.Textur
|
|||||||
geometryMatrix.SetTx(float64(game.x))
|
geometryMatrix.SetTx(float64(game.x))
|
||||||
geometryMatrix.SetTy(float64(game.x))
|
geometryMatrix.SetTy(float64(game.x))
|
||||||
g.DrawTexture(game.ebitenTexture,
|
g.DrawTexture(game.ebitenTexture,
|
||||||
0, 0, game.ebitenTexture.Width(), game.ebitenTexture.Height(),
|
0, 0, game.ebitenTexture.Width, game.ebitenTexture.Height,
|
||||||
geometryMatrix,
|
geometryMatrix,
|
||||||
graphics.IdentityColorMatrix())
|
graphics.IdentityColorMatrix())
|
||||||
}
|
}
|
||||||
|
@ -7,23 +7,28 @@ import (
|
|||||||
|
|
||||||
type Device interface {
|
type Device interface {
|
||||||
Update()
|
Update()
|
||||||
// TODO: Move somewhere
|
|
||||||
NewTexture(width, height int) Texture
|
|
||||||
NewTextureFromImage(img image.Image) Texture
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type GraphicsContext interface {
|
type GraphicsContext interface {
|
||||||
Clear()
|
Clear()
|
||||||
Fill(color color.Color)
|
Fill(color color.Color)
|
||||||
DrawTexture(texture Texture,
|
DrawTexture(texture *Texture,
|
||||||
srcX, srcY, srcWidth, srcHeight int,
|
srcX, srcY, srcWidth, srcHeight int,
|
||||||
geometryMatrix *GeometryMatrix, colorMatrix *ColorMatrix)
|
geometryMatrix *GeometryMatrix, colorMatrix *ColorMatrix)
|
||||||
SetOffscreen(texture Texture)
|
SetOffscreen(texture *Texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Texture interface {
|
type Texture struct {
|
||||||
Width() int
|
Width int
|
||||||
Height() int
|
Height int
|
||||||
TextureWidth() int
|
Image image.Image
|
||||||
TextureHeight() int
|
}
|
||||||
|
|
||||||
|
func NewTexture(width, height int) *Texture {
|
||||||
|
return &Texture{width, height, nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTextureFromImage(img image.Image) *Texture {
|
||||||
|
size := img.Bounds().Size()
|
||||||
|
return &Texture{size.X, size.Y, img}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ package opengl
|
|||||||
// #include <stdlib.h>
|
// #include <stdlib.h>
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
"image"
|
|
||||||
"github.com/hajimehoshi/go-ebiten/graphics"
|
"github.com/hajimehoshi/go-ebiten/graphics"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,13 +14,13 @@ type Device struct {
|
|||||||
screenHeight int
|
screenHeight int
|
||||||
screenScale int
|
screenScale int
|
||||||
graphicsContext *GraphicsContext
|
graphicsContext *GraphicsContext
|
||||||
offscreenTexture *Texture
|
offscreenTexture *graphics.Texture
|
||||||
drawFunc func(graphics.GraphicsContext, graphics.Texture)
|
drawFunc func(graphics.GraphicsContext, *graphics.Texture)
|
||||||
funcs []func()
|
funcs []func()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDevice(screenWidth, screenHeight, screenScale int,
|
func NewDevice(screenWidth, screenHeight, screenScale int,
|
||||||
drawFunc func(graphics.GraphicsContext, graphics.Texture)) *Device {
|
drawFunc func(graphics.GraphicsContext, *graphics.Texture)) *Device {
|
||||||
device := &Device{
|
device := &Device{
|
||||||
screenWidth: screenWidth,
|
screenWidth: screenWidth,
|
||||||
screenHeight: screenHeight,
|
screenHeight: screenHeight,
|
||||||
@ -30,16 +29,11 @@ func NewDevice(screenWidth, screenHeight, screenScale int,
|
|||||||
drawFunc: drawFunc,
|
drawFunc: drawFunc,
|
||||||
funcs: []func(){},
|
funcs: []func(){},
|
||||||
}
|
}
|
||||||
device.offscreenTexture = device.NewTexture(screenWidth, screenHeight).(*Texture)
|
device.offscreenTexture = graphics.NewTexture(screenWidth, screenHeight)
|
||||||
return device
|
return device
|
||||||
}
|
}
|
||||||
|
|
||||||
func (device *Device) Update() {
|
func (device *Device) Update() {
|
||||||
for _, f := range device.funcs {
|
|
||||||
f()
|
|
||||||
}
|
|
||||||
device.funcs = []func(){}
|
|
||||||
|
|
||||||
g := device.graphicsContext
|
g := device.graphicsContext
|
||||||
C.glEnable(C.GL_TEXTURE_2D)
|
C.glEnable(C.GL_TEXTURE_2D)
|
||||||
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_NEAREST)
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_NEAREST)
|
||||||
@ -61,25 +55,3 @@ func (device *Device) Update() {
|
|||||||
geometryMatrix, graphics.IdentityColorMatrix())
|
geometryMatrix, graphics.IdentityColorMatrix())
|
||||||
g.flush()
|
g.flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (device *Device) NewTexture(width, height int) graphics.Texture {
|
|
||||||
return createTexture(device, width, height, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (device *Device) NewTextureFromImage(img image.Image) graphics.Texture {
|
|
||||||
var pix []uint8
|
|
||||||
switch img.(type) {
|
|
||||||
case *image.RGBA:
|
|
||||||
pix = img.(*image.RGBA).Pix
|
|
||||||
case *image.NRGBA:
|
|
||||||
pix = img.(*image.NRGBA).Pix
|
|
||||||
default:
|
|
||||||
panic("image should be RGBA or NRGBA")
|
|
||||||
}
|
|
||||||
size := img.Bounds().Size()
|
|
||||||
return createTexture(device, size.X, size.Y, pix)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (device *Device) executeWhenDrawing(f func()) {
|
|
||||||
device.funcs = append(device.funcs, f)
|
|
||||||
}
|
|
||||||
|
@ -41,6 +41,23 @@ func newGraphicsContext(screenWidth, screenHeight, screenScale int) *GraphicsCon
|
|||||||
return context
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var glTextureCache = map[*graphics.Texture]*Texture{}
|
||||||
|
|
||||||
|
func glTexture(tex *graphics.Texture) *Texture {
|
||||||
|
if glTex, ok := glTextureCache[tex]; ok {
|
||||||
|
return glTex
|
||||||
|
}
|
||||||
|
|
||||||
|
var glTex *Texture = nil
|
||||||
|
if tex.Image != nil {
|
||||||
|
glTex = newTextureFromImage(tex.Image)
|
||||||
|
} else {
|
||||||
|
glTex = newTexture(tex.Width, tex.Height)
|
||||||
|
}
|
||||||
|
glTextureCache[tex] = glTex
|
||||||
|
return glTex
|
||||||
|
}
|
||||||
|
|
||||||
func (context *GraphicsContext) Clear() {
|
func (context *GraphicsContext) Clear() {
|
||||||
C.glClearColor(0, 0, 0, 1)
|
C.glClearColor(0, 0, 0, 1)
|
||||||
C.glClear(C.GL_COLOR_BUFFER_BIT)
|
C.glClear(C.GL_COLOR_BUFFER_BIT)
|
||||||
@ -61,13 +78,13 @@ func (context *GraphicsContext) DrawRect(x, y, width, height int, clr color.Colo
|
|||||||
// TODO: implement!
|
// TODO: implement!
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *GraphicsContext) DrawTexture(tex graphics.Texture,
|
func (context *GraphicsContext) DrawTexture(tex *graphics.Texture,
|
||||||
srcX, srcY, srcWidth, srcHeight int,
|
srcX, srcY, srcWidth, srcHeight int,
|
||||||
geometryMatrix *graphics.GeometryMatrix, colorMatrix *graphics.ColorMatrix) {
|
geometryMatrix *graphics.GeometryMatrix, colorMatrix *graphics.ColorMatrix) {
|
||||||
geometryMatrix = geometryMatrix.Clone()
|
geometryMatrix = geometryMatrix.Clone()
|
||||||
colorMatrix = colorMatrix.Clone()
|
colorMatrix = colorMatrix.Clone()
|
||||||
|
|
||||||
texture := tex.(*Texture)
|
texture := glTexture(tex)
|
||||||
|
|
||||||
context.setShaderProgram(geometryMatrix, colorMatrix)
|
context.setShaderProgram(geometryMatrix, colorMatrix)
|
||||||
C.glBindTexture(C.GL_TEXTURE_2D, texture.id)
|
C.glBindTexture(C.GL_TEXTURE_2D, texture.id)
|
||||||
@ -119,12 +136,12 @@ func abs(x int) int {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func (context *GraphicsContext) SetOffscreen(tex graphics.Texture) {
|
func (context *GraphicsContext) SetOffscreen(tex *graphics.Texture) {
|
||||||
C.glFlush()
|
C.glFlush()
|
||||||
|
|
||||||
var texture *Texture = nil
|
var texture *Texture = nil
|
||||||
if tex != nil {
|
if tex != nil {
|
||||||
texture = tex.(*Texture)
|
texture = glTexture(tex)
|
||||||
}
|
}
|
||||||
framebuffer := C.GLuint(0)
|
framebuffer := C.GLuint(0)
|
||||||
if texture != nil {
|
if texture != nil {
|
||||||
|
@ -5,6 +5,7 @@ package opengl
|
|||||||
// #include <OpenGL/gl.h>
|
// #include <OpenGL/gl.h>
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
|
"image"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ type Texture struct {
|
|||||||
textureHeight int
|
textureHeight int
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTexture(device *Device, width, height int, pixels []uint8) *Texture{
|
func createTexture(width, height int, pixels []uint8) *Texture {
|
||||||
textureWidth := int(Clp2(uint64(width)))
|
textureWidth := int(Clp2(uint64(width)))
|
||||||
textureHeight := int(Clp2(uint64(height)))
|
textureHeight := int(Clp2(uint64(height)))
|
||||||
if pixels != nil {
|
if pixels != nil {
|
||||||
@ -46,50 +47,46 @@ func createTexture(device *Device, width, height int, pixels []uint8) *Texture{
|
|||||||
textureHeight: textureHeight,
|
textureHeight: textureHeight,
|
||||||
}
|
}
|
||||||
|
|
||||||
device.executeWhenDrawing(func() {
|
textureID := C.GLuint(0)
|
||||||
textureID := C.GLuint(0)
|
C.glGenTextures(1, (*C.GLuint)(&textureID))
|
||||||
C.glGenTextures(1, (*C.GLuint)(&textureID))
|
if textureID == 0 {
|
||||||
if textureID == 0 {
|
panic("glGenTexture failed")
|
||||||
panic("glGenTexture failed")
|
}
|
||||||
}
|
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4)
|
||||||
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4)
|
C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(textureID))
|
||||||
C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(textureID))
|
|
||||||
|
ptr := unsafe.Pointer(nil)
|
||||||
ptr := unsafe.Pointer(nil)
|
if pixels != nil {
|
||||||
if pixels != nil {
|
ptr = unsafe.Pointer(&pixels[0])
|
||||||
ptr = unsafe.Pointer(&pixels[0])
|
}
|
||||||
}
|
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RGBA,
|
||||||
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RGBA,
|
C.GLsizei(textureWidth), C.GLsizei(textureHeight),
|
||||||
C.GLsizei(textureWidth), C.GLsizei(textureHeight),
|
0, C.GL_RGBA, C.GL_UNSIGNED_BYTE, ptr)
|
||||||
0, C.GL_RGBA, C.GL_UNSIGNED_BYTE, ptr)
|
|
||||||
|
|
||||||
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_LINEAR)
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_LINEAR)
|
||||||
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
|
C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MIN_FILTER, C.GL_LINEAR)
|
||||||
C.glBindTexture(C.GL_TEXTURE_2D, 0)
|
C.glBindTexture(C.GL_TEXTURE_2D, 0)
|
||||||
|
|
||||||
// TODO: lock?
|
// TODO: lock?
|
||||||
texture.id = textureID
|
texture.id = textureID
|
||||||
})
|
|
||||||
|
|
||||||
return texture
|
return texture
|
||||||
}
|
}
|
||||||
|
|
||||||
func (texture *Texture) Width() int {
|
func newTexture(width, height int) *Texture {
|
||||||
return texture.width
|
return createTexture(width, height, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (texture *Texture) Height() int {
|
func newTextureFromImage(img image.Image) *Texture {
|
||||||
return texture.height
|
var pix []uint8
|
||||||
}
|
switch img.(type) {
|
||||||
|
case *image.RGBA:
|
||||||
func (texture *Texture) TextureWidth() int {
|
pix = img.(*image.RGBA).Pix
|
||||||
return texture.textureWidth
|
case *image.NRGBA:
|
||||||
}
|
pix = img.(*image.NRGBA).Pix
|
||||||
|
default:
|
||||||
func (texture *Texture) TextureHeight() int {
|
panic("image should be RGBA or NRGBA")
|
||||||
return texture.textureHeight
|
}
|
||||||
}
|
size := img.Bounds().Size()
|
||||||
|
return createTexture(size.X, size.Y, pix)
|
||||||
func (texture *Texture) IsAvailable() bool {
|
|
||||||
return texture.id != 0
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user