diff --git a/internal/graphics/command.go b/internal/graphics/command.go index 136ff2097..0f7dbc2a7 100644 --- a/internal/graphics/command.go +++ b/internal/graphics/command.go @@ -15,6 +15,8 @@ package graphics import ( + "errors" + "fmt" "image/color" "math" @@ -26,7 +28,8 @@ type command interface { } type commandQueue struct { - commands []command + commands []command + indexOffsetInBytes int } var theCommandQueue = &commandQueue{ @@ -38,7 +41,18 @@ func (q *commandQueue) Enqueue(command command) { } func (q *commandQueue) Flush(context *opengl.Context) error { - // TODO: Do optimizing before executing + q.indexOffsetInBytes = 0 + vertices := []int16{} + for _, c := range q.commands { + switch c := c.(type) { + case *drawImageCommand: + vertices = append(vertices, c.vertices...) + } + } + // TODO: Check if len(vertices) is too big + if 0 < len(vertices) { + context.BufferSubData(context.ArrayBuffer, vertices) + } for _, c := range q.commands { if err := c.Exec(context); err != nil { return err @@ -79,8 +93,34 @@ func (c *drawImageCommand) Exec(context *opengl.Context) error { if err := c.dst.setAsViewport(context); err != nil { return err } - p := c.dst.projectionMatrix() - return drawTexture(context, c.src.native, p, c.vertices, c.geo, c.color, c.mode) + context.BlendFunc(c.mode) + + // NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far. + // Let's use them to compare to len(quads) in the future. + n := len(c.vertices) / 16 + if n == 0 { + return nil + } + if MaxQuads < n/16 { + return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", MaxQuads)) + } + + p := programContext{ + state: &theOpenGLState, + program: theOpenGLState.programTexture, + context: context, + projectionMatrix: glMatrix(c.dst.projectionMatrix()), + texture: c.src.native, + geoM: c.geo, + colorM: c.color, + } + p.begin() + defer p.end() + // TODO: We should call glBindBuffer here? + // The buffer is already bound at begin() but it is counterintuitive. + context.DrawElements(context.Triangles, 6*n, theCommandQueue.indexOffsetInBytes) + theCommandQueue.indexOffsetInBytes += 6 * n * 2 + return nil } type replacePixelsCommand struct { diff --git a/internal/graphics/draw.go b/internal/graphics/draw.go index e58e537b4..707c1bbb7 100644 --- a/internal/graphics/draw.go +++ b/internal/graphics/draw.go @@ -14,13 +14,6 @@ package graphics -import ( - "errors" - "fmt" - - "github.com/hajimehoshi/ebiten/internal/graphics/opengl" -) - func glMatrix(m *[4][4]float64) []float32 { return []float32{ float32(m[0][0]), float32(m[1][0]), float32(m[2][0]), float32(m[3][0]), @@ -33,35 +26,3 @@ func glMatrix(m *[4][4]float64) []float32 { type Matrix interface { Element(i, j int) float64 } - -func drawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4][4]float64, vertices []int16, geo Matrix, color Matrix, mode opengl.CompositeMode) error { - c.BlendFunc(mode) - - // NOTE: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far. - // Let's use them to compare to len(quads) in the future. - n := len(vertices) / 16 - if n == 0 { - return nil - } - if MaxQuads < n/16 { - return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", MaxQuads)) - } - - p := programContext{ - state: &theOpenGLState, - program: theOpenGLState.programTexture, - context: c, - projectionMatrix: glMatrix(projectionMatrix), - texture: texture, - geoM: geo, - colorM: color, - } - p.begin() - defer p.end() - // TODO: We should call glBindBuffer here? - // The buffer is already bound at begin() but it is counterintuitive. - c.BufferSubData(c.ArrayBuffer, vertices) - c.DrawElements(c.Triangles, 6*n) - - return nil -} diff --git a/internal/graphics/opengl/context_desktop.go b/internal/graphics/opengl/context_desktop.go index 0e7a31593..ec53192bf 100644 --- a/internal/graphics/opengl/context_desktop.go +++ b/internal/graphics/opengl/context_desktop.go @@ -438,9 +438,9 @@ func (c *Context) DeleteBuffer(b Buffer) { }) } -func (c *Context) DrawElements(mode Mode, len int) { +func (c *Context) DrawElements(mode Mode, len int, offsetInBytes int) { c.RunOnContextThread(func() error { - gl.DrawElements(uint32(mode), int32(len), gl.UNSIGNED_SHORT, gl.PtrOffset(0)) + gl.DrawElements(uint32(mode), int32(len), gl.UNSIGNED_SHORT, gl.PtrOffset(offsetInBytes)) return nil }) } diff --git a/internal/graphics/opengl/context_js.go b/internal/graphics/opengl/context_js.go index ccee910fd..3bd9b836c 100644 --- a/internal/graphics/opengl/context_js.go +++ b/internal/graphics/opengl/context_js.go @@ -356,7 +356,7 @@ func (c *Context) DeleteBuffer(b Buffer) { gl.DeleteBuffer(b.Object) } -func (c *Context) DrawElements(mode Mode, len int) { +func (c *Context) DrawElements(mode Mode, len int, offsetInBytes int) { gl := c.gl - gl.DrawElements(int(mode), len, gl.UNSIGNED_SHORT, 0) + gl.DrawElements(int(mode), len, gl.UNSIGNED_SHORT, offsetInBytes) } diff --git a/internal/graphics/opengl/context_mobile.go b/internal/graphics/opengl/context_mobile.go index a7fdf572c..a1d191131 100644 --- a/internal/graphics/opengl/context_mobile.go +++ b/internal/graphics/opengl/context_mobile.go @@ -359,7 +359,7 @@ func (c *Context) DeleteBuffer(b Buffer) { gl.DeleteBuffer(mgl.Buffer(b)) } -func (c *Context) DrawElements(mode Mode, len int) { +func (c *Context) DrawElements(mode Mode, len int, offsetInBytes int) { gl := c.gl - gl.DrawElements(mgl.Enum(mode), len, mgl.UNSIGNED_SHORT, 0) + gl.DrawElements(mgl.Enum(mode), len, mgl.UNSIGNED_SHORT, offsetInBytes) }