diff --git a/ebiten.go b/ebiten.go index d16099431..7d2f26226 100644 --- a/ebiten.go +++ b/ebiten.go @@ -3,19 +3,20 @@ package ebiten import ( "time" "github.com/hajimehoshi/go-ebiten/graphics" + "github.com/hajimehoshi/go-ebiten/graphics/opengl" "github.com/hajimehoshi/go-ebiten/ui" ) type Game interface { Update() - Draw(g *graphics.GraphicsContext, offscreen *graphics.Texture) + Draw(g graphics.GraphicsContext, offscreen graphics.Texture) } func Run(game Game, u ui.UI) { ch := make(chan bool, 1) - device := graphics.NewDevice( + device := opengl.NewDevice( u.ScreenWidth(), u.ScreenHeight(), u.ScreenScale(), - func(g *graphics.GraphicsContext, offscreen *graphics.Texture) { + func(g graphics.GraphicsContext, offscreen graphics.Texture) { ticket := <-ch game.Draw(g, offscreen) ch<- ticket diff --git a/examples/glut/main.go b/examples/glut/main.go index 9aaa7be84..3d93ca7db 100644 --- a/examples/glut/main.go +++ b/examples/glut/main.go @@ -28,7 +28,7 @@ type GlutUI struct{ screenWidth int screenHeight int screenScale int - device *graphics.Device + device graphics.Device } var currentUI *GlutUI @@ -85,13 +85,13 @@ func (ui *GlutUI) ScreenScale() int { return ui.screenScale } -func (ui *GlutUI) Run(device *graphics.Device) { +func (ui *GlutUI) Run(device graphics.Device) { ui.device = device C.glutMainLoop() } type DemoGame struct { - ebitenTexture *graphics.Texture + ebitenTexture graphics.Texture x int } @@ -108,12 +108,13 @@ func (game *DemoGame) Update() { panic(err) } + // TODO: It looks strange to get a texture from the device. game.ebitenTexture = currentUI.device.NewTextureFromImage(img) } 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}) if game.ebitenTexture == nil { return @@ -122,7 +123,7 @@ func (game *DemoGame) Draw(g *graphics.GraphicsContext, offscreen *graphics.Text geometryMatrix.SetTx(graphics.AffineMatrixElement(game.x)) geometryMatrix.SetTy(graphics.AffineMatrixElement(game.x)) g.DrawTexture(game.ebitenTexture, - 0, 0, game.ebitenTexture.Width, game.ebitenTexture.Height, + 0, 0, game.ebitenTexture.Width(), game.ebitenTexture.Height(), geometryMatrix, graphics.IdentityColorMatrix()) } diff --git a/graphics/graphics.go b/graphics/graphics.go new file mode 100644 index 000000000..f3ce2a4bd --- /dev/null +++ b/graphics/graphics.go @@ -0,0 +1,29 @@ +package graphics + +import ( + "image" + "image/color" +) + +type Device interface { + Update() + // TODO: Move somewhere + NewTexture(width, height int) Texture + NewTextureFromImage(img image.Image) Texture +} + +type GraphicsContext interface { + Clear() + Fill(color color.Color) + DrawTexture(texture Texture, + srcX, srcY, srcWidth, srcHeight int, + geometryMatrix *GeometryMatrix, colorMatrix *ColorMatrix) + SetOffscreen(texture Texture) +} + +type Texture interface { + Width() int + Height() int + TextureWidth() int + TextureHeight() int +} diff --git a/graphics/device.go b/graphics/opengl/device.go similarity index 74% rename from graphics/device.go rename to graphics/opengl/device.go index 5398c28aa..9e3223af7 100644 --- a/graphics/device.go +++ b/graphics/opengl/device.go @@ -1,4 +1,4 @@ -package graphics +package opengl // #cgo LDFLAGS: -framework OpenGL // @@ -7,6 +7,7 @@ package graphics import "C" import ( "image" + "github.com/hajimehoshi/go-ebiten/graphics" ) type Device struct { @@ -15,12 +16,12 @@ type Device struct { screenScale int graphicsContext *GraphicsContext offscreenTexture *Texture - drawFunc func(*GraphicsContext, *Texture) + drawFunc func(graphics.GraphicsContext, graphics.Texture) funcs []func() } func NewDevice(screenWidth, screenHeight, screenScale int, - drawFunc func(*GraphicsContext, *Texture)) *Device { + drawFunc func(graphics.GraphicsContext, graphics.Texture)) *Device { device := &Device{ screenWidth: screenWidth, screenHeight: screenHeight, @@ -29,7 +30,7 @@ func NewDevice(screenWidth, screenHeight, screenScale int, drawFunc: drawFunc, funcs: []func(){}, } - device.offscreenTexture = device.NewTexture(screenWidth, screenHeight) + device.offscreenTexture = device.NewTexture(screenWidth, screenHeight).(*Texture) return device } @@ -52,20 +53,20 @@ func (device *Device) Update() { C.glTexParameteri(C.GL_TEXTURE_2D, C.GL_TEXTURE_MAG_FILTER, C.GL_LINEAR) g.resetOffscreen() g.Clear() - geometryMatrix := IdentityGeometryMatrix() - geometryMatrix.SetA(AffineMatrixElement(g.screenScale)) - geometryMatrix.SetD(AffineMatrixElement(g.screenScale)) + geometryMatrix := graphics.IdentityGeometryMatrix() + geometryMatrix.SetA(graphics.AffineMatrixElement(g.screenScale)) + geometryMatrix.SetD(graphics.AffineMatrixElement(g.screenScale)) g.DrawTexture(device.offscreenTexture, 0, 0, device.screenWidth, device.screenHeight, - geometryMatrix, IdentityColorMatrix()) + geometryMatrix, graphics.IdentityColorMatrix()) g.flush() } -func (device *Device) NewTexture(width, height int) *Texture { +func (device *Device) NewTexture(width, height int) graphics.Texture { return createTexture(device, width, height, nil) } -func (device *Device) NewTextureFromImage(img image.Image) *Texture { +func (device *Device) NewTextureFromImage(img image.Image) graphics.Texture { var pix []uint8 switch img.(type) { case *image.RGBA: diff --git a/graphics/graphics_context.go b/graphics/opengl/graphics_context.go similarity index 88% rename from graphics/graphics_context.go rename to graphics/opengl/graphics_context.go index 2185632d6..616912232 100644 --- a/graphics/graphics_context.go +++ b/graphics/opengl/graphics_context.go @@ -1,4 +1,4 @@ -package graphics +package opengl // #cgo LDFLAGS: -framework OpenGL // @@ -9,6 +9,7 @@ import ( "fmt" "image/color" "unsafe" + "github.com/hajimehoshi/go-ebiten/graphics" ) type GraphicsContext struct { @@ -45,8 +46,8 @@ func (context *GraphicsContext) Clear() { C.glClear(C.GL_COLOR_BUFFER_BIT) } -func (context *GraphicsContext) Fill(color color.Color) { - r, g, b, a := color.RGBA() +func (context *GraphicsContext) Fill(clr color.Color) { + r, g, b, a := clr.RGBA() max := 65535.0 C.glClearColor( C.GLclampf(float64(r) / max), @@ -56,16 +57,18 @@ func (context *GraphicsContext) Fill(color color.Color) { C.glClear(C.GL_COLOR_BUFFER_BIT) } -func (context *GraphicsContext) DrawRect(x, y, width, height int, color color.Color) { +func (context *GraphicsContext) DrawRect(x, y, width, height int, clr color.Color) { // TODO: implement! } -func (context *GraphicsContext) DrawTexture(texture *Texture, +func (context *GraphicsContext) DrawTexture(tex graphics.Texture, srcX, srcY, srcWidth, srcHeight int, - geometryMatrix *GeometryMatrix, colorMatrix *ColorMatrix) { + geometryMatrix *graphics.GeometryMatrix, colorMatrix *graphics.ColorMatrix) { geometryMatrix = geometryMatrix.Clone() colorMatrix = colorMatrix.Clone() + texture := tex.(*Texture) + context.setShaderProgram(geometryMatrix, colorMatrix) C.glBindTexture(C.GL_TEXTURE_2D, texture.id) @@ -80,10 +83,10 @@ func (context *GraphicsContext) DrawTexture(texture *Texture, x2, y2, } - tu1 := float32(srcX) / float32(texture.TextureWidth) - tu2 := float32(srcX + srcWidth) / float32(texture.TextureWidth) - tv1 := float32(srcY) / float32(texture.TextureHeight) - tv2 := float32(srcY + srcHeight) / float32(texture.TextureHeight) + tu1 := float32(srcX) / float32(texture.textureWidth) + tu2 := float32(srcX + srcWidth) / float32(texture.textureWidth) + tv1 := float32(srcY) / float32(texture.textureHeight) + tv2 := float32(srcY + srcHeight) / float32(texture.textureHeight) texCoord := [...]float32{ tu1, tv1, tu2, tv1, @@ -116,7 +119,12 @@ func abs(x int) int { return x } -func (context *GraphicsContext) SetOffscreen(texture *Texture) { +func (context *GraphicsContext) SetOffscreen(tex graphics.Texture) { + var texture *Texture = nil + if tex != nil { + texture = tex.(*Texture) + } + // TODO: glFlush() here? framebuffer := C.GLuint(0) if texture != nil { framebuffer = context.getFramebuffer(texture) @@ -135,8 +143,8 @@ func (context *GraphicsContext) SetOffscreen(texture *Texture) { width, height, tx, ty := 0, 0, 0, 0 if framebuffer != context.mainFramebuffer { - width = texture.TextureWidth - height = texture.TextureHeight + width = texture.textureWidth + height = texture.textureHeight tx = -1 ty = -1 } else { @@ -169,7 +177,7 @@ func (context *GraphicsContext) flush() { // This method should be called on the UI thread. func (context *GraphicsContext) setShaderProgram( - geometryMatrix *GeometryMatrix, colorMatrix *ColorMatrix) { + geometryMatrix *graphics.GeometryMatrix, colorMatrix *graphics.ColorMatrix) { program := C.GLuint(0) if colorMatrix.IsIdentity() { program = regularShaderProgram diff --git a/graphics/shader.go b/graphics/opengl/shader.go similarity index 99% rename from graphics/shader.go rename to graphics/opengl/shader.go index 5510ac7d3..1a10db11c 100644 --- a/graphics/shader.go +++ b/graphics/opengl/shader.go @@ -1,4 +1,4 @@ -package graphics +package opengl // #cgo LDFLAGS: -framework OpenGL // diff --git a/graphics/texture.go b/graphics/opengl/texture.go similarity index 76% rename from graphics/texture.go rename to graphics/opengl/texture.go index 8840ad0bc..567da56a1 100644 --- a/graphics/texture.go +++ b/graphics/opengl/texture.go @@ -1,4 +1,4 @@ -package graphics +package opengl // #cgo LDFLAGS: -framework OpenGL // @@ -21,10 +21,10 @@ func Clp2(x uint64) uint64 { type Texture struct { id C.GLuint - Width int - Height int - TextureWidth int - TextureHeight int + width int + height int + textureWidth int + textureHeight int } func createTexture(device *Device, width, height int, pixels []uint8) *Texture{ @@ -40,10 +40,10 @@ func createTexture(device *Device, width, height int, pixels []uint8) *Texture{ } texture := &Texture{ id: 0, - Width: width, - Height: height, - TextureWidth: textureWidth, - TextureHeight: textureHeight, + width: width, + height: height, + textureWidth: textureWidth, + textureHeight: textureHeight, } device.executeWhenDrawing(func() { @@ -74,6 +74,22 @@ func createTexture(device *Device, width, height int, pixels []uint8) *Texture{ return texture } +func (texture *Texture) Width() int { + return texture.width +} + +func (texture *Texture) Height() int { + return texture.height +} + +func (texture *Texture) TextureWidth() int { + return texture.textureWidth +} + +func (texture *Texture) TextureHeight() int { + return texture.textureHeight +} + func (texture *Texture) IsAvailable() bool { return texture.id != 0 } diff --git a/graphics/texture_test.go b/graphics/opengl/texture_test.go similarity index 94% rename from graphics/texture_test.go rename to graphics/opengl/texture_test.go index f068b215b..13b64a156 100644 --- a/graphics/texture_test.go +++ b/graphics/opengl/texture_test.go @@ -1,4 +1,4 @@ -package graphics_test +package opengl_test import ( "testing" diff --git a/ui/ui.go b/ui/ui.go index a0e1b56f6..58cc5101e 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -8,5 +8,5 @@ type UI interface { ScreenWidth() int ScreenHeight() int ScreenScale() int - Run(device *graphics.Device) + Run(device graphics.Device) }