Add graphics.Texture

This commit is contained in:
Hajime Hoshi 2013-06-19 10:31:44 +09:00
parent 532b52d389
commit eda572d03e
6 changed files with 82 additions and 92 deletions

View File

@ -8,7 +8,7 @@ import (
type Game interface {
Update()
Draw(g graphics.GraphicsContext, offscreen graphics.Texture)
Draw(g graphics.GraphicsContext, offscreen *graphics.Texture)
}
type UI interface {
@ -22,7 +22,7 @@ func OpenGLRun(game Game, ui UI) {
ch := make(chan bool, 1)
device := opengl.NewDevice(
ui.ScreenWidth(), ui.ScreenHeight(), ui.ScreenScale(),
func(g graphics.GraphicsContext, offscreen graphics.Texture) {
func(g graphics.GraphicsContext, offscreen *graphics.Texture) {
ticket := <-ch
game.Draw(g, offscreen)
ch<- ticket

View File

@ -91,7 +91,7 @@ func (ui *GlutUI) Run(device graphics.Device) {
}
type DemoGame struct {
ebitenTexture graphics.Texture
ebitenTexture *graphics.Texture
x int
}
@ -108,13 +108,12 @@ func (game *DemoGame) Update() {
panic(err)
}
// TODO: It looks strange to get a texture from the device.
game.ebitenTexture = currentUI.device.NewTextureFromImage(img)
game.ebitenTexture = graphics.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
@ -123,7 +122,7 @@ func (game *DemoGame) Draw(g graphics.GraphicsContext, offscreen graphics.Textur
geometryMatrix.SetTx(float64(game.x))
geometryMatrix.SetTy(float64(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())
}

View File

@ -7,23 +7,28 @@ import (
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,
DrawTexture(texture *Texture,
srcX, srcY, srcWidth, srcHeight int,
geometryMatrix *GeometryMatrix, colorMatrix *ColorMatrix)
SetOffscreen(texture Texture)
SetOffscreen(texture *Texture)
}
type Texture interface {
Width() int
Height() int
TextureWidth() int
TextureHeight() int
type Texture struct {
Width int
Height int
Image image.Image
}
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}
}

View File

@ -6,7 +6,6 @@ package opengl
// #include <stdlib.h>
import "C"
import (
"image"
"github.com/hajimehoshi/go-ebiten/graphics"
)
@ -15,13 +14,13 @@ type Device struct {
screenHeight int
screenScale int
graphicsContext *GraphicsContext
offscreenTexture *Texture
drawFunc func(graphics.GraphicsContext, graphics.Texture)
offscreenTexture *graphics.Texture
drawFunc func(graphics.GraphicsContext, *graphics.Texture)
funcs []func()
}
func NewDevice(screenWidth, screenHeight, screenScale int,
drawFunc func(graphics.GraphicsContext, graphics.Texture)) *Device {
drawFunc func(graphics.GraphicsContext, *graphics.Texture)) *Device {
device := &Device{
screenWidth: screenWidth,
screenHeight: screenHeight,
@ -30,16 +29,11 @@ func NewDevice(screenWidth, screenHeight, screenScale int,
drawFunc: drawFunc,
funcs: []func(){},
}
device.offscreenTexture = device.NewTexture(screenWidth, screenHeight).(*Texture)
device.offscreenTexture = graphics.NewTexture(screenWidth, screenHeight)
return device
}
func (device *Device) Update() {
for _, f := range device.funcs {
f()
}
device.funcs = []func(){}
g := device.graphicsContext
C.glEnable(C.GL_TEXTURE_2D)
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())
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)
}

View File

@ -41,6 +41,23 @@ func newGraphicsContext(screenWidth, screenHeight, screenScale int) *GraphicsCon
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() {
C.glClearColor(0, 0, 0, 1)
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!
}
func (context *GraphicsContext) DrawTexture(tex graphics.Texture,
func (context *GraphicsContext) DrawTexture(tex *graphics.Texture,
srcX, srcY, srcWidth, srcHeight int,
geometryMatrix *graphics.GeometryMatrix, colorMatrix *graphics.ColorMatrix) {
geometryMatrix = geometryMatrix.Clone()
colorMatrix = colorMatrix.Clone()
texture := tex.(*Texture)
texture := glTexture(tex)
context.setShaderProgram(geometryMatrix, colorMatrix)
C.glBindTexture(C.GL_TEXTURE_2D, texture.id)
@ -119,12 +136,12 @@ func abs(x int) int {
return x
}
func (context *GraphicsContext) SetOffscreen(tex graphics.Texture) {
func (context *GraphicsContext) SetOffscreen(tex *graphics.Texture) {
C.glFlush()
var texture *Texture = nil
if tex != nil {
texture = tex.(*Texture)
texture = glTexture(tex)
}
framebuffer := C.GLuint(0)
if texture != nil {

View File

@ -5,6 +5,7 @@ package opengl
// #include <OpenGL/gl.h>
import "C"
import (
"image"
"unsafe"
)
@ -27,7 +28,7 @@ type Texture struct {
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)))
textureHeight := int(Clp2(uint64(height)))
if pixels != nil {
@ -46,50 +47,46 @@ func createTexture(device *Device, width, height int, pixels []uint8) *Texture{
textureHeight: textureHeight,
}
device.executeWhenDrawing(func() {
textureID := C.GLuint(0)
C.glGenTextures(1, (*C.GLuint)(&textureID))
if textureID == 0 {
panic("glGenTexture failed")
}
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4)
C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(textureID))
textureID := C.GLuint(0)
C.glGenTextures(1, (*C.GLuint)(&textureID))
if textureID == 0 {
panic("glGenTexture failed")
}
C.glPixelStorei(C.GL_UNPACK_ALIGNMENT, 4)
C.glBindTexture(C.GL_TEXTURE_2D, C.GLuint(textureID))
ptr := unsafe.Pointer(nil)
if pixels != nil {
ptr = unsafe.Pointer(&pixels[0])
}
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RGBA,
C.GLsizei(textureWidth), C.GLsizei(textureHeight),
0, C.GL_RGBA, C.GL_UNSIGNED_BYTE, ptr)
ptr := unsafe.Pointer(nil)
if pixels != nil {
ptr = unsafe.Pointer(&pixels[0])
}
C.glTexImage2D(C.GL_TEXTURE_2D, 0, C.GL_RGBA,
C.GLsizei(textureWidth), C.GLsizei(textureHeight),
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_MIN_FILTER, C.GL_LINEAR)
C.glBindTexture(C.GL_TEXTURE_2D, 0)
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.glBindTexture(C.GL_TEXTURE_2D, 0)
// TODO: lock?
texture.id = textureID
})
// TODO: lock?
texture.id = textureID
return texture
}
func (texture *Texture) Width() int {
return texture.width
func newTexture(width, height int) *Texture {
return createTexture(width, height, nil)
}
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
func newTextureFromImage(img image.Image) *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(size.X, size.Y, pix)
}