mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
graphics: Enable to draw unlimited number of sprites (#245)
This commit is contained in:
parent
d00eb131f4
commit
66f262c80e
@ -98,20 +98,20 @@ func (s Sprites) Src(i int) (x0, y0, x1, y1 int) {
|
||||
|
||||
const (
|
||||
MinSprites = 0
|
||||
MaxSprites = 10000
|
||||
MaxSprites = 50000
|
||||
)
|
||||
|
||||
var sprites = &Sprites{make([]*Sprite, MaxSprites), 500}
|
||||
|
||||
func update(screen *ebiten.Image) error {
|
||||
if ebiten.IsKeyPressed(ebiten.KeyLeft) {
|
||||
sprites.num -= 20
|
||||
sprites.num -= 100
|
||||
if sprites.num < MinSprites {
|
||||
sprites.num = MinSprites
|
||||
}
|
||||
}
|
||||
if ebiten.IsKeyPressed(ebiten.KeyRight) {
|
||||
sprites.num += 20
|
||||
sprites.num += 100
|
||||
if MaxSprites < sprites.num {
|
||||
sprites.num = MaxSprites
|
||||
}
|
||||
|
@ -58,41 +58,72 @@ func (q *commandQueue) Enqueue(command command) {
|
||||
q.commands = append(q.commands, command)
|
||||
}
|
||||
|
||||
func (q *commandQueue) commandGroups() [][]command {
|
||||
cs := make([]command, len(q.commands))
|
||||
copy(cs, q.commands)
|
||||
gs := [][]command{}
|
||||
quads := 0
|
||||
for 0 < len(cs) {
|
||||
if len(gs) == 0 {
|
||||
gs = append(gs, []command{})
|
||||
}
|
||||
c := cs[0]
|
||||
switch c := c.(type) {
|
||||
case *drawImageCommand:
|
||||
if maxQuads >= quads+c.quadsNum() {
|
||||
quads += c.quadsNum()
|
||||
break
|
||||
}
|
||||
cc := c.split(maxQuads - quads)
|
||||
gs[len(gs)-1] = append(gs[len(gs)-1], cc[0])
|
||||
cs[0] = cc[1]
|
||||
quads = 0
|
||||
gs = append(gs, []command{})
|
||||
continue
|
||||
}
|
||||
gs[len(gs)-1] = append(gs[len(gs)-1], c)
|
||||
cs = cs[1:]
|
||||
}
|
||||
return gs
|
||||
}
|
||||
|
||||
func (q *commandQueue) Flush(context *opengl.Context) error {
|
||||
q.m.Lock()
|
||||
defer q.m.Unlock()
|
||||
// glViewport must be called at least at every frame on iOS.
|
||||
context.ResetViewportSize()
|
||||
vertices := []int16{}
|
||||
for _, c := range q.commands {
|
||||
switch c := c.(type) {
|
||||
case *drawImageCommand:
|
||||
vertices = append(vertices, c.vertices...)
|
||||
for _, g := range q.commandGroups() {
|
||||
vertices := []int16{}
|
||||
for _, c := range g {
|
||||
switch c := c.(type) {
|
||||
case *drawImageCommand:
|
||||
vertices = append(vertices, c.vertices...)
|
||||
}
|
||||
}
|
||||
}
|
||||
if 0 < len(vertices) {
|
||||
context.BufferSubData(opengl.ArrayBuffer, vertices)
|
||||
}
|
||||
// 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.
|
||||
if maxQuads < len(vertices)/16 {
|
||||
return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", maxQuads))
|
||||
}
|
||||
numc := len(q.commands)
|
||||
indexOffsetInBytes := 0
|
||||
for _, c := range q.commands {
|
||||
if err := c.Exec(context, indexOffsetInBytes); err != nil {
|
||||
return err
|
||||
if 0 < len(vertices) {
|
||||
context.BufferSubData(opengl.ArrayBuffer, vertices)
|
||||
}
|
||||
if c, ok := c.(*drawImageCommand); ok {
|
||||
indexOffsetInBytes += 6 * len(c.vertices) / 16 * 2
|
||||
// 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.
|
||||
if maxQuads < len(vertices)/16 {
|
||||
return errors.New(fmt.Sprintf("len(quads) must be equal to or less than %d", maxQuads))
|
||||
}
|
||||
numc := len(g)
|
||||
indexOffsetInBytes := 0
|
||||
for _, c := range g {
|
||||
if err := c.Exec(context, indexOffsetInBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
if c, ok := c.(*drawImageCommand); ok {
|
||||
indexOffsetInBytes += 6 * len(c.vertices) / 16 * 2
|
||||
}
|
||||
}
|
||||
if 0 < numc {
|
||||
// Call glFlush to prevent black flicking (especially on Android (#226) and iOS).
|
||||
context.Flush()
|
||||
}
|
||||
}
|
||||
q.commands = []command{}
|
||||
if 0 < numc {
|
||||
// Call glFlush to prevent black flicking (especially on Android (#226) and iOS).
|
||||
context.Flush()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -133,7 +164,7 @@ func (c *drawImageCommand) Exec(context *opengl.Context, indexOffsetInBytes int)
|
||||
}
|
||||
context.BlendFunc(c.mode)
|
||||
|
||||
n := len(c.vertices) / 16
|
||||
n := c.quadsNum()
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
@ -156,6 +187,18 @@ func (c *drawImageCommand) Exec(context *opengl.Context, indexOffsetInBytes int)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *drawImageCommand) split(quadsNum int) [2]*drawImageCommand {
|
||||
c1 := *c
|
||||
c2 := *c
|
||||
c1.vertices = c.vertices[:quadsNum*16]
|
||||
c2.vertices = c.vertices[quadsNum*16:]
|
||||
return [2]*drawImageCommand{&c1, &c2}
|
||||
}
|
||||
|
||||
func (c *drawImageCommand) quadsNum() int {
|
||||
return len(c.vertices) / 16
|
||||
}
|
||||
|
||||
type replacePixelsCommand struct {
|
||||
dst *Image
|
||||
pixels []uint8
|
||||
|
@ -61,7 +61,6 @@ func (p *pixels) fill(clr color.Color) {
|
||||
|
||||
func (p *pixels) appendDrawImageHistory(item *drawImageHistoryItem) {
|
||||
p.drawImageHistory = append(p.drawImageHistory, item)
|
||||
// TODO: Consider the number of the vertices, which should not exceed the max number (#245).
|
||||
}
|
||||
|
||||
func (p *pixels) at(image *graphics.Image, idx int, context *opengl.Context) (color.Color, error) {
|
||||
|
Loading…
Reference in New Issue
Block a user