Replace TextureID with Texture

This commit is contained in:
Hajime Hoshi 2014-12-17 21:49:28 +09:00
parent 33cb234ae1
commit eb11831585
11 changed files with 87 additions and 61 deletions

View File

@ -23,7 +23,7 @@ import (
) )
type debugPrintState struct { type debugPrintState struct {
textTexture ebiten.TextureID textTexture *ebiten.Texture
debugPrintRenderTarget ebiten.RenderTargetID debugPrintRenderTarget ebiten.RenderTargetID
y int y int
} }
@ -62,12 +62,12 @@ func (d *debugPrintState) drawText(gr ebiten.GraphicsContext, str string, x, y i
} }
func (d *debugPrintState) DebugPrint(gr ebiten.GraphicsContext, str string) { func (d *debugPrintState) DebugPrint(gr ebiten.GraphicsContext, str string) {
if d.textTexture.IsNil() { if d.textTexture == nil {
img, err := assets.TextImage() img, err := assets.TextImage()
if err != nil { if err != nil {
panic(err) panic(err)
} }
d.textTexture, err = ebiten.NewTextureID(img, ebiten.FilterNearest) d.textTexture, err = ebiten.NewTexture(img, ebiten.FilterNearest)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -22,15 +22,19 @@ import (
"os" "os"
) )
func NewTextureIDFromFile(path string, filter ebiten.Filter) (ebiten.TextureID, error) { func NewTextureFromFile(path string, filter ebiten.Filter) (*ebiten.Texture, image.Image, error) {
file, err := os.Open(path) file, err := os.Open(path)
if err != nil { if err != nil {
return 0, err return nil, nil, err
} }
defer file.Close() defer file.Close()
img, _, err := image.Decode(file) img, _, err := image.Decode(file)
if err != nil { if err != nil {
return 0, err return nil, nil, err
} }
return ebiten.NewTextureID(img, filter) texture, err := ebiten.NewTexture(img, filter)
if err != nil {
return nil, nil, err
}
return texture, img, err
} }

View File

@ -37,7 +37,7 @@ type nameSize struct {
type Textures struct { type Textures struct {
texturePaths chan namePath texturePaths chan namePath
renderTargetSizes chan nameSize renderTargetSizes chan nameSize
textures map[string]ebiten.TextureID textures map[string]*ebiten.Texture
renderTargets map[string]ebiten.RenderTargetID renderTargets map[string]ebiten.RenderTargetID
sync.RWMutex sync.RWMutex
} }
@ -46,7 +46,7 @@ func NewTextures() *Textures {
textures := &Textures{ textures := &Textures{
texturePaths: make(chan namePath), texturePaths: make(chan namePath),
renderTargetSizes: make(chan nameSize), renderTargetSizes: make(chan nameSize),
textures: map[string]ebiten.TextureID{}, textures: map[string]*ebiten.Texture{},
renderTargets: map[string]ebiten.RenderTargetID{}, renderTargets: map[string]ebiten.RenderTargetID{},
} }
go func() { go func() {
@ -81,7 +81,7 @@ func (t *Textures) loopMain() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
id, err := ebiten.NewTextureID(img, ebiten.FilterNearest) id, err := ebiten.NewTexture(img, ebiten.FilterNearest)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -123,7 +123,7 @@ func (t *Textures) Has(name string) bool {
return ok return ok
} }
func (t *Textures) GetTexture(name string) ebiten.TextureID { func (t *Textures) GetTexture(name string) *ebiten.Texture {
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
return t.textures[name] return t.textures[name]

View File

@ -19,8 +19,10 @@ package main
import ( import (
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil" "github.com/hajimehoshi/ebiten/ebitenutil"
"image"
_ "image/jpeg" _ "image/jpeg"
"log" "log"
"math"
) )
const ( const (
@ -29,21 +31,33 @@ const (
) )
type Game struct { type Game struct {
gophersTexture ebiten.TextureID count int
gophersTexture *ebiten.Texture
gophersTextureWidth int
gophersTextureHeight int
} }
func (g *Game) Update(gr ebiten.GraphicsContext) error { func (g *Game) Update(gr ebiten.GraphicsContext) error {
ebiten.DrawWhole(gr.Texture(g.gophersTexture), 500, 414, ebiten.GeometryMatrixI(), ebiten.ColorMatrixI()) g.count++
geo := ebiten.TranslateGeometry(-float64(g.gophersTextureWidth)/2, -float64(g.gophersTextureHeight)/2)
geo.Concat(ebiten.ScaleGeometry(0.5, 0.5))
geo.Concat(ebiten.TranslateGeometry(screenWidth/2, screenHeight/2))
clr := ebiten.RotateHue(float64(g.count%180) * 2 * math.Pi / 180)
ebiten.DrawWhole(gr.Texture(g.gophersTexture), g.gophersTextureWidth, g.gophersTextureHeight, geo, clr)
return nil return nil
} }
func main() { func main() {
g := new(Game) g := new(Game)
id, err := ebitenutil.NewTextureIDFromFile("images/gophers.jpg", ebiten.FilterLinear) var img image.Image
var err error
g.gophersTexture, img, err = ebitenutil.NewTextureFromFile("images/gophers.jpg", ebiten.FilterLinear)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
g.gophersTexture = id g.gophersTextureWidth = img.Bounds().Size().X
g.gophersTextureHeight = img.Bounds().Size().Y
if err := ebiten.Run(g.Update, screenWidth, screenHeight, 2, "Image (Ebiten Demo)"); err != nil { if err := ebiten.Run(g.Update, screenWidth, screenHeight, 2, "Image (Ebiten Demo)"); err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -23,7 +23,6 @@ import (
"image/color" "image/color"
"log" "log"
"math" "math"
"sync"
) )
const ( const (
@ -32,7 +31,7 @@ const (
) )
type Game struct { type Game struct {
init sync.Once inited bool
count int count int
brushRenderTarget ebiten.RenderTargetID brushRenderTarget ebiten.RenderTargetID
canvasRenderTarget ebiten.RenderTargetID canvasRenderTarget ebiten.RenderTargetID
@ -42,14 +41,15 @@ func (g *Game) Update(gr ebiten.GraphicsContext) error {
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) { if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
g.count++ g.count++
} }
g.init.Do(func() { if !g.inited {
gr.PushRenderTarget(g.brushRenderTarget) gr.PushRenderTarget(g.brushRenderTarget)
gr.Fill(0xff, 0xff, 0xff) gr.Fill(0xff, 0xff, 0xff)
gr.PopRenderTarget() gr.PopRenderTarget()
gr.PushRenderTarget(g.canvasRenderTarget) gr.PushRenderTarget(g.canvasRenderTarget)
gr.Fill(0xff, 0xff, 0xff) gr.Fill(0xff, 0xff, 0xff)
gr.PopRenderTarget() gr.PopRenderTarget()
}) g.inited = true
}
mx, my := ebiten.CursorPosition() mx, my := ebiten.CursorPosition()

View File

@ -52,7 +52,7 @@ func NewRenderTargetID(width, height int, filter Filter) (RenderTargetID, error)
return currentUI.newRenderTargetID(width, height, glFilter(filter)) return currentUI.newRenderTargetID(width, height, glFilter(filter))
} }
// NewTextureID returns a new TextureID. // NewTexture returns a new Texture.
func NewTextureID(img image.Image, filter Filter) (TextureID, error) { func NewTexture(img image.Image, filter Filter) (*Texture, error) {
return currentUI.newTextureID(img, glFilter(filter)) return currentUI.newTexture(img, glFilter(filter))
} }

View File

@ -53,7 +53,7 @@ func DrawWhole(drawer Drawer, width, height int, geo GeometryMatrix, color Color
type GraphicsContext interface { type GraphicsContext interface {
Clear() error Clear() error
Fill(r, g, b uint8) error Fill(r, g, b uint8) error
Texture(id TextureID) Drawer Texture(texture *Texture) Drawer
RenderTarget(id RenderTargetID) Drawer RenderTarget(id RenderTargetID) Drawer
// TODO: ScreenRenderTarget() Drawer // TODO: ScreenRenderTarget() Drawer
PushRenderTarget(id RenderTargetID) PushRenderTarget(id RenderTargetID)
@ -70,13 +70,21 @@ const (
FilterLinear FilterLinear
) )
type Texture struct {
id int
}
type RenderTarget struct {
id int
}
// TextureID represents an ID of a texture. // TextureID represents an ID of a texture.
type TextureID int /*type TextureID int
// IsNil returns true if the texture is nil. // IsNil returns true if the texture is nil.
func (i TextureID) IsNil() bool { func (i TextureID) IsNil() bool {
return i == 0 return i == 0
} }*/
// RenderTargetID represents an ID of a render target. // RenderTargetID represents an ID of a render target.
// A render target is essentially same as a texture, but it is assumed that the // A render target is essentially same as a texture, but it is assumed that the

View File

@ -68,8 +68,8 @@ func (c *graphicsContext) Fill(r, g, b uint8) error {
return idsInstance.fillRenderTarget(c.currentIDs[len(c.currentIDs)-1], r, g, b) return idsInstance.fillRenderTarget(c.currentIDs[len(c.currentIDs)-1], r, g, b)
} }
func (c *graphicsContext) Texture(id TextureID) Drawer { func (c *graphicsContext) Texture(texture *Texture) Drawer {
return &textureWithContext{id, c} return &textureWithContext{texture, c}
} }
func (c *graphicsContext) RenderTarget(id RenderTargetID) Drawer { func (c *graphicsContext) RenderTarget(id RenderTargetID) Drawer {
@ -104,11 +104,11 @@ func (c *graphicsContext) postUpdate() {
} }
type textureWithContext struct { type textureWithContext struct {
id TextureID texture *Texture
context *graphicsContext context *graphicsContext
} }
func (t *textureWithContext) Draw(parts []TexturePart, geo GeometryMatrix, color ColorMatrix) error { func (t *textureWithContext) Draw(parts []TexturePart, geo GeometryMatrix, color ColorMatrix) error {
currentID := t.context.currentIDs[len(t.context.currentIDs)-1] currentID := t.context.currentIDs[len(t.context.currentIDs)-1]
return idsInstance.drawTexture(currentID, t.id, parts, geo, color) return idsInstance.drawTexture(currentID, t.texture, parts, geo, color)
} }

52
ids.go
View File

@ -26,25 +26,25 @@ import (
) )
type ids struct { type ids struct {
textures map[TextureID]*opengl.Texture textures map[*Texture]*opengl.Texture
renderTargets map[RenderTargetID]*opengl.RenderTarget renderTargets map[RenderTargetID]*opengl.RenderTarget
renderTargetToTexture map[RenderTargetID]TextureID renderTargetToTexture map[RenderTargetID]*Texture
lastID int lastID int
currentRenderTargetID RenderTargetID currentRenderTargetID RenderTargetID
sync.RWMutex sync.RWMutex
} }
var idsInstance = &ids{ var idsInstance = &ids{
textures: map[TextureID]*opengl.Texture{}, textures: map[*Texture]*opengl.Texture{},
renderTargets: map[RenderTargetID]*opengl.RenderTarget{}, renderTargets: map[RenderTargetID]*opengl.RenderTarget{},
renderTargetToTexture: map[RenderTargetID]TextureID{}, renderTargetToTexture: map[RenderTargetID]*Texture{},
currentRenderTargetID: -1, currentRenderTargetID: -1,
} }
func (i *ids) textureAt(id TextureID) *opengl.Texture { func (i *ids) textureAt(texture *Texture) *opengl.Texture {
i.RLock() i.RLock()
defer i.RUnlock() defer i.RUnlock()
return i.textures[id] return i.textures[texture]
} }
func (i *ids) renderTargetAt(id RenderTargetID) *opengl.RenderTarget { func (i *ids) renderTargetAt(id RenderTargetID) *opengl.RenderTarget {
@ -53,35 +53,35 @@ func (i *ids) renderTargetAt(id RenderTargetID) *opengl.RenderTarget {
return i.renderTargets[id] return i.renderTargets[id]
} }
func (i *ids) toTexture(id RenderTargetID) TextureID { func (i *ids) toTexture(id RenderTargetID) *Texture {
i.RLock() i.RLock()
defer i.RUnlock() defer i.RUnlock()
return i.renderTargetToTexture[id] return i.renderTargetToTexture[id]
} }
func (i *ids) createTexture(img image.Image, filter int) (TextureID, error) { func (i *ids) createTexture(img image.Image, filter int) (*Texture, error) {
texture, err := opengl.CreateTextureFromImage(img, filter) glTexture, err := opengl.CreateTextureFromImage(img, filter)
if err != nil { if err != nil {
return 0, err return nil, err
} }
i.Lock() i.Lock()
defer i.Unlock() defer i.Unlock()
i.lastID++ i.lastID++
textureID := TextureID(i.lastID) texture := &Texture{i.lastID}
i.textures[textureID] = texture i.textures[texture] = glTexture
return textureID, nil return texture, nil
} }
func (i *ids) createRenderTarget(width, height int, filter int) (RenderTargetID, error) { func (i *ids) createRenderTarget(width, height int, filter int) (RenderTargetID, error) {
texture, err := opengl.CreateTexture(width, height, filter) glTexture, err := opengl.CreateTexture(width, height, filter)
if err != nil { if err != nil {
return 0, err return 0, err
} }
// The current binded framebuffer can be changed. // The current binded framebuffer can be changed.
i.currentRenderTargetID = -1 i.currentRenderTargetID = -1
r, err := opengl.NewRenderTargetFromTexture(texture) r, err := opengl.NewRenderTargetFromTexture(glTexture)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -89,13 +89,13 @@ func (i *ids) createRenderTarget(width, height int, filter int) (RenderTargetID,
i.Lock() i.Lock()
defer i.Unlock() defer i.Unlock()
i.lastID++ i.lastID++
textureID := TextureID(i.lastID) texture := &Texture{i.lastID}
i.lastID++ i.lastID++
renderTargetID := RenderTargetID(i.lastID) renderTargetID := RenderTargetID(i.lastID)
i.textures[textureID] = texture i.textures[texture] = glTexture
i.renderTargets[renderTargetID] = r i.renderTargets[renderTargetID] = r
i.renderTargetToTexture[renderTargetID] = textureID i.renderTargetToTexture[renderTargetID] = texture
return renderTargetID, nil return renderTargetID, nil
} }
@ -116,15 +116,15 @@ func (i *ids) deleteRenderTarget(id RenderTargetID) {
defer i.Unlock() defer i.Unlock()
renderTarget := i.renderTargets[id] renderTarget := i.renderTargets[id]
textureID := i.renderTargetToTexture[id] texture := i.renderTargetToTexture[id]
texture := i.textures[textureID] glTexture := i.textures[texture]
renderTarget.Dispose() renderTarget.Dispose()
texture.Dispose() glTexture.Dispose()
delete(i.renderTargets, id) delete(i.renderTargets, id)
delete(i.renderTargetToTexture, id) delete(i.renderTargetToTexture, id)
delete(i.textures, textureID) delete(i.textures, texture)
} }
func (i *ids) fillRenderTarget(id RenderTargetID, r, g, b uint8) error { func (i *ids) fillRenderTarget(id RenderTargetID, r, g, b uint8) error {
@ -137,15 +137,15 @@ func (i *ids) fillRenderTarget(id RenderTargetID, r, g, b uint8) error {
return nil return nil
} }
func (i *ids) drawTexture(target RenderTargetID, id TextureID, parts []TexturePart, geo GeometryMatrix, color ColorMatrix) error { func (i *ids) drawTexture(target RenderTargetID, texture *Texture, parts []TexturePart, geo GeometryMatrix, color ColorMatrix) error {
texture := i.textureAt(id) glTexture := i.textureAt(texture)
if err := i.setViewportIfNeeded(target); err != nil { if err := i.setViewportIfNeeded(target); err != nil {
return err return err
} }
r := i.renderTargetAt(target) r := i.renderTargetAt(target)
projectionMatrix := r.ProjectionMatrix() projectionMatrix := r.ProjectionMatrix()
quads := textureQuads(parts, texture.Width(), texture.Height()) quads := textureQuads(parts, glTexture.Width(), glTexture.Height())
shader.DrawTexture(texture.Native(), projectionMatrix, quads, &geo, &color) shader.DrawTexture(glTexture.Native(), projectionMatrix, quads, &geo, &color)
return nil return nil
} }

View File

@ -41,11 +41,11 @@ func (c *syncGraphicsContext) Fill(r, g, b uint8) (err error) {
return return
} }
func (c *syncGraphicsContext) Texture(id TextureID) (d Drawer) { func (c *syncGraphicsContext) Texture(texture *Texture) (d Drawer) {
c.syncer.Sync(func() { c.syncer.Sync(func() {
d = &drawer{ d = &drawer{
syncer: c.syncer, syncer: c.syncer,
innerDrawer: c.innerGraphicsContext.Texture(id), innerDrawer: c.innerGraphicsContext.Texture(texture),
} }
}) })
return return

8
ui.go
View File

@ -127,13 +127,13 @@ func (u *ui) draw(f func(GraphicsContext) error) (err error) {
return return
} }
func (u *ui) newTextureID(img image.Image, filter int) (TextureID, error) { func (u *ui) newTexture(img image.Image, filter int) (*Texture, error) {
var id TextureID var texture *Texture
var err error var err error
u.use(func() { u.use(func() {
id, err = idsInstance.createTexture(img, filter) texture, err = idsInstance.createTexture(img, filter)
}) })
return id, err return texture, err
} }
func (u *ui) newRenderTargetID(width, height int, filter int) (RenderTargetID, error) { func (u *ui) newRenderTargetID(width, height int, filter int) (RenderTargetID, error) {