diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Attribute.java b/SPD-classes/src/main/java/com/watabou/glwrap/Attribute.java index ea8ab4532..9b495b25a 100644 --- a/SPD-classes/src/main/java/com/watabou/glwrap/Attribute.java +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Attribute.java @@ -48,4 +48,8 @@ public class Attribute { public void vertexPointer( int size, int stride, FloatBuffer ptr ) { GLES20.glVertexAttribPointer( location, size, GLES20.GL_FLOAT, false, stride * Float.SIZE / 8, ptr ); } + + public void vertexBuffer( int size, int stride, int offset) { + GLES20.glVertexAttribPointer( location, size, GLES20.GL_FLOAT, false, stride * Float.SIZE / 8, offset * Float.SIZE / 8 ); + } } diff --git a/SPD-classes/src/main/java/com/watabou/glwrap/Vertexbuffer.java b/SPD-classes/src/main/java/com/watabou/glwrap/Vertexbuffer.java new file mode 100644 index 000000000..de2de3815 --- /dev/null +++ b/SPD-classes/src/main/java/com/watabou/glwrap/Vertexbuffer.java @@ -0,0 +1,85 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2016 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.watabou.glwrap; + +import android.opengl.GLES20; + +import java.nio.FloatBuffer; +import java.util.ArrayList; + +public class Vertexbuffer { + + private int id; + private FloatBuffer vertices; + private boolean needsUpdate; + + private static ArrayList buffers = new ArrayList<>(); + + public Vertexbuffer( FloatBuffer vertices ) { + int[] ptr = new int[1]; + GLES20.glGenBuffers( 1, ptr, 0 ); + id = ptr[0]; + + this.vertices = vertices; + buffers.add(this); + + //forces an update so the GL data isn't blank + needsUpdate = true; + updateGLData(); + } + + public void updateVertices( FloatBuffer vertices ){ + this.vertices = vertices; + needsUpdate = true; + } + + public void updateGLData(){ + if (!needsUpdate) return; + + vertices.position(0); + bind(); + GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, (vertices.limit()*4), vertices, GLES20.GL_DYNAMIC_DRAW); + release(); + needsUpdate = false; + } + + public void bind(){ + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, id); + } + + public void release(){ + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); + } + + public void delete(){ + GLES20.glDeleteBuffers(1, new int[]{id}, 0); + buffers.remove(this); + } + + public static void refreshAllBuffers(){ + for (Vertexbuffer buf : buffers) { + buf.needsUpdate = true; + buf.updateGLData(); + } + } + +} diff --git a/SPD-classes/src/main/java/com/watabou/noosa/BitmapText.java b/SPD-classes/src/main/java/com/watabou/noosa/BitmapText.java index f1e5a7e38..fe9b71108 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/BitmapText.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/BitmapText.java @@ -27,6 +27,7 @@ import com.watabou.gltextures.SmartTexture; import com.watabou.gltextures.TextureCache; import com.watabou.glwrap.Matrix; import com.watabou.glwrap.Quad; +import com.watabou.glwrap.Vertexbuffer; import android.graphics.Bitmap; import android.graphics.RectF; @@ -38,6 +39,7 @@ public class BitmapText extends Visual { protected float[] vertices = new float[16]; protected FloatBuffer quads; + protected Vertexbuffer buffer; public int realLength; @@ -58,15 +60,6 @@ public class BitmapText extends Visual { this.font = font; } - @Override - public void destroy() { - text = null; - font = null; - vertices = null; - quads = null; - super.destroy(); - } - @Override protected void updateMatrix() { // "origin" field is ignored @@ -80,25 +73,37 @@ public class BitmapText extends Visual { public void draw() { super.draw(); + + if (dirty) { + updateVertices(); + quads.limit(quads.position()); + if (buffer == null) + buffer = new Vertexbuffer(quads); + else + buffer.updateVertices(quads); + } NoosaScript script = NoosaScript.get(); font.texture.bind(); - if (dirty) { - updateVertices(); - } - script.camera( camera() ); script.uModel.valueM4( matrix ); script.lighting( rm, gm, bm, am, ra, ga, ba, aa ); - script.drawQuadSet( quads, realLength ); + script.drawQuadSet( buffer, realLength, 0 ); } - + + @Override + public void destroy() { + super.destroy(); + if (buffer != null) + buffer.delete(); + } + protected void updateVertices() { width = 0; diff --git a/SPD-classes/src/main/java/com/watabou/noosa/Game.java b/SPD-classes/src/main/java/com/watabou/noosa/Game.java index f9f4298c3..94d964e8e 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/Game.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/Game.java @@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10; import com.watabou.glscripts.Script; import com.watabou.gltextures.TextureCache; +import com.watabou.glwrap.Vertexbuffer; import com.watabou.input.Keys; import com.watabou.input.Touchscreen; import com.watabou.noosa.audio.Music; @@ -242,9 +243,11 @@ public class Game extends Activity implements GLSurfaceView.Renderer, View.OnTou GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA ); GLES20.glEnable( GL10.GL_SCISSOR_TEST ); - + + //refreshes texture and vertex data stored on the gpu TextureCache.reload(); RenderedText.reloadCache(); + Vertexbuffer.refreshAllBuffers(); } protected void destroyGame() { diff --git a/SPD-classes/src/main/java/com/watabou/noosa/Image.java b/SPD-classes/src/main/java/com/watabou/noosa/Image.java index 356449687..46994522f 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/Image.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/Image.java @@ -28,6 +28,7 @@ import android.graphics.RectF; import com.watabou.gltextures.TextureCache; import com.watabou.gltextures.SmartTexture; import com.watabou.glwrap.Quad; +import com.watabou.glwrap.Vertexbuffer; public class Image extends Visual { @@ -39,6 +40,7 @@ public class Image extends Visual { protected float[] vertices; protected FloatBuffer verticesBuffer; + protected Vertexbuffer buffer; protected boolean dirty; @@ -149,6 +151,16 @@ public class Image extends Visual { super.draw(); + if (dirty) { + verticesBuffer.position( 0 ); + verticesBuffer.put( vertices ); + if (buffer == null) + buffer = new Vertexbuffer( verticesBuffer ); + else + buffer.updateVertices( verticesBuffer ); + dirty = false; + } + NoosaScript script = NoosaScript.get(); texture.bind(); @@ -159,13 +171,15 @@ public class Image extends Visual { script.lighting( rm, gm, bm, am, ra, ga, ba, aa ); - - if (dirty) { - verticesBuffer.position( 0 ); - verticesBuffer.put( vertices ); - dirty = false; - } - script.drawQuad( verticesBuffer ); + + script.drawQuad( buffer ); } + + @Override + public void destroy() { + super.destroy(); + if (buffer != null) + buffer.delete(); + } } diff --git a/SPD-classes/src/main/java/com/watabou/noosa/NinePatch.java b/SPD-classes/src/main/java/com/watabou/noosa/NinePatch.java index aaa369c98..26a060a00 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/NinePatch.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/NinePatch.java @@ -26,6 +26,7 @@ import java.nio.FloatBuffer; import com.watabou.gltextures.SmartTexture; import com.watabou.gltextures.TextureCache; import com.watabou.glwrap.Quad; +import com.watabou.glwrap.Vertexbuffer; import android.graphics.RectF; @@ -34,7 +35,8 @@ public class NinePatch extends Visual { public SmartTexture texture; protected float[] vertices; - protected FloatBuffer verticesBuffer; + protected FloatBuffer quads; + protected Vertexbuffer buffer; protected RectF outterF; protected RectF innerF; @@ -49,6 +51,8 @@ public class NinePatch extends Visual { protected boolean flipHorizontal; protected boolean flipVertical; + + protected boolean dirty; public NinePatch( Object tx, int margin ) { this( tx, margin, margin, margin, margin ); @@ -73,7 +77,7 @@ public class NinePatch extends Visual { nHeight = height = h; vertices = new float[16]; - verticesBuffer = Quad.createSet( 9 ); + quads = Quad.createSet( 9 ); marginLeft = left; marginRight = right; @@ -88,7 +92,7 @@ public class NinePatch extends Visual { protected void updateVertices() { - verticesBuffer.position( 0 ); + quads.position( 0 ); float right = width - marginRight; float bottom = height - marginBottom; @@ -105,33 +109,35 @@ public class NinePatch extends Visual { Quad.fill( vertices, 0, marginLeft, 0, marginTop, outleft, inleft, outtop, intop ); - verticesBuffer.put( vertices ); + quads.put( vertices ); Quad.fill( vertices, marginLeft, right, 0, marginTop, inleft, inright, outtop, intop ); - verticesBuffer.put( vertices ); + quads.put( vertices ); Quad.fill( vertices, right, width, 0, marginTop, inright, outright, outtop, intop ); - verticesBuffer.put( vertices ); + quads.put( vertices ); Quad.fill( vertices, 0, marginLeft, marginTop, bottom, outleft, inleft, intop, inbottom ); - verticesBuffer.put( vertices ); + quads.put( vertices ); Quad.fill( vertices, marginLeft, right, marginTop, bottom, inleft, inright, intop, inbottom ); - verticesBuffer.put( vertices ); + quads.put( vertices ); Quad.fill( vertices, right, width, marginTop, bottom, inright, outright, intop, inbottom ); - verticesBuffer.put( vertices ); + quads.put( vertices ); Quad.fill( vertices, 0, marginLeft, bottom, height, outleft, inleft, inbottom, outbottom ); - verticesBuffer.put( vertices ); + quads.put( vertices ); Quad.fill( vertices, marginLeft, right, bottom, height, inleft, inright, inbottom, outbottom ); - verticesBuffer.put( vertices ); + quads.put( vertices ); Quad.fill( vertices, right, width, bottom, height, inright, outright, inbottom, outbottom ); - verticesBuffer.put( vertices ); + quads.put( vertices ); + + dirty = true; } public int marginLeft() { @@ -195,6 +201,14 @@ public class NinePatch extends Visual { super.draw(); + if (dirty){ + if (buffer == null) + buffer = new Vertexbuffer(quads); + else + buffer.updateVertices(quads); + dirty = false; + } + NoosaScript script = NoosaScript.get(); texture.bind(); @@ -206,7 +220,14 @@ public class NinePatch extends Visual { rm, gm, bm, am, ra, ga, ba, aa ); - script.drawQuadSet( verticesBuffer, 9 ); + script.drawQuadSet( buffer, 9, 0 ); } + + @Override + public void destroy() { + super.destroy(); + if (buffer != null) + buffer.delete(); + } } diff --git a/SPD-classes/src/main/java/com/watabou/noosa/NoosaScript.java b/SPD-classes/src/main/java/com/watabou/noosa/NoosaScript.java index 36392015b..a59e5a558 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/NoosaScript.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/NoosaScript.java @@ -30,6 +30,7 @@ import com.watabou.glscripts.Script; import com.watabou.glwrap.Attribute; import com.watabou.glwrap.Quad; import com.watabou.glwrap.Uniform; +import com.watabou.glwrap.Vertexbuffer; public class NoosaScript extends Script { @@ -96,6 +97,20 @@ public class NoosaScript extends Script { GLES20.glDrawElements( GLES20.GL_TRIANGLES, Quad.SIZE, GLES20.GL_UNSIGNED_SHORT, 0 ); } + + public void drawQuad( Vertexbuffer buffer ) { + + buffer.updateGLData(); + + buffer.bind(); + + aXY.vertexBuffer( 2, 4, 0 ); + aUV.vertexBuffer( 2, 4, 2 ); + + buffer.release(); + + GLES20.glDrawElements( GLES20.GL_TRIANGLES, Quad.SIZE, GLES20.GL_UNSIGNED_SHORT, 0 ); + } public void drawQuadSet( FloatBuffer vertices, int size ) { @@ -112,6 +127,24 @@ public class NoosaScript extends Script { GLES20.glDrawElements( GLES20.GL_TRIANGLES, Quad.SIZE * size, GLES20.GL_UNSIGNED_SHORT, 0 ); } + + public void drawQuadSet( Vertexbuffer buffer, int length, int offset ){ + + if (length == 0) { + return; + } + + buffer.updateGLData(); + + buffer.bind(); + + aXY.vertexBuffer( 2, 4, 0 ); + aUV.vertexBuffer( 2, 4, 2 ); + + buffer.release(); + + GLES20.glDrawElements( GLES20.GL_TRIANGLES, Quad.SIZE * length, GLES20.GL_UNSIGNED_SHORT, Quad.SIZE * offset ); + } public void lighting( float rm, float gm, float bm, float am, float ra, float ga, float ba, float aa ) { uColorM.value4f( rm, gm, bm, am ); diff --git a/SPD-classes/src/main/java/com/watabou/noosa/Tilemap.java b/SPD-classes/src/main/java/com/watabou/noosa/Tilemap.java index 029b0bcff..72acf3bcb 100644 --- a/SPD-classes/src/main/java/com/watabou/noosa/Tilemap.java +++ b/SPD-classes/src/main/java/com/watabou/noosa/Tilemap.java @@ -26,6 +26,7 @@ import java.nio.FloatBuffer; import com.watabou.gltextures.SmartTexture; import com.watabou.gltextures.TextureCache; import com.watabou.glwrap.Quad; +import com.watabou.glwrap.Vertexbuffer; import com.watabou.utils.Rect; import android.graphics.RectF; @@ -47,6 +48,7 @@ public class Tilemap extends Visual { protected short[] bufferPositions; protected short bufferLength; protected FloatBuffer quads; + protected Vertexbuffer buffer; public Rect updated; @@ -96,7 +98,6 @@ public class Tilemap extends Visual { float x2 = x1 + cellW; int pos = i * mapWidth + updated.left; - quads.position( 16 * pos ); for (int j=updated.left; j < updated.right; j++) { @@ -155,6 +156,15 @@ public class Tilemap extends Visual { super.draw(); + if (!updated.isEmpty()) { + updateVertices(); + quads.limit(bufferLength*16); + if (buffer == null) + buffer = new Vertexbuffer(quads); + else + buffer.updateVertices(quads); + } + NoosaScript script = NoosaScript.get(); texture.bind(); @@ -164,17 +174,18 @@ public class Tilemap extends Visual { rm, gm, bm, am, ra, ga, ba, aa ); - if (!updated.isEmpty()) { - quads.limit(quads.capacity()); - updateVertices(); - quads.limit(bufferLength); - } - script.camera( camera ); - script.drawQuadSet( quads, bufferLength ); + script.drawQuadSet( buffer, bufferLength, 0 ); } + @Override + public void destroy() { + super.destroy(); + if (buffer != null) + buffer.delete(); + } + protected boolean needsRender(int pos){ return true; }