1 module prova.graphics.sprites.spritebatch; 2 3 import prova.graphics, 4 prova.math, 5 prova.util, 6 std.typecons; 7 8 /// 9 final class SpriteBatch 10 { 11 static ShaderProgram defaultShaderProgram; 12 /// Copy of defaultShaderProgram 13 ShaderProgram shaderProgram; 14 private bool begun; 15 private Mesh mesh; 16 private RenderTarget renderTarget; 17 private Matrix projection; 18 private LinkedList!(Tuple!(Sprite, Matrix)) sprites; 19 20 /// 21 this() 22 { 23 if(!defaultShaderProgram) 24 defaultShaderProgram = new SpriteShaderProgram(); 25 26 shaderProgram = defaultShaderProgram; 27 28 sprites = new LinkedList!(Tuple!(Sprite, Matrix)); 29 30 mesh = new SpriteMesh(); 31 } 32 33 /// 34 void begin(RenderTarget renderTarget, Matrix projection) 35 { 36 if(begun) 37 throw new Exception("Batch already started"); 38 39 this.renderTarget = renderTarget; 40 this.projection = projection; 41 begun = true; 42 } 43 44 /// 45 void batchSprite(AnimatedSprite sprite, Matrix transform) 46 { 47 sprite.update(); 48 49 batchSprite(cast(Sprite) sprite, transform); 50 } 51 52 /// 53 void batchSprite(Sprite sprite, Matrix transform) 54 { 55 if(!begun) 56 throw new Exception("Batch not started"); 57 58 sprites.insertBack(tuple(sprite, transform)); 59 } 60 61 /// Draws batched sprites 62 void end() 63 { 64 if(!begun) 65 throw new Exception("Batch not started"); 66 67 Color lastTint; 68 uint lastTexture = -1; 69 70 // set the inital value for the tint 71 shaderProgram.setVector4("tint", lastTint); 72 73 foreach(Tuple!(Sprite, Matrix) spriteTuple; sprites) { 74 Sprite sprite = spriteTuple[0]; 75 Matrix transform = spriteTuple[1]; 76 77 if(sprite.texture.id != lastTexture) { 78 shaderProgram.setTexture(0, sprite.texture); 79 lastTexture = sprite.texture.id; 80 } 81 82 if(sprite.tint != lastTint) { 83 shaderProgram.setVector4("tint", sprite.tint); 84 lastTint = sprite.tint; 85 } 86 87 drawSprite(sprite, transform); 88 } 89 90 sprites.clear(); 91 begun = false; 92 } 93 94 /// 95 void drawSprite(Sprite sprite, Matrix transform) 96 { 97 Vector2 size = sprite.clip.getSize(); 98 Vector3 center = size / 2; 99 100 Rect clip; 101 clip.left = sprite.clip.left / sprite.texture.width; 102 clip.top = 1 - (sprite.clip.top + sprite.clip.height) / sprite.texture.height; 103 clip.width = sprite.clip.width / sprite.texture.width; 104 clip.height = sprite.clip.height / sprite.texture.height; 105 106 Matrix offset = Matrix.identity; 107 offset = offset.scale(size); 108 offset = offset.translate(-sprite.origin - center); 109 110 shaderProgram.setMatrix("transform", projection * (transform * offset)); 111 shaderProgram.setVector4("clip", clip); 112 shaderProgram.drawMesh(mesh, renderTarget, DrawMode.TRIANGLE_FAN); 113 } 114 }